Why can std::rc::Rc call its own value's methods?
Asked Answered
P

2

5

I'm a newbie to Rust and type-systems. I'm reading rustc/rc.rs. I don't know why Rc<T> can call T's methods. What conditions does a Structure<T> satisfy for calling methods of the wrapped value?

use std::rc::Rc;

fn main() {
    let a = Rc::new("The quick fox".to_string());
    println!("{}", a.contains("white")); // Rc<String> can call String#contains.
}
Paresis answered 22/12, 2019 at 4:44 Comment(0)
F
9

This property is called "Deref coercion".

If you have two types T and U, such that T: Deref<Target = U>, then everywhere you have a &T, you can coerce it to &U. In particular, as method call syntax is just sugar to the functions taking &self (or &mut self, or self - depending on the method), you can call methods on the U having only T.

As you can see in the docs, Deref is implemented for Rc, as it is for almost any other smart pointer (the "active" smart pointers like Mutex, which involve explicit locking, being notable exception). So, when you have one of these smart pointers, you can treat a reference to it as the reference to the inner value - see also this question about other consequences of this fact.

More info on this topic could be also found in the Rust book.

Forme answered 22/12, 2019 at 5:23 Comment(4)
so basically the compiler knows what types are smart pointers and the compiler writes (*a).contains("white") automatically? can i implement deref on my custom type? and then call its inner type methods without writing *object everytime?Jollity
Of course you can. Other then these auth-inserted coercions, Deref is an ordinary trait, which can be implemented on arbitrary types (modulo orphan rules, of course).Forme
i didnt ask if you can implement the trait, i asked if you get auto deref without writing * after implemeting the traitJollity
This is not called "Deref coercion" but "autoderef". Deref coercion is for example when you do let v: &String = &rc.Involve
J
0

im writing this answer for people who want to implement their custom type that has an inner type and then call the inner's type methods without writing wrapper functions.

this is a handy situation for struct composition/aggregation, where you have a wrapper over a type and dont want to write every method like this:

pub fn width(&self) -> i32 {
    self.inner.width()
}

pub fn height(&self) -> i32 {
    self.inner.height()
}
/// and so on ...

this is actually ugly and annoying. imagine if you have 100 methods to wrap ...

here's the small example:

use std::ops::Deref;

pub struct Inner {}

impl Inner {
    pub fn just_a_method(&self) -> i32 {
        32
    }
}

struct DerefExample<T> {
    inner: T,
}

impl<T> Deref for DerefExample<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}

fn main() {
    let x = DerefExample {
        inner: Inner {}
    };
    let result = (*x).just_a_method();
    println!("(*x).just_a_method() == {}", result);
    let result = x.just_a_method();
    println!("x.just_a_method() == {}", result);
}

note that both methods of calling the just_a_method work the same. the second time the compiler automatically dereferences the x to get the inner type.

program output:

(*x).just_a_method() == 32
x.just_a_method() == 32
Jollity answered 28/12, 2022 at 10:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.