fn main() {
let a: Vec<i32> = vec![1,2,3];
let b: &i32 = &a[2];
println!("{a:?}, {b}");
}
Should I think of b as path number 2 in the image below, or paths number 1a and 1b (although in this case I'm unsure how it directs to 1b unless it remembers the offset, somehow ?
heap_addr_of_data_of_a is a reference to the whole slice on the heap. &a[0] is a reference to the first element of the slice. The latter can only access the first element, the former allows you to inspect all elements of the slice.
Both are semantically equivalent. &a is shorter, but &a[..] a bit more expressive. I wouldn't consider one to be more idiomatic than the other, but that's just my opinion.
Keep in mind that although it only "actually" stores the address of the item when running (with the usual "behaves as-if it follows the rules" caveats once you enable optimizations), the borrow is still a reborrow of the implicit borrow of the Vec when you constructed it, and therefore it prevents simultaneous mutable references to any other item (or the Vec itself, eg with a push()) as a compile-time check.