//! Implementing Deref allows customization of the * operator. use std::ops::Deref; // defining our own smart pointer // for struct MyBox and its implementation struct MyBox(T); impl MyBox { fn new(x: T) -> MyBox { MyBox(x) } } // treating a type like a reference by implementing the Deref trait // impl section impl Deref for MyBox { type Target = T; fn deref(&self) -> &Self::Target { // This is a tuple with one element inside of a box?? &self.0 } } fn hello(name: &str) { println!("Hello, {name}!"); } fn main() { // following the pointer to the value let x = 5; let y = &x; // *y to follow the reference to the value in x. assert_eq!(5, x); assert_eq!(5, *y); // Using Box like a reference let x = 5; let y = Box::new(x); assert_eq!(5, x); assert_eq!(5, *y); // defining our own smart pointer let x = 5; let y = MyBox::new(x); assert_eq!(5, x); assert_eq!(5, *y); // Implicit deref coercions with functions and methods // deref coercion converts a reference to a type that implements // Deref trait into a reference to another type. let m = MyBox::new(String::from("Rust")); hello(&m); // How deref coercion interacts with mutability // // Rust does deref coercion when it finds types and // trait implementations in three cases: // 1) From &T to &U when `T: Deref` // 2) From &mut T to &mut U when `T: DerefMut` // 3) From &mut T to &U when `T: Deref` // // Rust will never coerce an immutable reference into a // mutable reference. }