Skip to content

Vec::retain leaks items when predicate panics #52267

Closed
@stephaneyfx

Description

@stephaneyfx

Since the implementation of Vec::retain changed after Rust 1.25, items may not be dropped when the predicate panics.

Reproduction example

#[derive(Debug)]
struct Foo(i32);

impl Drop for Foo {
    fn drop(&mut self) {
        println!("Dropping Foo({})", self.0);
    }
}

fn main() {
    let mut v = (0..3).map(Foo).collect::<Vec<_>>();
    println!("Before retain");
    v.retain(|&Foo(n)| match n {
        0 => false,
        2 => panic!("Boo"),
        _ => true,
    });
    println!("After retain");
}

Expected result

All 3 Foo instances are dropped. The output should look like (with Rust 1.25):

Before retain
thread 'main' panicked at 'Boo', a.rs:15:14
note: Run with `RUST_BACKTRACE=1` for a backtrace.
Dropping Foo(1)
Dropping Foo(0)
Dropping Foo(2)

Actual result

Only one Foo instance is dropped. The output since Rust 1.26 (and with 1.27.1) is:

Before retain
Dropping Foo(0)
thread 'main' panicked at 'Boo', a.rs:15:14
note: Run with `RUST_BACKTRACE=1` for a backtrace.

Edited to clarify item leak (i.e. not dropped).

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-collectionsArea: `std::collections`C-bugCategory: This is a bug.T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions