Skip to content

Unexpected/wasteful handling of capacity by vec.split_off(0) #119913

Closed
@Zalathar

Description

@Zalathar

I was reviewing some code that uses split_off(0) in a loop to take the contents of a buffer, while leaving the buffer's capacity intact to be reused by subsequent iterations. When I double-checked the actual behaviour of split_off(0), I was surprised to find that the vector returned by split_off(0) had a much larger capacity than was necessary to hold its contents.

Consider this example program: (playground link)

fn main() {
    let mut buffer = Vec::with_capacity(100);
    buffer.extend([1u8, 2u8]);
    println!("buffer capacity: {}", buffer.capacity());
    println!();
    
    let split_off_1 = buffer.split_off(1);
    println!("split_off_1 capacity: {}", split_off_1.capacity());
    println!("buffer capacity: {}", buffer.capacity());
    println!();

    let split_off_0 = buffer.split_off(0);
    println!("split_off_0 capacity: {}", split_off_0.capacity());
    println!("buffer capacity: {}", buffer.capacity());
    println!();
}

I expected that the split_off_1 and split_off_0 vectors would have similar capacities, since they each only hold one value.

Instead, this happened:

buffer capacity: 100

split_off_1 capacity: 1
buffer capacity: 100

split_off_0 capacity: 100
buffer capacity: 100

The single-element vector produced by split_off(1) has a tight capacity of 1, but the single-element vector produced by split_off(0) has a wasteful capacity of 100, which is the same as the original vector's capacity.

(The method's documentation doesn't make any explicit promises about the capacity of the returned vector, so this isn't necessarily a bug per se, but it is a surprising behaviour.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.T-libsRelevant to the library team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions