🧙Deref Coercion
What is Deref
Coercion?
Deref
Coercion?💡 The Deref
trait enables "Deref
coercion," which allows the compiler to automatically perform implicit dereferencing when calling functions or methods by converting the references of custom types to references of their inner types.
This is how Deref
coercion works behind the scenes:
The compiler will check if the argument type implements
Deref
.If it does, and the dereferenced type matches the expected type in the function signature, the compiler will automatically inserts calls to the
deref
method as needed.
When the Deref
Coercion is applied?
Deref
Coercion is applied?Rust performs Deref
coercion in three specific cases:
Cases | How it works? |
---|---|
From |
|
From |
|
From |
|
Deref
with Function & Method Calls
Deref
with Function & Method CallsUsing the previous example of our custom smart pointer. To demonstrate how the Deref
coercion works, we add a new function say_hi
which receives a &str
reference.
In this code, the Deref
coercion happens in the say_hi
function.
The say_hi
function expects a &str
reference. But we passed &name
, which is a reference to a MySmartPointer<String>
.
Deref
coercion comes into play again:
The compiler sees the argument type
&MySmartPointer<String>
and the expected type&str
.MySmartPointer<String>
implementsDeref<Target=String>
, butsay_hi
needs&str
Behind the scenes, the compiler performs a double dereference.
First, it dereferences
&name
to get a reference&String
from inner&MySmartPointer<String>
.Then, because
String
implementsDeref<Target=str>
, it automatically dereferences again to the&String
to get the underlying string slice (&str
) thatsay_hi
can use.Finally, the
say_hi
function will get the correct string format and printHi, Thomas!
.
DerefMut
for Mutable Dereferencing
DerefMut
for Mutable DereferencingRust also provides the DerefMut
trait for mutable dereferencing.
Let’s dive a bit inside the Deref
implementation
DerefMut
trait inherits from the Deref
trait, it means it requires everything from Deref
and adds its own method.
The different here is the DerefMut
has a required method which is called deref_mut
. This method takes &mut self
(a mutable reference to the implementing type) as an argument and returns a mutable reference (&mut
) to the associated type Target
.
As the previous example, we have the MySmartPointer
smart pointer with implemented Deref
trait. In this updates, we will implement the DerefMut
trait for MySmartPointer
to demonstrate how we can dereference a mutable reference and mutate the data.
To allow dereference mutable reference for our smart pointer, we’re going to implement DerefMut
trait for MySmartPointer
. The deref_mut
method returns a mutable reference (&mut
) to the inner value (&self.0
- the .0
accesses the first value in a tuple struct). This allows dereferencing and mutating to the underlying data.
In the main function, we created a new mutable MySmartPointer
with the string “Thomas”.
The DerefMut
coercion happens in the name = String::from("Ashley")
line.
We’re assigning a new
String
("Ashley") to the dereferenced value ofname
.Deref
coercion happens becauseMySmartPointer
implementsDerefMut<Target=String>
.The compiler automatically dereferences
name
(which is a&mut MySmartPointer<String>
) usingderef_mut
to get a mutable reference (&mut String
) to the inner value, and then modifies the inner string through assignment*name
.Finally, the
say_hi
function will printHi, Ashley!
.
Last updated