Могу ли я временно продлить время жизни ссылки, если в Rust требуется stati c? - PullRequest
0 голосов
/ 30 мая 2020

У меня есть код, который выглядит следующим образом:

fn my_func(data: &mut Data) {
  third_party_func(|| {
    // I need access to data here
  })
}

где third_party_func ожидает параметр FnMut() + 'static.

Поскольку параметр 'static, я не могу ссылаться на data непосредственно изнутри закрытия.

Я знаю , что закрытие используется только на время вызова third_party_func. Похоже, что либо автор third_party_func, либо кто-то из вышестоящих разработчиков хотел упростить задачу и просто потребовал, чтобы обратный вызов был 'static. Независимо от причины, я бессилен изменить third_party_func. У меня также нет контроля над распределением Data, и в большей части моего кода он доступен только по ссылке, поэтому, например, изменение my_func, чтобы принять что-то вроде Rc<RefCell<Data>>, здесь действительно невозможно.

Я думал, что обходной путь мог бы выглядеть следующим образом, если бы у меня была пара magi c структур StackMutRefGuard и StackMutRef:

fn my_func(data: &mut Data) {

  // The following line should 'consume' `data`
  // the &mut Data will be held onto inside the `guard` variable
  // until it goes out of scope
  // type of guard should include the lifetime of `data` to ensure
  // that `guard` does not outlive `data` through a move
  let guard = StackMutRefGuard::new(data)

  // stackref is 'static, so it can be taken by the closure
  let stackref: StackMutRef<Data> = guard.get()

  third_party_func(move || {
    // try_borrow() should return Some(data) if guard is still
    // alive, and None if it isn't
    // there's a bit of trickiness here about the lifetime of
    // the reference that try_borrow should return --
    // stackref itself may outlive the returned reference
    // actually `try_borrow` could be replaced with a `map`-like
    // method to ensure that lifetime is limited
    let data = stackref.try_borrow().unwrap()
    // or
    let blah_result = stackref.map(|data| data.compute_blah()).unwrap()
  })
}

Разумно ли мое мышление? Независимо от того, является ли мое предложение разумным, можно ли получить доступ к data изнутри крышки, и если да, то как? Есть ли в стандартной библиотеке или ящике что-то, что решает эту проблему?

Я был бы очень доволен любым решением, в котором мне не нужно было бы писать код unsafe самостоятельно.

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