如何正确处理复杂的递归生命周期?
How does one properly handle complex recursive lifetimes?
我有两个不同的结构。主要的 Example
和包装递归类型函数的 SFunction
.
这是它们的样子:
struct Example {
text: String,
}
impl<'a> Example {
fn function(&'a mut self) -> SFunction<'a> {
let closed_function = move || self.do_something();
SFunction::new(Box::new(closed_function))
}
fn do_something(&'a mut self) -> SFunction<'a> {
SFunction::empty()
}
}
struct SFunction<'a> {
f: Option<Box<FnMut() -> SFunction<'a> + 'a>>,
}
impl<'a> SFunction<'a> {
fn new(f: Box<FnMut() -> SFunction<'a> + 'a>) -> SFunction<'a> { // or no 'a on store
SFunction { f: Some(f) }
}
fn empty() -> SFunction<'a> {
SFunction { f: None }
}
}
(Here is a version in the Rust Playground)
这不编译,但我很困惑为什么会这样。我确定它与递归类型的函数有关,因为整个闭包的编译过程中没有那个部分。
错误信息如下:
src/main.rs:34:45: 34:59 error: cannot infer an appropriate lifetime for autoref due to conflicting requirements
src/main.rs:34 let closed_function = move || self.do_something();
^~~~~~~~~~~~~~
note: in expansion of closure expansion
src/main.rs:34:32: 34:59 note: expansion site
src/main.rs:34:40: 34:59 note: first, the lifetime cannot outlive the lifetime as defined on the block at 34:39...
src/main.rs:34 let closed_function = move || self.do_something();
^~~~~~~~~~~~~~~~~~~
src/main.rs:34:40: 34:44 note: ...so that closure can access `self`
src/main.rs:34 let closed_function = move || self.do_something();
^~~~
note: in expansion of closure expansion
src/main.rs:34:32: 34:59 note: expansion site
src/main.rs:33:49: 36:7 note: but, the lifetime must be valid for the lifetime 'a as defined on the block at 33:48...
src/main.rs:33 fn function(&'a mut self) -> SFunction<'a> {
src/main.rs:34 let closed_function = move || self.do_something();
src/main.rs:35 SFunction::new(Box::new(closed_function))
src/main.rs:36 }
src/main.rs:35:10: 35:51 note: ...so that expression is assignable (expected `SFunction<'a>`, found `SFunction<'_>`)
src/main.rs:35 SFunction::new(Box::new(closed_function))
问题是 do_something(&'a mut self)
借用了 self 并且在完成之前不会释放它。但是您的盒装闭包是 "promising" 以保持 do_something
可多次调用,这是不可能的(因为第一次调用将 "lock" self)。
或者你可以从 do_something
:
中删除对 self 的依赖
impl Example {
fn function<'a>(&'a mut self) -> SFunction<'a> {
let closed_function = move || do_something();
SFunction::new(Box::new(closed_function))
}
}
fn do_something<'a>() -> SFunction<'a> {
SFunction::empty()
}
或者您使用 FnOnce
而不是 Shepmaster 评论的 FnMut
。请注意,在这种情况下,您正在移动 self 的所有权而不是借用,并且您承诺只调用一次闭包。
struct Example {
text: String,
}
impl Example {
fn function<'a>(self) -> SFunction<'a> {
let closed_function = move || self.do_something();
SFunction::new(Box::new(closed_function))
}
fn do_something<'a>(self) -> SFunction<'a> {
SFunction::empty()
}
}
struct SFunction<'a> {
f: Option<Box<FnOnce() -> SFunction<'a> + 'a>>,
}
impl<'a> SFunction<'a> {
fn new(f: Box<FnOnce() -> SFunction<'a> + 'a>) -> SFunction<'a> { // or no 'a on store
SFunction { f: Some(f) }
}
fn empty() -> SFunction<'a> {
SFunction { f: None }
}
}
fn main() {}
我有两个不同的结构。主要的 Example
和包装递归类型函数的 SFunction
.
这是它们的样子:
struct Example {
text: String,
}
impl<'a> Example {
fn function(&'a mut self) -> SFunction<'a> {
let closed_function = move || self.do_something();
SFunction::new(Box::new(closed_function))
}
fn do_something(&'a mut self) -> SFunction<'a> {
SFunction::empty()
}
}
struct SFunction<'a> {
f: Option<Box<FnMut() -> SFunction<'a> + 'a>>,
}
impl<'a> SFunction<'a> {
fn new(f: Box<FnMut() -> SFunction<'a> + 'a>) -> SFunction<'a> { // or no 'a on store
SFunction { f: Some(f) }
}
fn empty() -> SFunction<'a> {
SFunction { f: None }
}
}
(Here is a version in the Rust Playground)
这不编译,但我很困惑为什么会这样。我确定它与递归类型的函数有关,因为整个闭包的编译过程中没有那个部分。
错误信息如下:
src/main.rs:34:45: 34:59 error: cannot infer an appropriate lifetime for autoref due to conflicting requirements
src/main.rs:34 let closed_function = move || self.do_something();
^~~~~~~~~~~~~~
note: in expansion of closure expansion
src/main.rs:34:32: 34:59 note: expansion site
src/main.rs:34:40: 34:59 note: first, the lifetime cannot outlive the lifetime as defined on the block at 34:39...
src/main.rs:34 let closed_function = move || self.do_something();
^~~~~~~~~~~~~~~~~~~
src/main.rs:34:40: 34:44 note: ...so that closure can access `self`
src/main.rs:34 let closed_function = move || self.do_something();
^~~~
note: in expansion of closure expansion
src/main.rs:34:32: 34:59 note: expansion site
src/main.rs:33:49: 36:7 note: but, the lifetime must be valid for the lifetime 'a as defined on the block at 33:48...
src/main.rs:33 fn function(&'a mut self) -> SFunction<'a> {
src/main.rs:34 let closed_function = move || self.do_something();
src/main.rs:35 SFunction::new(Box::new(closed_function))
src/main.rs:36 }
src/main.rs:35:10: 35:51 note: ...so that expression is assignable (expected `SFunction<'a>`, found `SFunction<'_>`)
src/main.rs:35 SFunction::new(Box::new(closed_function))
问题是 do_something(&'a mut self)
借用了 self 并且在完成之前不会释放它。但是您的盒装闭包是 "promising" 以保持 do_something
可多次调用,这是不可能的(因为第一次调用将 "lock" self)。
或者你可以从 do_something
:
impl Example {
fn function<'a>(&'a mut self) -> SFunction<'a> {
let closed_function = move || do_something();
SFunction::new(Box::new(closed_function))
}
}
fn do_something<'a>() -> SFunction<'a> {
SFunction::empty()
}
或者您使用 FnOnce
而不是 Shepmaster 评论的 FnMut
。请注意,在这种情况下,您正在移动 self 的所有权而不是借用,并且您承诺只调用一次闭包。
struct Example {
text: String,
}
impl Example {
fn function<'a>(self) -> SFunction<'a> {
let closed_function = move || self.do_something();
SFunction::new(Box::new(closed_function))
}
fn do_something<'a>(self) -> SFunction<'a> {
SFunction::empty()
}
}
struct SFunction<'a> {
f: Option<Box<FnOnce() -> SFunction<'a> + 'a>>,
}
impl<'a> SFunction<'a> {
fn new(f: Box<FnOnce() -> SFunction<'a> + 'a>) -> SFunction<'a> { // or no 'a on store
SFunction { f: Some(f) }
}
fn empty() -> SFunction<'a> {
SFunction { f: None }
}
}
fn main() {}