When shloud we use Deref notation (*)?

I am a new rustacean.
we have Deref Coercions yet. So when should we add the * notation to the code by ourselves? Just when compiler mentioned?

like this code 1:

fn main() {
    let mut v = vec![1, 2, 3];
        let foobar = &mut v;
        foobar[0] = foobar[1] + 1;
    println!("{}", v[0]);

and this code 2:

fn main() {
    let mut v = vec![1, 2, 3];
        let foobar = &mut v;
        (*foobar)[0] = (*foobar)[1] + 1;
    println!("{}", v[0]);

These two codes did the same thing and have the same result.
I guess the reason is compiler did the Deref Coercions for code 1. (The real reason is auto-deref)
So, in the real-situations, What kind of the code should we write? code 1 or code 2?

Thank you!


from our discussion, we think that you should use Deref notation only when required.
First time, you may write the code without them, and add them by compiler’s error message. You’d better understand why there should be Deref notation.

You really only need to explicitly deref when working with

  1. smart pointers - Box<T>, Arc<T> etc (although in only in some cases, otherwise this is implicitly deref’d with “.”(dot))
  2. raw pointers (obviously)

otherwise, it’s not required and is just unnecessary semantics.

raw pointers? Such as borrow and mutable borrow?
I don’t think Rust have raw pointers really.

If you are using references to primitives there is often no ((typically dot)) operator so the you have to add the deref.

    fn t(a: &mut u8, b: &u8) {
        *a += b;

    struct S<'a>{a: &'a mut u8}
    let mut a = &mut 0;
    let mut s = S{a};
    *s.a = 1;
1 Like

yes rust has raw pointers. *const T and *mut T

what you’re referring to are references immutable and mutable references (&T & &mut T)

Oh, thank you :sweat_smile:

So, in that case, it will cause compile errors right?
then, can I say that we needn’t add Deref if compiler don’t mentioned?

Yes it's better (from readability point) to not add extra manually and leave the compiler to coerce.

Often (at least for me) (the same with adding &) you first write without and then use the error message to decide to add.

Thank you that you answered all which I’m confuse about

To avoid mixing up terms, deref coercion is a different (albeit related) feature; what’s being discussed in this thread is auto-deref (vs explicit deref).

1 Like

some body just told me that was Deref coercion, so, what’s the different between Deref coercion and auto-deref? Or are there any doc about it?

The classic example of deref coercion is:

fn takes_str_slice(s: &str) {}

fn main() {
   let s = "hello".to_string();

Technically, &s forms a &String. However, the compiler will perform a deref coercion to &str there, which is allowed because String: Deref<str>. Similarly, you can coerce a Vec<T> to a &[T]. There are certain contexts, such as method calls, where the compiler will attempt coercion if the immediate type is not valid (like in the above case where &String is an invalid type for the call).

auto deref is basically done by method calls. The dot operator there removes as many layers of reference as necessary to make the call:

// this is a &'static str
let s = "hello”;
// this is &&&...&'static str
let x = &&&&&&&&&&s;
// method call strips off as many layers of refs as needed
let len = x.len();

There’s a related autoref, which automatically borrows a value to make a method call on it:

let mut v = vec![1];
// autoref to get the &mut self for the push() call

So, v[x](v is a vector) is also a kind of method calls? because it did autoderef maybe.

[] is sugar for calling std::ops::Index::index() (or IndexMut::index_mut if in a mutable context) method.

It seems I need to learn deeply. So, any suggestion about when to use explicit deref?

What others have said is a good starting point. In general, use it only when required - compiler will tell you about those cases. And when they happen, try to understand why it’s required there - ask for help/clarification here if needed.