简体   繁体   中英

Why does the compiler infer different lifetimes for a trait and its implementation?

I'm currently using rustlearn to evaluate different classification models. The problem I ran into basically boils down to this:

trait Foo<T> {
    fn bar(&self, x: T);
}

struct Baz;

struct Smth;

impl<'a> Foo<&'a Smth> for Baz {
    fn bar(&self, x: &Smth) {}
}

fn main() {
    let some_foo: Box<Baz> = Box::new(Baz {});  // ok
    // let some_foo: Box<Foo<&Smth>> = Box::new(Baz {});  // not ok
    let x = Smth {};
    some_foo.bar(&x);
}

While it is possible to type some_foo as Box<Baz> , it is not possible to use Box<Foo<&Smth>> instead, since it will cause the compiler to complain about &x being dropped (at the end of main ) while still borrowed (in bar ). This is (I think) due to the fact that x is created after some_foo , hence x gets dropped before some_foo . Moving the creation of x such that it occurs before the creation of some_foo would be a solution; but let's assume that's not possible¹.

I still don't quite get why the code is valid for some_foo: Box<Baz> but not for some_foo: Box<Foo<&Smth>> . What is it that the compiler cannot know (otherwise it wouldn't need to complain)?


¹ because you have a collection of models which you wish to crossvalidate , ie model.fit(x, y) where x, y are subsets of larger (X, Y) .

The boxed trait object needs to work with all lifetimes for the reference to Smth :

let some_foo: Box<for<'a> Foo<&'a Smth>> = Box::new(Baz {});

Maybe someone else can explain why the compiler couldn't derive a working lifetime :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM