【问题标题】:How do I return a mutable reference to an Optional boxed Trait stored in a struct member如何返回对存储在结构成员中的可选盒装特征的可变引用
【发布时间】:2019-04-26 10:23:36
【问题描述】:

我的目标是返回对存储在 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)
    }
}

Playground link.

错误信息:

   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

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

同样尝试用as_mut 替换&amp;mut **x 也无济于事。

【问题讨论】:

  • 我在发布后不久就找到了一个可行的解决方案。但我很高兴接受一个对正在发生的事情有更好解释的答案。
  • 请使用rustfmt 格式化您的代码。你可以在the playground右上角的工具下找到它。

标签: rust


【解决方案1】:

这是由于编译器中的一个怪癖而发生的。让我们扩展borrow_mut中的生命周期:

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

表达式

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

被推断为具有Option&lt;&amp;mut dyn (Baz + 'static)&gt; 类型,而函数预期输出Option&lt;&amp;'a mut dyn (Baz + 'a)&gt;。应用于 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&lt;&amp;'a mut (dyn Baz + 'a)&gt;,例如使用手动match 语句、? 运算符或强制转换。

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

另请参阅:Covariance of Box type in Rust

【讨论】:

    【解决方案2】:

    似乎使用解构语法似乎可以解决这个问题: 以下代码编译正常:

    fn borrow_mut(&mut self) -> Option<&mut Baz> {
        match &mut self.data {
            Some(e) => Some(e.as_mut()),
            None => None,
        }
    }
    

    【讨论】:

    • 有点古怪,但这也适用:Some(self.data.as_mut()?.as_mut())
    猜你喜欢
    • 2015-08-01
    • 2017-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-25
    • 1970-01-01
    • 2023-03-18
    相关资源
    最近更新 更多