Как сделать так, чтобы эти жизни совпадали? - PullRequest
0 голосов
/ 22 июня 2019

Скажем, у нас есть такой код:

struct X {
    y: String,
}

trait Foo {
    fn bar(&mut self, x: &X);
}

type Stack<'a> = Vec<&'a X>;

struct Quux<'a> {
    stack: Stack<'a>,
}

fn bar(stack: &mut Stack, x: &X) {
    stack.push(x);
}

impl <'a>Foo for Quux<'a> {
    fn bar(&mut self, x: &X) {
        bar(&mut self.stack, x)
    }
}

Цель состоит в том, чтобы разделить функцию bar между структурами, которые реализуют Foo.Оказывается, bar делает что-то с self.stack, и поэтому мы не можем легко реализовать общее определение для Foo.

Этот код не будет компилироваться, жалуясь на время жизни Stackи &X отличаются. Ссылка на игровую площадку .

Как мы можем сопоставить эти времена жизни?

1 Ответ

1 голос
/ 22 июня 2019

Ответ на вопрос, на самом деле. Вам нужно, чтобы время жизни совпадало. Таким образом, ваша (не черта) bar должна иметь подпись

fn bar<'a>(stack: &mut Stack<'a>, x: &'a X)

Теперь ваша черта слишком общая. Он обещает, что не может сдержать. Он говорит: «Если что-то реализует Foo, то вы можете вызвать bar для него с любой ссылкой на X». Но это не то, что вы хотите. Вы должны ограничить это определенным временем жизни x. Итак, давайте параметризовать это.

trait Foo<'a> {
    fn bar(&mut self, x: &'a X);
}

Тогда мы изменим impl.

impl <'a>Foo<'a> for Quux<'a> {
    fn bar(&mut self, x: &'a X) {
        bar(&mut self.stack, x)
    }
}

Потому что теперь мы даем правильную гарантию. Quux<'a> не реализует Foo. Он специально реализует Foo<'a> для определенного времени жизни 'a.

Ссылка на игровую площадку

Полный код:

struct X {
    y: String,
}

trait Foo<'a> {
    fn bar(&mut self, x: &'a X);
}

type Stack<'a> = Vec<&'a X>;

struct Quux<'a> {
    stack: Stack<'a>,
}

fn bar<'a>(stack: &mut Stack<'a>, x: &'a X) {
    stack.push(x);
}

impl <'a>Foo<'a> for Quux<'a> {
    fn bar(&mut self, x: &'a X) {
        bar(&mut self.stack, x)
    }
}

fn main(){}
...