The following is the Deref
example from The Rust Programming Language except I've added another assertion.
Why does the assert_eq
with the deref
also equal 'a'
? Why do I need a *
once I've manually called deref
?
use std::ops::Deref;
struct DerefExample<T> {
value: T,
}
impl<T> Deref for DerefExample<T> {
type Target = T;
fn deref(&self) -> &T {
&self.value
}
}
fn main() {
let x = DerefExample { value: 'a' };
assert_eq!('a', *x.deref()); // this is true
// assert_eq!('a', x.deref()); // this is a compile error
assert_eq!('a', *x); // this is also true
println!("ok");
}
If I uncomment the line, I get this error:
error[E0308]: mismatched types
--> src/main.rs:18:5
|
18 | assert_eq!('a', x.deref());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected char, found &char
|
= note: expected type `char`
found type `&char`
= help: here are some functions which might fulfill your needs:
- .to_ascii_lowercase()
- .to_ascii_uppercase()
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
First, let's spell out the generic types for your specific example:
'a'
ischar
, so we have:Notably, the return type of
deref
is a reference to achar
. Thus it shouldn't be surprising that, when you use justx.deref()
, the result is a&char
rather than achar
. Remember, at that pointderef
is just another normal method — it's just implicitly invoked as part of some language-provided special syntax.*x
, for example, will callderef
and dereference the result, when applicable.x.char_method()
andfn_taking_char(&x)
will also callderef
some number of times and then do something further with the result.Why does
deref
return a reference to begin with, you ask? Isn't that circular? Well, no, it isn't circular: it reduces library-defined smart pointers to the built-in type&T
which the compiler already knows how to dereference. By returning a reference instead of a value, you avoid a copy/move (which may not always be possible!) and allow&*x
(or&x
when it's coerced) to refer to the actualchar
thatDerefExample
holds rather than a temporary copy.See also: