借用检查器坚持取消引用值的生命周期

Mas*_*tic 5 rust

这是我遇到的问题的最小示例:

struct S<'a> {
    value: &'a mut Option<()>,
}

impl<'a> S<'a> {
    fn f<'b>(&'b mut self) {
        *self.value = Some(());
        let value: &'a () = self.value.as_ref().unwrap();
    }
}
Run Code Online (Sandbox Code Playgroud)

Playground

错误:

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
 --> src/lib.rs:8:34
  |
8 |         let value: &'a () = self.value.as_ref().unwrap();
  |                                        ^^^^^^
  |
note: first, the lifetime cannot outlive the lifetime `'b` as defined on the method body at 6:7...
 --> src/lib.rs:6:7
  |
6 |     fn f<'b>(&'b mut self) {
  |          ^^
note: ...so that reference does not outlive borrowed content
 --> src/lib.rs:8:23
  |
8 |         let value: &'a () = self.value.as_ref().unwrap();
  |                             ^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 5:6...
 --> src/lib.rs:5:6
  |
5 | impl<'a> S<'a> {
  |      ^^
note: ...so that reference does not outlive borrowed content
 --> src/lib.rs:8:23
  |
8 |         let value: &'a () = self.value.as_ref().unwrap();
  |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

问题是我期望f'svalue变量具有'a我注释的生命周期,但是借用检查器仅在它是'b. 我需要它,'a因为在我的真实代码中,我从中获得了一个期望'a生命周期的值。这对我来说也很有意义,'a因为(这是我困惑的症结所在:)在self.value我已经取消引用'b并且应该留下&'a mut Option<()>,即一个(仅)生命周期的值'a

我可以通过指定来解决它,'b: 'a但实际上恰恰相反(如果我需要的话'a: 'b);并且如果'b: 'a那么这个函数无限期地可变借用并且我无法触摸Safter 调用f这是一个问题Playground

我不确定这是否过于保守,或者我是否真的在尝试做一些不合理的事情。看看呼叫站点的生命周期,它是完全合理的。


关于我的真实用例的一些信息:我有一个 B 类型的缓冲区,从那个缓冲区我可以派生出一个类型 T 的值。 T 不仅仅是从 B 派生的,它还引用了它(想象一下fn derive<'a>(self: &'a B) -> T<'a>) . T 值过期并需要管理,所以我创建了一个管理器结构 M,这就是问题所在:M 包含一个对 B 的可变引用和一个缓存的 T。因此在 M 内部,B 引用有一些生命周期,而 T 有它也是,因为 T 指的是 B。它是这样的:

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
 --> src/lib.rs:8:34
  |
8 |         let value: &'a () = self.value.as_ref().unwrap();
  |                                        ^^^^^^
  |
note: first, the lifetime cannot outlive the lifetime `'b` as defined on the method body at 6:7...
 --> src/lib.rs:6:7
  |
6 |     fn f<'b>(&'b mut self) {
  |          ^^
note: ...so that reference does not outlive borrowed content
 --> src/lib.rs:8:23
  |
8 |         let value: &'a () = self.value.as_ref().unwrap();
  |                             ^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 5:6...
 --> src/lib.rs:5:6
  |
5 | impl<'a> S<'a> {
  |      ^^
note: ...so that reference does not outlive borrowed content
 --> src/lib.rs:8:23
  |
8 |         let value: &'a () = self.value.as_ref().unwrap();
  |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

因此,在我的最小示例中,我尝试获取 B 的引用(我希望它具有缓冲区的生命周期,但它具有 M 的生命周期),因此我可以从中派生,然后将结果分配给缓存的 T ,但我没有正确的寿命。