This article is basically my own understanding of the Rust documentation article found here.
Code on Github: https://github.com/caveofprogramming/rust/
Why Can Box Be Dereferenced?
The following code dereferences Box
with *
to get the value out of Box
. This is what we’ll look at here. This is accomplished by implementing the Deref
trait.
Actually, with Box, the following code also works and prints the value 5, even without the dereference operator.
This second kind of behaviour apparently depends on special compiler support for deref coercion for types in the standard library, where values are automatically dereferenced. This isn’t going to work with our own types, although we could make it work by implementing the Display
trait.
A Tuple Struct
We start with a simple tuple struct. Tuple structs are like structs except the fields aren’t named.
The following code defines a tuple struct that can hold one integer value. We create a tuple struct and then print its value, using .0
to access its first field.
We can make this able to handle any type via generics.
Now the type T is inferred by the compiler, and we can successfully handle a float.
It is possible to explicitly define the type of thing that the tuple struct works with like this:
Adding a Constructor-Like Method
We can add a new
function that allows us to construct these tuple structs.
The name new
here is only a convention.
The first <T>
after impl
specifies that T
is a type that can be used in the rest of the definition. The <T>
after Value
says that Value
is actually a generic type and is going to work with whatever T
is.
Now we can create a Value like this:
But we still can’t use *
to get the numeric or other value out of our Value
struct.
To make that work we need to implement the Deref
trait.
Implementing Deref
We can implement Deref like this:
The type Target = T
here provides an associated type, T
, that will be returned by the dereference operator.
We can now do this:
Implicit Deref Coercion
Although we can’t pass a Value
to println!
without dereferencing it, there are circumstances under which Rust will actually dereference it as many times as necessary to get a value of the right type, and this happens at compile time.
Suppose we define a function like this:
And we have a Value
containing an i32
:
We still cannot pass this value directly to test()
, but if we pass a reference to a Value
containing an i32
, Rust will dereference it twice to coerce the Value
into an i32
.
This actually works!
Share this post