Trait Solver 4 @BoxyUwU @WaffleLapkin
Warning: this quiz is still "work-in-progress", some questions might not have good explanations (or any at all), formatting/structure/titles/etc are not final, and so on. You might want to return here on a later date.
trait A<'a> {
type Assoc;
}
trait B {}
fn f(_: impl for<'a> A<'a, Assoc = impl B + 'a>) {}
impl<'a> A<'a> for () {
type Assoc = &'a u8;
}
impl B for &u8 {}
fn main() {
f(());
}
Solution
error: `impl Trait` can only mention lifetimes from an fn or impl
--> examples/trait_solver_4.rs:7:45
|
7 | fn f(_: impl for<'a> A<'a, Assoc = impl B + 'a>) {}
| -- lifetime declared here ^^
error[E0308]: mismatched types
--> examples/trait_solver_4.rs:16:5
|
16 | f(());
| ^^^^^ one type is more general than the other
|
= note: expected reference `&'a _`
found reference `&_`
note: the lifetime requirement is introduced here
--> examples/trait_solver_4.rs:7:28
|
7 | fn f(_: impl for<'a> A<'a, Assoc = impl B + 'a>) {}
| ^^^^^^^^^^^^^^^^^^^
For more information about this error, try `rustc --explain E0308`.
error: could not compile `code` (example "trait_solver_4") due to 2 previous errors
The impl
s are turned into generic parameters on the function (O
for the outer impl A
, I
for the inner impl B
).
fn f<O, I>(_: O)
where
O: for<'a> A<'a, Assoc = I>,
I: B + 'a,
{}
When looked at like this, it can be seen that the 'a
in I: B + 'a
doesn't actually exist.
It is supposed to come from the O: for<'a>
bound, but that's a separate bound.
So the I
bound cannot name 'a
, which is why this does not compile.
This is why nested argument-position-impl-trait can sometimes inhibit confusing behavior.
To make this example compile, you can use newly-stabilized associated type bounds instead of an impl trait.
As the Assoc: B + 'a
is part of the bound on the generic parameter, it can name the higher-ranked 'a
.
fn f(_: impl for<'a> A<'a, Assoc: B + 'a>) {}