如何告诉 rustc 返回值的寿命足够长?

问题描述 投票:0回答:1

一段代码:

use std::mem::*;

trait Child {
    fn do_something(&mut self, value: u32);
}

trait Parent<'a> {
    type Remove;
    // add a child to the parent, RAII-like pattern
    // we assume that child may change its internal state when parent does its calls on child's methods, but the child doesn't have to
    fn put(&'a mut self, child: &'a mut dyn Child) -> Self::Remove;
    // just a helper method
    fn put_callback(&'a mut self, callback: &'a dyn Fn(u32) -> ()) -> CallbackRemove<'a, Self::Remove> {
        let mut remove = CallbackRemove {
            child: CallbackChild { callback },
            remove: MaybeUninit::uninit()
        };
        remove.remove = MaybeUninit::new(self.put(&mut remove.child));
        
        remove
    }
}

struct CallbackChild<'a> {
    callback: &'a dyn Fn(u32) -> ()
}
impl<'a> Child for CallbackChild<'a> {
    fn do_something(&mut self, value: u32) -> () {
        (self.callback)(value)
    }
}
struct CallbackRemove<'a, R> {
    child: CallbackChild<'a>,
    remove: MaybeUninit<R>
}

沙盒链接

Foo1
Foo2
Bar1
foo2_to_foo1
可以是任何有意义的东西,它们的内容对问题没有任何影响。

有 2 个错误:

  1. 归还已借的
    bar2
  2. bar2.foo1
    的生命周期不够长,因为
    &mut bar2.foo1
    的生命周期是
    '_
    ,而
    foo1
    func1
    的生命周期需要
    'a
    ,尽管我明确声明了
    bar2
    的生命周期

问题是我们通过

bar2
借用了
bar2
,即使用已经初始化的
bar2
的字段来初始化
bar2
的字段。看起来借用应该在那行之后结束,因为我们将值借回给所有者。

而且,

&mut bar2.foo1
确实活得足够长,因为我们返回值,并且指定了返回值的生命周期,即
&mut bar2.foo1
应该有
'a
生命周期。

我只需要如何摆脱这些错误,这些错误是无意义的(借回的值被视为借用,而不是拥有;具有明确定义生命周期的借用值

'a
实际上存在于
'_
)。我想摆脱
MaybeUninit
。最简单的方法是在
foo1
范围之外声明
Bar2<'a>
字段,但它不会被返回,并且它的生命周期实际上将是
'_
而不是
'a

rust lifetime
1个回答
0
投票

您对构造的生命周期如何工作感到困惑。考虑一下:

use std::mem::*;

trait Child {
    fn do_something(&mut self, value: u32);
}

trait Parent<'a> {
    type Remove;
    // add a child to the parent, RAII-like pattern
    // we assume that child may change its internal state when parent does its calls on child's methods, but the child doesn't have to
    fn put<'c>(&'a mut self, child: &'c mut dyn Child) -> Self::Remove;
    // just a helper method
    fn put_callback(&'a mut self, callback: &'a dyn Fn(u32) -> ()) -> CallbackRemove<'a, Self::Remove> {
        let mut remove = CallbackRemove {
            child: CallbackChild { callback },
            remove: MaybeUninit::uninit()
        };
        remove.remove = MaybeUninit::new(self.put(&mut remove.child));
        
        remove
    }
}

struct CallbackChild<'cb> {
    callback: &'cb dyn Fn(u32) -> ()
}
impl Child for CallbackChild<'_> {
    fn do_something(&mut self, value: u32) -> () {
        (self.callback)(value)
    }
}

struct CallbackRemove<'cb, R> {
    child: CallbackChild<'cb>,
    remove: MaybeUninit<R>
}

传递给 put 的子进程不必活到

'a
为止... put 可以在子进程还活着的时候对子进程做它需要做的事情,并返回完全拥有的移除——即之后孩子可以清理,家长可以对内容为所欲为。

P.S.:我认为你真的应该重新考虑设计,这感觉很麻烦,而且你的意图似乎很复杂。

© www.soinside.com 2019 - 2024. All rights reserved.