Reputation: 343
I'm having trouble with the follwoing code...
use std::collections::BTreeSet;
use maybe_owned::MaybeOwned;
struct Thing<'a, T> {
set: BTreeSet<MaybeOwned<'a, T>>
}
impl<'a, T: Ord> Thing<'a, T> {
fn take(&mut self, x: T){
let y = self.set.take(&MaybeOwned::Borrowed(&x));
}
}
gives the compiler error
error[E0597]: `x` does not live long enough
--> src/main.rs:10:53
|
8 | impl<'a, T: Ord> Thing<'a, T> {
| -- lifetime `'a` defined here
9 | fn take(&mut self, x: T){
10 | let y = self.set.take(&MaybeOwned::Borrowed(&x));
| ------------------------------------^^--
| | |
| | borrowed value does not live long enough
| argument requires that `x` is borrowed for `'a`
11 | }
| - `x` dropped here while still borrowed
However x is clearly not borrowed at that point because the MaybeOwned has fallen out of scope and therefore the enclosed borrow has fallen out of scope.
How can I tell the rust compiler that this is fine?
Upvotes: 3
Views: 72
Reputation: 168958
The problem is that, while the temporary MaybeOwned
doesn't live that long, it doesn't matter because it's implicitly MaybeOwned<'a, T>
. This means x
must live at least as long as 'a
but it doesn't. The fact that the temporary MaybeOwned
won't live that long isn't relevant to the borrow checker.
BTreeSet::take()
's second argument is a &Q
, where the set's own T
implements Borrow<Q>
. MaybeOwned<'a, T>
doesn't implement Borrow<MaybeOwned<'b, T>>
where 'b: 'a
, but all T
and &T
implement Borrow<T>
thanks to a blanket implementation, so given an argument typed &MaybeOwned<'_, T>
, the only lifetime that satisfies the T: Borrow<Q>
constraint is &MaybeOwned<'a, T>
-- thus, the lifetime parameter of the temporary MaybeOwned
is inferred to be 'a
. That's the only way the trait bounds can be satisfied.
Thankfully, none of this matters, because MaybeOwned<'_, T>
implements Borrow<T>
, which means you can just supply a &T
:
let y = self.set.take(&x);
Upvotes: 2