I am currently working through the Rust Book (Brown University version). The quizzes really help a lot to keep me on my toes, but now I stumbled upon a question / solution I don't fully understand.
The final quiz of Chapter 15.5 asks which of the code snippets would violate memory safety.
I get why this would be the case in the correct answer (the vector could have been relocated due to the push, so the reference to its first element might be invalid).
But I don't understand why option 4 would be fine. My reasoning: with the first push, the vector might have been relocated, so the push with the second reference might be referencing an invalid location.
Its more like the underlying buffer of the vector can reallocate due to the push, not the vector itself. The vector itself is basically a fat pointer consisting of length and capacity fields plus a pointer to some heap-allocated memory containing the vector's elements. If the capacity of the heap-allocation is too little to fit another element when it is pushed, a new heap allocation is created, causing the reallocation of the previous elements to the new location. So references inside the vector (i.e. to its elements) are problematic, if they were allowed to exist while one could still push new elements to the vector.
Rust code is incorrect if it exhibits any of the behaviors in the following list.
Breaking the pointer aliasing rules. … &mut T must point to memory that is not read or written by any pointer not derived from the reference and that no other reference points to while they are live.
v1 and v2 are both &mut Vec<i32>, and v2 points to memory which is mutated while v2 is live (through v1, which is not derived from v2), so this code contains UB.
Many of the quiz questions that were worded like "This code does not compile, but now we pretend it compiles, so what would be the problem" were so confusing to me, and I spend a lot of time trying to understand the answers.