How do I pass Rc>> to a function accepting Rc>>?

前端 未结 1 529
滥情空心
滥情空心 2020-12-19 06:49

I have originally asked this question here, but it was marked as duplicate, although it duplicates only a part of it in my opinion, so I have created a more specific one:

相关标签:
1条回答
  • 2020-12-19 07:50

    (An older revision of this answer essentially advised to clone the underlying struct and put it in a new Rc<RefCell<Box<MyTrait>> object; this was necessary at the time on stable Rust, but since not long after that time, Rc<RefCell<MyStruct>> will coerce to Rc<RefCell<MyTrait>> without trouble.)

    Drop the Box<> wrapping, and you can coerce Rc<RefCell<MyStruct>> to Rc<RefCell<MyTrait>> freely and easily. Recalling that cloning an Rc<T> just produces another Rc<T>, increasing the refcount by one, you can do something like this:

    use std::rc::Rc;
    use std::cell::RefCell;
    
    trait MyTrait {
        fn trait_func(&self);
    }
    
    #[derive(Clone)]
    struct MyStruct1;
    impl MyStruct1 {
        fn my_fn(&self) {
            // do something
        }
    }
    
    impl MyTrait for MyStruct1 {
        fn trait_func(&self) {
            // do something
        }
    }
    
    fn my_trait_fn(t: Rc<RefCell<MyTrait>>) {
        t.borrow_mut().trait_func();
    }
    
    fn main() {
        // (The type annotation is not necessary here, but helps explain it.
        // If the `my_str.borrow().my_fn()` line was missing, it would actually
        // be of type Rc<RefCell<MyTrait>> instead of Rc<RefCell<MyStruct1>>,
        // essentially doing the coercion one step earlier.)
        let my_str: Rc<RefCell<MyStruct1>> = Rc::new(RefCell::new(MyStruct1));
        my_trait_fn(my_str.clone());
        my_str.borrow().my_fn();
    }
    

    As a general rule, see if you can make things take the contained value by reference, ideally even generically—fn my_trait_fn<T: MyTrait>(t: &T) and similar, which can typically be called as my_str.borrow() with automatic referencing and dereferencing taking care of the rest—rather than the whole Rc<RefCell<MyTrait>> thing.

    0 讨论(0)
提交回复
热议问题