0

consider this code, borrowed from this chapter from the official tutorial

fn main() {
    let a = [1, 2, 3, 4, 5];
    let b = [1, 2, 3, 4, 5];
    let slice = &a[1..3];
    let slice2 = &b[1..3];
    assert_eq!(slice, &[2, 3]);
    assert_eq!(slice2, &[2, 3]);
    assert_eq!(slice, slice2);
}

I would expect the assertions to fail. Why every reference points to the same memory? At first I thought that's because a and b and the subsequent slices are immutable, so multiple references can address the same memory without problems. But:

fn main(){
    let a = [1, 2, 3, 4, 5];
    let mut  b = [1, 2, 3, 4, 5];
    let slice = &a[1..3];
    let slice2 = &mut b[1..3];
    slice2[0] = 2;
    assert_eq!(slice, &[2, 3]);
    assert_eq!(slice2, &[2, 3]);
    assert_eq!(slice, slice2); 
}

Again no assertion fails, this time if I change one slice I definitely want two different references, one to the changed slice and one to the immutable one. However if I replace slice2[0] = 2; with slice2[0] = 6; (hence actually changing the slice) the assertions fail as expected. The possible causes I can imagine:

  • assert_eq! is comparing the actual values not the references. I couldn't verify this since printing the value of a reference right now is above my skill set; the documentation mentions that it uses PartialEq and I don't know how it is implemented for references
  • everything is done in a lazy fashion: only when and if one slice actually changes the new memory is allocated and the reference updated (the copy-on-write pattern)

Is this behavior documented somewhere?

JoulinRouge
  • 456
  • 4
  • 18
  • 1
    `a == b` is syntax sugar for `a.eq(b)`, `assert_eq!` uses the same methodology, then the correct implementation is looked for by following the auto-dereferencing rules, see [What are Rust's exact auto-dereferencing rules?](https://stackoverflow.com/questions/28519997/what-are-rusts-exact-auto-dereferencing-rules) – cafce25 Apr 02 '23 at 19:46
  • thanks @cafce25 , that explains it, if you want points write an answer I'll mark it as correct – JoulinRouge Apr 02 '23 at 19:58
  • 1
    The implementations for references are [here](https://doc.rust-lang.org/std/cmp/trait.PartialEq.html#impl-PartialEq%3C%26B%3E-for-%26A), which I think invokes [this slice-array impl](https://doc.rust-lang.org/std/cmp/trait.PartialEq.html#impl-PartialEq%3C%5BB%5D%3E-for-%5BA%3B%20N%5D), which then invokes the `i32` impl on each element. – drewtato Apr 02 '23 at 20:01

0 Answers0