Make Vec::push return a &mut reference to the pushed value (original) (raw)

Proposal

Problem statement

Getting a reference to the value you just pushed to a vector requires an extra call and unwrap:

let mut v = Vec::new(); v.push(42); *v.last_mut().unwrap() = 43;

Motivating examples or use cases

I'm currently porting https://github.com/Naruyoko/OmegaNum.js/ to Rust, and this is a common pattern all over:
x.array[i+1]=(x.array[i+1]||0)+1;
This is directly translated as

if x.is_empty() { x.push(0); } let last_mut = x.last_mut().unwrap(); *last_mut += 1;

With this, this could be the following:

let last_mut = x.last_mut().unwrap_or(x.push(0)); *last_mut += 1;

which is much nicer.

Solution sketch

Change Vec::push to return a reference to the pushed value:

pub fn push(&mut self, value: T) -> &mut T { let len = self.len; if len == self.buf.capacity() { self.buf.grow_one(); } unsafe { let end = self.as_mut_ptr().add(len); ptr::write(end, value); self.len = len + 1; &mut *end } }

Alternatives

Alternatively, Vec::last_or_push(default: T) -> &T, along with 3 other variations for mutability and laziness, could make the above translate in only one line - maybe it would be better, but both would be nice. See issue #465.