// Recursive type using boxes use std::rc::Rc; enum List { Cons(i32, Rc), Nil, } struct MyBox(T); impl MyBox { fn new(x: T) -> MyBox { MyBox(x) } } use std::ops::Deref; impl Deref for MyBox { type Target = T; fn deref(&self) -> &T { &self.0 } } struct CustomSmartPointer { data: String, } impl Drop for CustomSmartPointer { fn drop(&mut self) { println!("Dropping CustomSmartPointer with data `{}`!", self.data); } } fn main() { // Storing `i32` value on heap let b = Box::new(5); println!("b = {}", b); use crate::List::{Cons, Nil}; let list = Cons(1, Rc::new(Cons(2, Rc::new(Cons(3, Rc::new(Nil)))))); // Dereferencing let x = 5; let y = &x; assert_eq!(5, x); assert_eq!(5, *y); let x = 5; let y = Box::new(x); assert_eq!(5, x); assert_eq!(5, *y); let x = 5; let y = MyBox::new(x); assert_eq!(5, x); assert_eq!(5, *y); // `*y` is equivalent to `*(y.deref())` fn hello(name: &str) { println!("Hello, {}", name); } // Deref coercion let m = MyBox::new(String::from("Rust")); // `&MyBox` -> `&String` -> `&str` hello(&m); // `m`: MyBox, `*m`: String, `(*m)[..]`: str, `&(*m)[..]`: &str hello(&(*m)[..]); let c = CustomSmartPointer { data: String::from("my stuff"), }; let d = CustomSmartPointer { data: String::from("other stuff"), }; println!("CustomSmartPointer created."); drop(c); println!("CustomSmartPointer dropped before the end of main."); let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil))))); println!("count after creating a = {}", Rc::strong_count(&a)); let b = Cons(3, Rc::clone(&a)); println!("count after creating b = {}", Rc::strong_count(&a)); { let c = Cons(4, Rc::clone(&a)); println!("count after creating c = {}", Rc::strong_count(&a)); } println!("count after c goes out of scope = {}", Rc::strong_count(&a)); }