Почему параметр s не живет достаточно долго - PullRequest
0 голосов
/ 28 января 2019

Код:

use std::fmt::Debug;

trait DoSomthing<T> {
    fn do_sth(&self, value: T);
}

impl<T: Debug> DoSomthing<T> for &usize {
    fn do_sth(&self, value: T) {
        println!("{:?}", value);
    }
}

fn foo(b: Box<DoSomthing<&i32>>) {
    let s = 123;
    b.do_sth(&s);
}

fn main() {
    foo(Box::new(&3));
}

Сообщение об ошибке компилятора:

error[E0597]: `s` does not live long enough
  --> src/main.rs:15:14
   |
13 | fn foo(b: Box<DoSomthing<&i32>>) {
   |        - has type `std::boxed::Box<(dyn DoSomthing<&'1 i32> + '_)>`
14 |     let s = 123;
15 |     b.do_sth(&s);
   |     ---------^^-
   |     |        |
   |     |        borrowed value does not live long enough
   |     argument requires that `s` is borrowed for `'1`
16 | }
   | - `s` dropped here while still borrowed

Я думаю, это & ​​s просто используется в foo, метод foo заканчивается и больше не заимствует?Но это не так.Кто все еще одалживает это?Как решить эту проблему?Большое спасибо!

1 Ответ

0 голосов
/ 28 января 2019

Всякий раз, когда есть ссылка в Rust, есть целая жизнь.В большинстве случаев компилятор может сделать вывод, что вам не нужно записывать его, но он все еще там.Когда вы получаете запутанные ошибки времени жизни, это помогает попытаться выяснить, каковы эти неявные времена жизни.

fn foo(b: Box<DoSomthing<&i32>>) {
    let s = 123;
    b.do_sth(&s);
}

Это эквивалентно

fn foo<'y>(b: Box<DoSomthing<&'y i32>>) {
    let s = 123;
    b.do_sth(&s);
}

Другими словами, время жизниссылка, переданная на do_sth, на самом деле является "тем, что хочет вызывающий foo".Эта сигнатура функции позволяет мне написать следующее:

fn main() {
    let b : Box<DoSomthing<&'static i32>> = Box::new(&3);
    foo(b);
}

И если вы расширите черту DoSomthing для этого параметра, вы получите следующую функцию:

fn do_sth(&self, value: &'static i32) {
    println!("{:?}", value);
}

, которая foo пытается вызвать со ссылкой на локальную переменную.

Я надеюсь, это объясняет, почему ваш код не работает.

Что касается того, что вы должны написать вместо этого, я думаю, что это не такдействительно отвечает в целом.Невозможно написать подпись do_sth таким образом, чтобы «все ссылки, переданные этой функции, могли быть временными».Вам придется взглянуть на свой реальный код и придумать лучший способ его написания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...