У меня есть код, который выглядит следующим образом:
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
самостоятельно.