如何为包含Rc <Refcell <Trait >>的结构实现Deref?

时间:2019-09-09 14:29:27

标签: rust traits rc refcell

我的目标是将针对我的结构的方法调用委托给Trait的方法,其中Trait对象位于Rc的{​​{1}}中。

我尝试遵循此问题的建议: How can I obtain an &A reference from a Rc<RefCell<A>>?

出现编译错误。

RefCell

这是错误:

use std::rc::Rc;
use std::cell::RefCell;
use std::fmt::*;
use std::ops::Deref;

pub struct ShyObject {
    pub association: Rc<RefCell<dyn Display>>
}

impl Deref for ShyObject {
    type Target = dyn Display;
    fn deref<'a>(&'a self) -> &(dyn Display + 'static) {
        &*self.association.borrow()
    }
}

fn main() {}

我的示例使用error[E0515]: cannot return value referencing temporary value --> src/main.rs:13:9 | 13 | &*self.association.borrow() | ^^------------------------- | | | | | temporary value created here | returns a value referencing data owned by the current function 作为特征;实际上,我有很多方法的特质。我试图避免必须实现所有这些方法的样板,而只是在每次调用时深入到Trait对象。

2 个答案:

答案 0 :(得分:3)

不能。 RefCell::borrow返回Ref<T>,而不是&T。如果您尝试使用一种方法来执行此操作,则需要首先借用Ref<T>,但它将超出范围。

您可以有一个方法返回执行以下操作的方法,而不是实现Deref

impl ShyObject {
    fn as_deref(&self) -> impl Deref<Target = dyn Display> {
        self.association.borrow()
    }
}

否则,由于无论如何您只想公开内部数据的Display实现,因此可以通过实际取消引用委托的其他类型来解决此问题:

pub struct ShyObject {
    association: Assocation<dyn Display>,
}

struct Assocation<T: ?Sized>(Rc<RefCell<T>>);

impl<T: Display + ?Sized> fmt::Display for Assocation<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0.borrow())
    }
}

impl Deref for ShyObject {
    type Target = dyn Display + 'static;
    fn deref(&self) -> &Self::Target {
        &self.association
    }
}

答案 1 :(得分:2)

您不能那样做。 borrow创建a new struct,允许RefCell跟踪借用。这样一来,您就不能向此Ref借钱,因为它是一个局部变量。