我的目标是返回对存储在Box中的特征对象的可变引用。
这似乎与此question about borrowing references to optional struct members有关,但是主要区别似乎在于特质对象的存在。 我也试图返回一个选项而不是结果。
尝试使用相同的方法似乎会导致终身问题。
示例代码:
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 **x
替换为as_mut
也无济于事。
答案 0 :(得分:3)
发生这种情况是因为编译器中有一个怪癖。让我们扩展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)>
。应用于特征对象的生命周期约束的这种细微差别无法通过强制转换解决,因为可变引用相对于特征对象的生命周期是不变的。
我们可以做的就是同意输出对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)
}
}
答案 1 :(得分:0)
似乎使用解构语法似乎可以解决此问题: 以下代码可以正常编译:
fn borrow_mut(&mut self) -> Option<&mut Baz> {
match &mut self.data {
Some(e) => Some(e.as_mut()),
None => None,
}
}