首页 > 解决方案 > 如何返回对存储在结构成员中的可选盒装特征的可变引用

问题描述

我的目标是返回对存储在 Box 中的 trait 对象的可变引用。

这似乎与关于借用对可选结构成员的引用的问题有关,但主要区别似乎是特征对象的存在。我也试图返回一个选项而不是一个结果。

尝试使用相同的方法似乎会导致终身问题。

示例代码:

trait Baz {}

#[derive(Debug)]
struct Foo;

impl Baz for Foo {}

struct Bar {
    data: Option<Box<Baz>>,
}

enum BarErr {
    Nope,
}

impl Bar {
    fn borrow_mut(&mut self) -> Option<&mut Baz> {
        self.data.as_mut().map(|x| &mut **x)
    }
}

游乐场链接。

错误信息:

   Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
  --> src/lib.rs:20:9
   |
20 |         self.data.as_mut().map(|x| &mut **x)
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
   |
   = note: expected type `std::option::Option<&mut dyn Baz>`
              found type `std::option::Option<&mut (dyn Baz + 'static)>`
note: the anonymous lifetime #1 defined on the method body at 19:5...
  --> src/lib.rs:19:5
   |
19 | /     fn borrow_mut(&mut self) -> Option<&mut Baz> {
20 | |         self.data.as_mut().map(|x| &mut **x)
21 | |     }
   | |_____^
   = note: ...does not necessarily outlive the static lifetime

我真的看不出寿命会在哪里延长。

尝试替换 &mut **xas_mut也无济于事。

标签: rust

解决方案


发生这种情况是因为编译器中的一个怪癖。让我们扩展 中的生命周期borrow_mut

fn borrow_mut<'a>(&'a mut self) -> Option<&'a mut dyn Baz> {

表达方式

self.data.as_mut().map(|x| &mut **x)

被推断有类型Option<&mut dyn (Baz + 'static)>,而函数期望输出Option<&'a mut dyn (Baz + 'a)>。应用于 trait 对象的生命周期约束的这种细微差别不能通过简单的强制来解决,因为可变引用对于 trait 对象的生命周期是不变的。

我们可以做的是要么同意输出一个可变引用dyn Baz + 'static

fn borrow_mut<'a>(&'a mut self) -> Option<&'a mut (dyn Baz + 'static)> {
   self.data.as_mut().map(|x| x.as_mut())
}

或者告诉编译器Option<&'a mut (dyn Baz + 'a)>通过其他方式解析表达式,例如使用手动match语句、?运算符或强制转换。

impl Bar {
    fn borrow_mut(&mut self) -> Option<&mut dyn Baz> {
        self.data.as_mut().map(|x| &mut **x as &mut dyn Baz)
    }
}

另请参阅:Rust 中 Box 类型的协方差


推荐阅读