Reputation: 1933
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 , i.e. model.fit(x, y)
where x, y
are subsets of larger (X, Y)
.
Upvotes: 4
Views: 87
Reputation: 5530
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 :)
Upvotes: 3