struct Foo<T>(T); // `T` is covariant.
fn foo<'b>(x: Foo<for<'a> fn(&'a ())>) {
let Foo(y): Foo<fn(&'b ())> = x;
}
fn main() {}
should compile but errors with
error[E0308]: mismatched types
--> src/main.rs:4:13
|
4 | let Foo(y): Foo<fn(&'b ())> = x;
| ^ one type is more general than the other
|
= note: expected fn pointer `for<'a> fn(&'a ())`
found fn pointer `fn(&())`
looking at the mir of foo it becomes clear why that happens:
fn foo(_1: Foo<for<'a> fn(&'a ())>) -> () {
debug x => _1; // in scope 0 at src/main.rs:3:12: 3:13
let mut _0: (); // return place in scope 0 at src/main.rs:3:40: 3:40
let _2: fn(&()) as UserTypeProjection { base: UserType(0), projs: [Field(field[0], ())] }; // in scope 0 at src/main.rs:4:13: 4:14
scope 1 {
debug y => _2; // in scope 1 at src/main.rs:4:13: 4:14
}
bb0: {
AscribeUserType(_1, +, UserTypeProjection { base: UserType(1), projs: [] }); // scope 0 at src/main.rs:4:17: 4:32
StorageLive(_2); // scope 0 at src/main.rs:4:13: 4:14
_2 = (_1.0: fn(&())); // scope 0 at src/main.rs:4:13: 4:14
_0 = const (); // scope 0 at src/main.rs:3:40: 5:2
StorageDead(_2); // scope 0 at src/main.rs:5:1: 5:2
return; // scope 0 at src/main.rs:5:2: 5:2
}
}
notice that in _2 = (_1.0: fn(&())); the type of _1.0 is actually for<'a> fn(&'a ()).
Possible ways to fix this are:
- correctly deal with subtyping when sanitizing field projections, note that they cannot just always be covariant.
- change the type of the field to be the actual one during mir building, so that subtyping actually happens at the assignment
always lazily recompute the type of the field instead of storing it in the mir
should compile but errors with
looking at the mir of
fooit becomes clear why that happens:notice that in
_2 = (_1.0: fn(&()));the type of_1.0is actuallyfor<'a> fn(&'a ()).Possible ways to fix this are:
always lazily recompute the type of the field instead of storing it in the mir