I was reading the docs for Rust's Deref
trait:
pub trait Deref {
type Target: ?Sized;
fn deref(&self) -> &Self::Target;
}
The type signature for the deref
function seems counter-intuitive to me; why is the return type a reference? If references implement this trait so they can be dereferenced, what effect would this have at all?
The only explanation that I can come up with is that references don't implement Deref
, but are considered "primitively dereferenceable". However, how would a polymorphic function which would work for any dereferenceable type, including both Deref<T>
and &T
, be written then?
that references don't implement Deref
You can see all the types that implement Deref
, and &T
is in that list:
impl<'a, T> Deref for &'a T where T: ?Sized
The non-obvious thing is that there is syntactical sugar being applied when you use the *
operator with something that implements Deref
. Check out this small example:
use std::ops::Deref;
fn main() {
let s: String = "hello".into();
let _: () = Deref::deref(&s);
let _: () = *s;
}
error[E0308]: mismatched types
--> src/main.rs:5:17
|
5 | let _: () = Deref::deref(&s);
| ^^^^^^^^^^^^^^^^ expected (), found &str
|
= note: expected type `()`
found type `&str`
error[E0308]: mismatched types
--> src/main.rs:6:17
|
6 | let _: () = *s;
| ^^ expected (), found str
|
= note: expected type `()`
found type `str`
The explicit call to deref
returns a &str
, but the operator *
returns a str
. It's more like you are calling *Deref::deref(&s)
, ignoring the implied infinite recursion.
Xirdus is correct in saying
If deref
returned a value, it would either be useless because it would always move out, or have semantics that drastically differ from every other function
Although "useless" is a bit strong; it would still be useful for types that implement Copy
.
See also:
- Why does asserting on the result of Deref::deref fail with a type mismatch?
The compiler knows only how to dereference &-pointers - but it also knows that types that implement Deref
trait have a deref()
method that can be used to get an appropriate reference to something inside given object. If you dereference an object, what you actually do is first obtain the reference and only then dereference it.
If deref()
returned a value, it would either be useless because it would always move out, or have semantics that drastically differ from every other function which is not nice.