Description
We tried to build some more complex traits and this lead to a situation where the compiler would refuse to compile the trait implementation for a certain type. The reason for this turned out to be that an embedded unsafe cell somewhere deep inside the type made it invariant.
Here is an example of this:
use std::cell::UnsafeCell;
use std::rc::Rc;
type Invariant<T> = UnsafeCell<T>;
type Covariant<T> = T;
//type Wrapper<T> = Invariant<T>;
type Wrapper<T> = Covariant<T>;
trait AsSelf<'slf> {
type Ref: ?Sized;
fn as_self(&'slf self) -> &Self::Ref;
}
struct Foo<'a>(Wrapper<&'a str>);
impl<'slf, 'd: 'slf> AsSelf<'slf> for Foo<'d> {
type Ref = Foo<'slf>;
fn as_self(&'slf self) -> &Self::Ref {
self
}
}
This compiles, but if Wrapper<T>
is changed to the Invariant version, then it refuses to compile with this error:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'slf` due to conflicting requirements
--> src/lib.rs:21:42
|
21 | fn as_self(&'slf self) -> &Self::Ref {
| __________________________________________^
22 | | self
23 | | }
| |_____^
|
note: first, the lifetime cannot outlive the lifetime 'slf as defined on the impl at 18:6...
--> src/lib.rs:18:6
|
18 | impl<'slf, 'd: 'slf> AsSelf<'slf> for Foo<'d> {
| ^^^^
= note: ...so that the types are compatible:
expected AsSelf<'slf>
found AsSelf<'_>
note: but, the lifetime must be valid for the lifetime 'd as defined on the impl at 18:12...
--> src/lib.rs:18:12
|
18 | impl<'slf, 'd: 'slf> AsSelf<'slf> for Foo<'d> {
| ^^
= note: ...so that the expression is assignable:
expected &'slf Foo<'_>
found &'slf Foo<'d>
error: aborting due to previous error
This is a pretty gnarly situation one finds itself in because a) the compiler says rustc --explain E0495
but there is no extended help for E0495 and b) the actual problem here is rooted in variance and subtyping and not necessarily lifetimes as such. Would it be possible to indicate that the compiler considers Wrapper<T>
invariant because it contains an UnsafeCell<T>
(or &mut T
) and maybe even where and link to the variance docs? This would help tremendously understanding what's happening here.