Skip to content

Make Vec::push return a &mut reference to the pushed value #464

Closed as not planned
@balt-dev

Description

@balt-dev

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    T-libs-apiapi-change-proposalA proposal to add or alter unstable APIs in the standard libraries

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions