1

I am doing examples from the Rust book but I dont understand this one. How can a.tail() use tail(), when tail() is a function in the implementation of List and a is of Rc type?

use crate::List::{Cons, Nil};
use std::cell::RefCell;
use std::rc::Rc;

#[derive(Debug)]
enum List {
    Cons(i32, RefCell<Rc<List>>),
    Nil,
}

impl List {
    fn tail(&self) -> Option<&RefCell<Rc<List>>> {
        match self {
            Cons(_, item) => Some(item),
            Nil => None,
        }
    }
}

fn main() {
    let a = Rc::new(Cons(5, RefCell::new(Rc::new(Nil))));

    println!("a initial rc count = {}", Rc::strong_count(&a));
    println!("a next item = {:?}", a.tail());
}

Thank you

Little A
  • 7
  • 1

2 Answers2

3

Rc implements Deref. That means you can do &*rc and get back &T, like if it was a reference.

When you call a method, the compiler automatically inserts &s and *s as necessary. This is called autoref or autoderef. See What are Rust's exact auto-dereferencing rules? for more details.

Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77
3

That's due to automatic dereferencing, or Deref coercion. Rc is a Reference-counted smart pointer and it implements the Deref interface, which basically allows you to directly call methods on the value the Rc points to (in your case, the List enum).

See this and also this for more.

at54321
  • 8,726
  • 26
  • 46