Skip to content

Vec-growing logic emitted for Vecs which never grow #118563

@LingMan

Description

@LingMan

Consider these two examples:

pub fn foo(sizes: &[u64]) -> u64 {
    let mut top = Vec::with_capacity(1);
    for &size in sizes {
        /*if top.capacity() <= top.len() {
            unsafe { std::hint::unreachable_unchecked() }
        }*/
        top.push(size);
        top.pop();
    }
    top.iter().sum()
}
pub fn bar(sizes: &[u64]) -> u64 {
    const TOP_ELEMENTS: usize = 3;
    let mut top = Vec::with_capacity(TOP_ELEMENTS + 1);
    for &size in sizes {
        /*if top.capacity() <= top.len() {
            unsafe { std::hint::unreachable_unchecked() }
        }*/
        let i = 0; //top.partition_point(|&cur| cur > size);
        top.insert(i, size);
        top.truncate(TOP_ELEMENTS);
    }
    top.iter().sum()
}

Godbolt: https://rust.godbolt.org/z/PhrMr7dYr

Neither are ever going to grow their Vec from the initial size. Yet, RawVec::reserve_for_push and friends are emitted when compiling.
Uncommenting the unreachable_unchecked hints allows the optimizer to clean everything up. Might be asking a lot of the compiler but it would be great if it could figure that out by itself.

Tested with Rust 1.74 and with 1.76.0-nightly (87e1447 2023-11-30).

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchI-heavyIssue: Problems and improvements with respect to binary size of generated code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.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