Reputation: 359
I'm creating a local struct (second
) which contains a reference to a local variable (wrapper
). This local variable, in turn, references a larger lifetime ('a
). How do I show the compiler, that the lifetime of the local variable doesn't need to be as large as that larger lifetime?
This problem is reproduced by the following code (playground):
#![allow(dead_code)]
use std::marker::PhantomData;
trait Abc {}
struct ImplAbc;
impl Abc for ImplAbc {}
struct WrappingAbc<'a, A> {
value: &'a A,
}
impl<'a, A: Abc> Abc for WrappingAbc<'a, A> {}
impl<'a, A: Abc> WrappingAbc<'a, A> {
fn new(value: &'a A) -> Self {
WrappingAbc { value }
}
}
struct AnotherWrapper<'a, K, A, S> {
value: &'a A,
other: usize,
phantom_data: PhantomData<(K, S)>,
}
impl<'a, A: Abc, S: Strategy<KindOne, A>> AnotherWrapper<'a, KindOne, A, S> {
fn new(value: &'a A) -> Self {
AnotherWrapper {
value,
other: 0,
phantom_data: PhantomData,
}
}
}
impl<'a, 'b, A: Abc, S: Strategy<KindTwo, WrappingAbc<'b, A>>>
AnotherWrapper<'a, KindTwo, WrappingAbc<'b, A>, S>
{
fn replace_value<SOther: Strategy<KindOne, A>>(
old: AnotherWrapper<KindOne, A, SOther>,
newvalue: &'a WrappingAbc<'b, A>,
) -> Self {
AnotherWrapper {
value: newvalue,
other: old.other,
phantom_data: PhantomData,
}
}
}
trait Kind {}
struct KindOne;
impl Kind for KindOne {}
struct KindTwo;
impl Kind for KindTwo {}
trait Strategy<K: Kind, A: Abc>: Sized {}
struct StrategyImpl;
impl<K: Kind, A: Abc> Strategy<K, A> for StrategyImpl {}
fn f<'a, A: Abc, SOne: Strategy<KindOne, A>, STwo: Strategy<KindTwo, WrappingAbc<'a, A>>>(
x: &'a A,
) {
let first = AnotherWrapper::<KindOne, A, SOne>::new(x);
let wrapper = WrappingAbc::new(x);
let second = AnotherWrapper::<KindTwo, WrappingAbc<A>, STwo>::replace_value(first, &wrapper);
move_away(second);
}
fn move_away<'a, A: Abc, S: Strategy<KindTwo, WrappingAbc<'a, A>>>(
_argument: AnotherWrapper<'a, KindTwo, WrappingAbc<'a, A>, S>,
) {
}
error[E0597]: `wrapper` does not live long enough
--> src/lib.rs:62:88
|
57 | fn f<'a, A: Abc, SOne: Strategy<KindOne, A>, STwo: Strategy<KindTwo, WrappingAbc<'a, A>>>(
| -- lifetime `'a` defined here
...
62 | let second = AnotherWrapper::<KindTwo, WrappingAbc<A>, STwo>::replace_value(first, &wrapper);
| ----------------------------------------------------------------------^^^^^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `wrapper` is borrowed for `'a`
63 | move_away(second);
64 | }
| - `wrapper` dropped here while still borrowed
How can I change the lifetime definitions such that wrapper
is not required to live as long as 'a
, given that second
is moved right after anyways? I suspect that this is related to the definition of move_away
, because when I modify that line to this (playground):
fn move_away<'a, A: Abc, S: Strategy<KindTwo, A>>(_argument: AnotherWrapper<'a, KindTwo, A, S>) {}
the code compiles.
Upvotes: 1
Views: 101
Reputation: 359
Changing the definition of move_away
to the following solves the compilation error:
fn move_away<'a, 'b, A: Abc, S: Strategy<KindTwo, WrappingAbc<'b, A>>>(
_argument: AnotherWrapper<'a, KindTwo, WrappingAbc<'b, A>, S>
) {}
Introducing the lifetime 'b
removes the requirement that the lifetime of the inner WrappingAbc
is just as long as 'a
as specified by the parent function.
Upvotes: 1