Как указать время жизни, чтобы локальное значение, отличное от указанного в ссылке? - PullRequest
1 голос
/ 08 апреля 2019

Я создаю локальную структуру (second), которая содержит ссылку на локальную переменную (wrapper).Эта локальная переменная, в свою очередь, ссылается на большее время жизни ('a).Как мне показать компилятору, что время жизни локальной переменной не должно быть таким же большим, как у этого большего времени жизни?

Эта проблема воспроизводится следующим кодом ( детская площадка ):

#![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

Как я могу изменить определения времени жизни так, чтобы wrapper не обязывался жить так же долго, как 'a, учитывая, что second перемещается сразу после этого?Я подозреваю, что это связано с определением move_away, потому что когда я изменяю эту строку следующим образом ( детская площадка ):

fn move_away<'a, A: Abc, S: Strategy<KindTwo, A>>(_argument: AnotherWrapper<'a, KindTwo, A, S>) {}

код компилируется.

1 Ответ

1 голос
/ 09 апреля 2019

Изменение определения move_away на следующее устраняет ошибку компиляции:

fn move_away<'a, 'b, A: Abc, S: Strategy<KindTwo, WrappingAbc<'b, A>>>(
    _argument: AnotherWrapper<'a, KindTwo, WrappingAbc<'b, A>, S>
) {}

Введение времени жизни 'b устраняет необходимость в том, чтобы время жизни внутреннего WrappingAbc равнялось 'a, как указано родительской функцией.

...