Rust DISCUSSION

Rust error E0502 when pushing to a Vec while holding a reference to an element: why?

Started by gabriel borrow checkerE0502mutable borrowVec reallocationdangling reference
5 replies 248 views 6 participants
Latest activity · 30 Sep 2026

Rust error E0502 when pushing to a Vec while holding a reference to an element: why?

gabriel Rust Forum
#1

This fragment does not compile: let first = &v[0]; v.push(4); println!("{}", first);. The error is E0502: cannot borrow v as mutable because it is also borrowed as immutable. In C++ the equivalent code with a std::vector compiles without complaint.

I know the rule about one mutable reference or many shared ones, but I do not see what could actually go wrong here, since push only appends at the end. What is the compiler protecting me from, and what are the usual ways to restructure such code?

Community replies 5

Re: Rust error E0502 when pushing to a Vec while holding a reference to an element: why?

#2

push may reallocate. A vector with length 3 and capacity 3 has no room for a fourth element, so it allocates a larger block, moves the elements over and frees the old block. first would still point into the freed block, and the println! would read freed memory. In C++ this compiles and is the classic invalidated-reference bug: undefined behaviour that appears to work whenever the capacity happens to be sufficient.

The signature is fn push(&mut self, value: T). The &mut self says the method may change anything about the vector, so no other reference into it may be live across the call. The compiler does not look inside push; it checks signatures only.

Re: Rust error E0502 when pushing to a Vec while holding a reference to an element: why?

#3

A borrow lasts until the last use of the reference, not until the end of the enclosing block. So reordering is often enough: let first = &v[0]; println!("{}", first); v.push(4); compiles, because first is no longer used when push runs.

If the value is needed after the push, copy it out instead of borrowing it: let first = v[0]; for Copy types such as integers, or let first = v[0].clone(); for others. Then there is no outstanding borrow at all.

Re: Rust error E0502 when pushing to a Vec while holding a reference to an element: why?

#4

Another standard restructuring is to hold an index instead of a reference: let idx = 0; v.push(4); println!("{}", v[idx]);. An index is just a number. It borrows nothing and stays valid across a reallocation.

This is how graphs and trees are commonly built in Rust: nodes live in a Vec and the links between them are usize indexes. The trade-off is that an index can go stale if elements are removed. That shows up as a bounds-check panic or a logically wrong element, not as memory corruption.

Re: Rust error E0502 when pushing to a Vec while holding a reference to an element: why?

#5

The same error appears in a less obvious form with methods. let cfg = self.config(); self.update(); use_it(cfg); fails when config takes &self and update takes &mut self, because the getter's signature borrows all of self, even if it only returns one field.

Borrowing fields directly is tracked separately: let cfg = &self.config; self.counter += 1; compiles, since the compiler can see that the two fields are disjoint. For two elements of one slice, split_at_mut returns two non-overlapping mutable slices, and v.swap(i, j) covers the common case of exchanging two elements.

Re: Rust error E0502 when pushing to a Vec while holding a reference to an element: why?

#6

Modifying a collection while iterating over it is rejected for the same reason: for x in &v { if *x > 2 { v.push(*x); } }. Collect the changes first and apply them afterwards: let extra: Vec<i32> = v.iter().copied().filter(|x| *x > 2).collect(); v.extend(extra);.

RefCell is sometimes suggested, but it only moves the same check to run time: a conflicting borrow panics instead of failing to compile. It is a tool for shared-ownership designs, not a way to silence E0502. Running rustc --explain E0502 prints the full explanation with examples.

TEP COMMUNITY