I'm getting a lifetime error with Rust 1.14 due to using an associated type, demonstrated by the following two similar programs, the first which compiles without error and the second which has the lifetime error.
Program #1 — compiles without error
trait Trait<'a> {
type T;
}
struct Impl;
impl<'a> Trait<'a> for Impl {
type T = std::marker::PhantomData<&'a ()>;
}
struct Alpha<'a, T: Trait<'a>> {
_dummy: std::marker::PhantomData<(&'a (), T)>,
}
fn use_alpha<'a>(_: &'a Alpha<'a, Impl>) {}
fn main() {
for x in Vec::<Alpha<Impl>>::new().into_iter() {
use_alpha(&x); // <-- ok
}
}
Program #2 — has the lifetime error
trait Trait<'a> {
type T;
}
struct Impl;
impl<'a> Trait<'a> for Impl {
type T = std::marker::PhantomData<&'a ()>;
}
struct Alpha<'a, T: Trait<'a>> {
_dummy: std::marker::PhantomData<(&'a (), T::T)>,
}
fn use_alpha<'a>(_: &'a Alpha<'a, Impl>) {}
fn main() {
for x in Vec::<Alpha<Impl>>::new().into_iter() {
use_alpha(&x); // <-- !error!
}
}
Here's the compile-time error for the second program:
error: `x` does not live long enough
--> src/main.rs:20:5
|
19 | use_alpha(&x); // <-- !error!
| - borrow occurs here
20 | }
| ^ `x` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created
Here's the diff for the two programs:
#[derive(Clone)]
struct Alpha<'a, T: Trait<'a>> {
- _dummy: std::marker::PhantomData<(&'a (), T)>,
+ _dummy: std::marker::PhantomData<(&'a (), T::T)>,
}
The only difference is that by changing the first program to use an associated type instead of the type parameter in the struct
definition, a lifetime error occurs. I have no idea why this happens. As far as I can tell, the associated type should not incur any additional lifetime restrictions—it's all just 'a
, but clearly the Rust compiler disagrees.
If I replace iteration in the second program's main
function with simple instantiation, then the lifetime error goes away. That is:
fn main() {
let x = Alpha::<Impl> { _dummy: std::marker::PhantomData };
use_alpha(&x); // <-- ok in both programs
}
I don't understand why iteration is any different than direct instantiation.
iter()
instead ofinto_iter()
and it will work. – Peter Hall