Ошибка "недостаточно долго" с Weak <RefCell <_ >> ` - PullRequest
0 голосов
/ 02 мая 2018

В последнее время у меня много проблем с тем, что Rust отказывается от моего кода. Чтобы задать вопрос, я упростил свой код:

use std::cell::RefCell;
use std::rc::{Rc, Weak};

struct SomeOtherType<'a>{
    data: &'a i32,
}

struct MyType<'a> {
    some_data: i32,
    link_to_other_type: Weak<RefCell<SomeOtherType<'a>>>,
}

struct ParentStruct<'a> {
    some_other_other_data: i32,
    first_types: &'a Vec<MyType<'a>>,
}


fn get_parent_struct<'a>(first_types: &'a Vec<MyType<'a>>) -> ParentStruct<'a> {
    ParentStruct { some_other_other_data: 4, first_types: first_types }
} 

fn consume(parent_struct: ParentStruct) {
    print!("{}", parent_struct.first_types[0].some_data);
}

fn main() {
    let some_vect = vec!(
        MyType { some_data: 1, link_to_other_type: Weak::new() },
        MyType { some_data: 2, link_to_other_type: Weak::new() }
    );
    loop {
        let some_struct = get_parent_struct(&some_vect);
        consume(some_struct);
    }
}

Этот код не компилируется, я получаю следующую ошибку:

error[E0597]: `some_vect` does not live long enough
  --> src/main.rs:33:46
   |
33 |         let some_struct = get_parent_struct(&some_vect);
   |                                              ^^^^^^^^^ borrowed value does not live long enough
...
36 | }
   | - `some_vect` dropped here while still borrowed
   |
   = note: values in a scope are dropped in the opposite order they are created 

Но странный факт: если в типе MyType я меняю Weak<RefCell<...>> на Rc<RefCell<...>> или RefCell<...> или Weak<...>: он компилируется !!

Мой вопрос: почему? Почему средство проверки заимствования отказывается компилировать исходный код (и почему он принимает код с другими типами вместо Weak<RefCell<...>>)?

1 Ответ

0 голосов
/ 02 мая 2018

Поскольку Лукас Калбертодт предоставил MCVE ( Детская площадка ), я буду использовать его код:

struct MyType<'a> {
    link_to_other_type: Weak<RefCell<&'a i32>>,
}

fn get_parent_struct<'a>(_: &'a MyType<'a>) {} 

fn main() {
    let foo = MyType { link_to_other_type: Weak::new() };
    get_parent_struct(&foo);
}

Давайте пройдемся по шагам:

  • A Weak создан и перемещен в MyType со временем жизни 'a
  • Когда оно передается get_parent_struct<'a>(_: &'a MyType<'a>), у вас есть ссылка с временем жизни 'a на тип с временем жизни 'a
  • get_parent_struct ожидает, что его параметр будет жить ровно столько же, сколько и сам foo, что не соответствует действительности, поскольку foo доживает до конца области действия

Как уже упоминалось kazemakase , решение состоит в том, чтобы использовать другое время жизни для ссылки. Если вы слегка измените сигнатуру get_parent_struct, она будет работать:

fn get_parent_struct<'a>(_: &MyType<'a>) {} 

Детская площадка

Компилятор теперь сократит время жизни до

fn get_parent_struct<'a, 'b>(_: &'b MyType<'a>) where 'a: 'b {}

Сейчас 'a переживает 'b.

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