Comments (4)
Can be somewhat reproduced on stable with
pub fn into_vec<'inner>(dummy: impl FromRow<'inner>) {
let _f = dummy.prepare();
}
pub fn test() {
into_vec(Assume(Some("test")));
}
pub trait FromRow<'t> {
type Out<'a>;
fn prepare(self) -> impl for<'a> FnMut(&'a ()) -> Self::Out<'a>;
}
impl<'t, T: Value<'t>> FromRow<'t> for T
where
<T as Value<'t>>::Typ: MyTyp,
{
type Out<'a> = <T::Typ as MyTyp>::Out<'a>;
fn prepare(self) -> impl for<'a> FnMut(&'a ()) -> Self::Out<'a> {
move |_| loop {}
}
}
pub struct Assume<A>(pub(crate) A);
impl<'t, T, A: Value<'t, Typ = Option<T>>> Value<'t> for Assume<A> {
type Typ = T;
}
pub trait Value<'t> {
type Typ;
}
impl<'t> Value<'t> for &str {
type Typ = String;
}
impl<'t, T: Value<'t, Typ = X>, X: MyTyp> Value<'t> for Option<T> {
type Typ = Option<T::Typ>;
}
pub trait MyTyp: 'static {
type Out<'t>;
}
impl MyTyp for String {
type Out<'t> = Self;
}
giving
WARN rustc_codegen_ssa::mir::locals Unexpected initial operand type: expected Closure(DefId(0:19 ~ unnamed_1[0fad]::{impl#0}::prepare::{closure#0}), [ReErased, Assume<s
td::option::Option<&ReErased str>>, i16, Binder(extern "RustCall" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) (),)) -> Alias(Projection, AliasT
y { args: [std::string::String, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon })], def_id: DefId(0:41 ~ unnamed_1[0fad]::MyTyp::Out) }), [Region(BrAnon)]
), ()]), found Closure(DefId(0:19 ~ unnamed_1[0fad]::{impl#0}::prepare::{closure#0}), [ReErased, Assume<std::option::Option<&ReErased str>>, i16, Binder(extern "RustCal
l" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) (),)) -> std::string::String, [Region(BrAnon)]), ()]).See <https://github.com/rust-lang/rust/iss
ues/114858>.
(but no ICE)
warning links to #114858 and seems related although the setup is very different
It seems like this is a bug in normalization somewhere, but this specific ICE happens as part of getting debug info for types. So, building in release (or rather, without debug info) actually prevents the ICE but then still hits the same warning.
from rust.
So in that sense (last part of last comment) this ICE was technically introduced by #127995 though the root cause is certainly not that and seems to be the same as #114858
from rust.
Slightly reduced:
fn into_vec(dummy: impl FromRow) {
let _f = dummy.prepare();
}
pub fn test() {
into_vec(Assume(()));
}
trait FromRow {
type Out<'a>;
fn prepare(self) -> impl for<'a> FnMut(&'a ()) -> Self::Out<'a>;
}
impl<T: Value<Typ: MyTyp>> FromRow for T {
type Out<'a> = <T::Typ as MyTyp>::Out<'a>;
fn prepare(self) -> impl for<'a> FnMut(&'a ()) -> Self::Out<'a> {
|_| loop {}
}
}
struct Assume<A>(A);
impl<T, A: Value<Typ = T>> Value for Assume<A> {
type Typ = T;
}
trait Value {
type Typ;
}
impl Value for () {
type Typ = ();
}
trait MyTyp {
type Out<'t>;
}
impl MyTyp for () {
type Out<'t> = ();
}
from rust.
So I had my own smaller reproducer, but still bigger than @cyrgani. However, after seeing theirs, I minimized it further similar to @cyrgani's version, except some of my comments might be useful. They're based on tracing the right parts of the compiler:
pub struct Wrapper<T>(T);
struct Struct;
pub trait TraitA {
// NEEDS TO BE GAT
type AssocA<'t>;
}
pub trait TraitB {
type AssocB;
}
pub fn helper(v: impl MethodTrait) {
// monomorphization instantiates something it then normalizes to:
//
// Closure(
// DefId(0:27 ~ unnamed_1[00e7]::{impl#0}::method::{closure#0}),
// [
// Wrapper1<StructX>,
// i16,
// Binder {
// value: extern "RustCall" fn((&'^0 (),)) -> Alias(Projection, AliasTy { args: [StructX, '^0], def_id: DefId(0:10 ~ unnamed_1[00e7]::TraitA::AssocA), .. }),
// bound_vars: [Region(BrAnon)]
// },
// ()
// ]
// ),
//
// This should be completely normalized but isn't.
// so, normalizing again gives (StructX is inserted) for
// Alias(Projection, AliasTy { args: [StructX, '^0], def_id: DefId(0:10 ~ unnamed_1[00e7]::TraitA::AssocA), .. })
//
// Closure(
// DefId(0:27 ~ unnamed_1[00e7]::{impl#0}::method::{closure#0}),
// [
// Wrapper1<StructX>,
// i16,
// Binder {
// value: extern "RustCall" fn((&'^0 (),)) -> StructX, bound_vars: [Region(BrAnon)]
// },
// ()
// ]
// ).
let _local_that_causes_ice = v.method();
}
pub fn main() {
helper(Wrapper(Struct));
}
pub trait MethodTrait {
type Assoc<'a>;
fn method(self) -> impl for<'a> FnMut(&'a ()) -> Self::Assoc<'a>;
}
impl<T: TraitB> MethodTrait for T
where
<T as TraitB>::AssocB: TraitA,
{
type Assoc<'a> = <T::AssocB as TraitA>::AssocA<'a>;
// must be a method (through Self), the example below doesn't work (as a standalone function)
// fn helper2<M: MethodTrait>(_v: M) -> impl for<'a> FnMut(&'a ()) -> M::Assoc<'a> {
// move |_| loop {}
// }
fn method(self) -> impl for<'a> FnMut(&'a ()) -> Self::Assoc<'a> {
move |_| loop {}
}
}
impl<T, B> TraitB for Wrapper<B>
where
B: TraitB<AssocB = T>,
{
type AssocB = T;
}
impl TraitB for Struct {
type AssocB = Struct;
}
impl TraitA for Struct {
type AssocA<'t> = Self;
}
So the specific ICE, like I said before, is essentially unrelated. It's because some debug assertion got changed into an actual assertion here. The problem is actually easier to see when you don't look at this assertion, but wait until the same root cause causes a warning later in the compiler when a sanity check is done here.
What's going on is that the warning triggers when the initialization of a MIR local doesn't match the type of its declaration. In this case we're talking about a ZST function item, and in that codepath, to get the type of the function item at the declaration site, the declaration type is monomorphized, and then layout_of
is used. Both monomorphize
and layout_of
normalize, so the type is normalized twice.
However, to check for the warning the type is only monomorphized, causing only one normalization: here
As I show in my comment in the code example, the monomorphized type normalized once gives:
Closure(
DefId(0:27 ~ unnamed_1[00e7]::{impl#0}::method::{closure#0}),
[
Wrapper1<StructX>,
i16,
Binder {
value: extern "RustCall" fn((&'^0 (),)) -> Alias(Projection, AliasTy { args: [StructX, '^0], def_id: DefId(0:10 ~ unnamed_1[00e7]::TraitA::AssocA), .. }),
bound_vars: [Region(BrAnon)]
},
()
]
),
and the second normalization gives:
Closure(
DefId(0:27 ~ unnamed_1[00e7]::{impl#0}::method::{closure#0}),
[
Wrapper1<StructX>,
i16,
Binder {
value: extern "RustCall" fn((&'^0 (),)) -> StructX, bound_vars: [Region(BrAnon)]
},
()
]
)
which, notably, is different!
For some reason the first normalization round, rust is happy to normalize to something still containing a Projection which is normalized away in round two.
In the assertion that causes the ICE, essentially the same happens. The compiler sees if normalizing is idempotent and doesn't change the type anymore, but it still does.
from rust.
Related Issues (20)
- Tracking Issue for `lazy_get`
- [ICE] adding a def'n for node-id NodeId(130468) and def kind AnonConst but a previous def'n exists HOT 3
- #[inline(never)] does not work for async functions HOT 3
- `unreachable_patterns` fires on match arm that can't be removed. HOT 3
- Compiler doesn't realize that all match cases are covered HOT 3
- Error message suggests to use a Box to wrap dyn Trait when it's unnecessary
- Compiler can't infer &str type when &String is inserted first in a collection with tuples HOT 1
- Integer literal type inference causes weird behavior including strange compiler diagnostic (but the suggestion is working).
- `dylib-soname` run-make test is not language independant HOT 3
- Add some docs for tidy
- Tracking Issue for unbounded_shifts
- rust-analyzer compiler error (not issue with code) HOT 2
- Closure Fn* trait coercion removes other implementable Fn* traits HOT 3
- run-make: fix `run_make_support::fs::create_symlink` API and audit symlink usages in rmake.rs tests
- run-make: audit tests that codegen for specific targets
- Tracking Issue for `new_zeroed_alloc`
- Tracking Issue for `box_uninit_write`
- wasip2 uses wasi:random/random to generate hashmap_random_keys
- `refining_impl_trait` suggestion in invalid code
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rust.