如何正确处理复杂的递归生命周期?

时间:2015-10-12 06:20:14

标签: rust lifetime

我有两种不同的结构。主要的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))

1 个答案:

答案 0 :(得分:2)

问题是do_something(&'a mut self)借用了自己,并且在完成之前不会释放它。但你的盒装封口是'#34;承诺&#34;保持do_something可多次调用,这是不可能的(因为第一次调用将&#34;锁定&#34;自我)。

您可以从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代替FnMut,因为Shepmaster发表了评论。请注意,在这种情况下,您将移动自己的所有权而不是借用,并且您承诺只会调用一次关闭。

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() {}