1

For example, I have a struct with Deref implemented

use std::ops::{Deref, DerefMut, IndexMut};

#[derive(Debug)]
struct Selector<T> {
    elements: Vec<T>,
    current: usize
}

impl<T> Deref for Selector<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.elements[self.current]
    }
}

impl<T> DerefMut for Selector<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.elements[self.current]
    }
}

Then I do *s = 'w'; This means that rust is doing &s.elements[s.current] = 'w' which is the same as s.elements.index_mut(s.current) = 'w'; except index_mut returns a reference and you can't assign a reference to something so I changed the above to *&mut *s.elements.index_mut(s.current) = 'w';

So *s is the same as *s.deref_mut() where deref_mut is my implementation of Deref. So this leads me to think that *s is more like **s, where the first * calls my deref_mut method and the second * turns the resulting &mut T into mut T. Is rust adding another deref method after my implementation of Deref because deref_mut returns a reference? If so what is this called?

Does this mean that * and the deref method are different where one follows a pointer to data and the other one allows you to do something to a reference and then return another reference? Is rust implicitly inserting another * to convert the reference?

oberblastmeister
  • 864
  • 9
  • 13

1 Answers1

1

If x has type &T or &mut T, then *x has type T.

What if x has some other type S? If S implements Deref or DerefMut, then Rust will call .deref() or .deref_mut() on x, and dereference that.

Does this mean that * and the deref method are different where one follows a pointer to data and the other one allows you to do something to a reference and then return another reference?

Yes. The unary * operator follows a reference, and the deref traits coerce a non-reference into a reference.

Lambda Fairy
  • 13,814
  • 7
  • 42
  • 68
  • When I do `*s` the first `* `calls my deref_mut method but rust has to convert the `&mut T ` that deref_mut returned to `T` like you said. Does this mean rust is inserting another `* ` after turning the first `*` into my deref_mut to convert the reference? I only used one *` when I did `*s` so I am asking if rust implicitly inserts another `*`. – oberblastmeister Jun 22 '20 at 02:48
  • No, it does not insert another `*`. The `deref_mut` method converts `&mut Selector` to `&mut T`, and the `*` operator converts `&mut T` to `T`. – Lambda Fairy Jun 22 '20 at 04:51