如何从 Rc<RefCell<A>> 获取 &A 引用?

Jak*_*ake 5 reference smart-pointers rust borrowing

我有一些设计问题,我想用安全的 Rust 来解决,但我一直无法找到可行的解决方案。我不能使用 aRefCell因为你不能得到 & 对数据的引用,只有Ref/ RefMut

这是一个简化的示例,删除了不相关的字段/方法

use std::cell::RefCell;
use std::rc::Rc;

struct LibraryStruct {}
impl LibraryStruct {
    fn function(&self, _a: &TraitFromLibrary) {}
}

trait TraitFromLibrary {
    fn trait_function(&self, library_struct: LibraryStruct);
}

// I don't want to copy this, bad performance
struct A {
    // fields...
}

impl TraitFromLibrary for A {
    fn trait_function(&self, library_struct: LibraryStruct) {
        // custom A stuff
    }
}

// B manipulates A's in data
struct B {
    data: Vec<A>,
}

struct C {
    // This type doesn't have to be & for solution. C just needs immutable access
    a: Rc<RefCell<A>>,
}

impl<'a> TraitFromLibrary for C {
    fn trait_function(&self, library_struct: LibraryStruct) {
        // custom C stuff

        // Takes generic reference &, this is why Ref / RefCell doesn't work
        library_struct.function(&self.a.borrow());
    }
}

// B and C's constructed in Container and lifetime matches Container
// Container manipulates fields b and c
struct Container {
    b: B,
    c: Vec<C>,
}

fn main() {}
Run Code Online (Sandbox Code Playgroud)

我将能够解决这个问题,Rc<RefCell<A>>但我被限制在需要&A.

这会产生错误:

use std::cell::RefCell;
use std::rc::Rc;

struct LibraryStruct {}
impl LibraryStruct {
    fn function(&self, _a: &TraitFromLibrary) {}
}

trait TraitFromLibrary {
    fn trait_function(&self, library_struct: LibraryStruct);
}

// I don't want to copy this, bad performance
struct A {
    // fields...
}

impl TraitFromLibrary for A {
    fn trait_function(&self, library_struct: LibraryStruct) {
        // custom A stuff
    }
}

// B manipulates A's in data
struct B {
    data: Vec<A>,
}

struct C {
    // This type doesn't have to be & for solution. C just needs immutable access
    a: Rc<RefCell<A>>,
}

impl<'a> TraitFromLibrary for C {
    fn trait_function(&self, library_struct: LibraryStruct) {
        // custom C stuff

        // Takes generic reference &, this is why Ref / RefCell doesn't work
        library_struct.function(&self.a.borrow());
    }
}

// B and C's constructed in Container and lifetime matches Container
// Container manipulates fields b and c
struct Container {
    b: B,
    c: Vec<C>,
}

fn main() {}
Run Code Online (Sandbox Code Playgroud)

Pet*_*all 8

如果函数有一个类型为 a 的参数&A,那么您可以使用对任何取消引用的类型的引用来调用它A,其中包括诸如&Ref<A>. 一种类型取消引用另一种类型的概念由特征捕获Deref&str这也是为什么可以调用接受的函数的原因&String(String: Deref<Target = str>

所以,如果你保留a为 a Rc<RefCell<A>>,你可以很容易地修复你的代码,如下所示:

library_struct.function(&*self.a.borrow());
Run Code Online (Sandbox Code Playgroud)

请注意,这会取消引用A,然后重新借用它,以便可以将其强制为特征对象。