Search code examples
rusttraits

How to qualify a trait function for Ref<RefCell<>>


Consider the following code:

use std::{cell::RefCell, rc::Rc};
trait MyTrait {
    fn my_func(&mut self) {}
}
struct MyStruct;
impl MyTrait for MyStruct {}
fn main() {
    let my_ref=Rc::new(RefCell::new(MyStruct{}));
    my_ref.borrow_mut().my_func();
}

This of course works fine. If I have two traits with the same function name I have to use the fully qualified version. If I try:

MyTrait::my_func(&mut my_ref.borrow_mut());

instead of

my_ref.borrow_mut().my_func();

I get the error message:

error[E0277]: the trait bound `RefMut<'_, MyStruct>: MyTrait` is not satisfied
 --> src/main.rs:9:22
  |
9 |     MyTrait::my_func(&mut my_ref.borrow_mut());
  |     ---------------- ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `RefMut<'_, MyStruct>`
  |     |
  |     required by a bound introduced by this call
  |
  = help: the trait `MyTrait` is implemented for `MyStruct`

How do I correctly fully qualify the trait function for a <Ref<RefCell<MyStruct>>?


Solution

  • MyTrait::my_func(…)
    

    only partially qualifies the method, it specifies which trait's method to call, but it does not qualify the Self type of the implementer.

    The fully qualified syntax to call the function is this:

    <MyStruct as MyTrait>::my_func(&mut my_ref.borrow_mut());
    

    Which does work, because the compiler is able to tell what the desired target type (MyStruct) is and apply type coercion.

    You can also convert your reference to one that does already have the appropriate type, either like eggyal suggests by dereferencing the BorrowMut:

    MyTrait::my_func(&mut *my_ref.borrow_mut());
    

    or, by coercing the reference either implicitly:

    let my_struct_ref: &mut MyStruct = my_ref.borrow_mut();
    MyTrait::my_func(my_struct_ref);
    

    or explicitly:

    MyTrait::my_func(&mut my_ref.borrow_mut() as &mut MyStruct);