Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove drain-on-drop behavior from various DrainFilter iterators #136

Closed
the8472 opened this issue Nov 15, 2022 · 7 comments
Closed

Remove drain-on-drop behavior from various DrainFilter iterators #136

the8472 opened this issue Nov 15, 2022 · 7 comments
Labels
ACP-accepted API Change Proposal is accepted (seconded with no objections) api-change-proposal A proposal to add or alter unstable APIs in the standard libraries T-libs-api

Comments

@the8472
Copy link
Member

the8472 commented Nov 15, 2022

Proposal

Problem statement

The current implementations can double-panic (via a panic-drop-panic cascade), may become aborts even on a single panic if the deny panic-in-drop RFC goes through and are not consistent with general Iterator laziness.

Motivation, use-cases

A panicking closure can lead to a double-panic while iterating. Playground link

#![feature(drain_filter)]
use std::collections::LinkedList;

fn main() {
    let mut c = LinkedList::from([1, 2, 3]);
    let _c = c.drain_filter(|_| panic!("panic")).collect::<Vec<_>>();
}

Solution sketches

Add #[must_use] and remove drain-on-drop behavior from the drain_filter impls for these collections:

  • Vec
  • LinkedList
  • BTree{Map, Set}
  • Hash{Map, Set}

Since it'll be redundant needed it will also remove vec::DrainFilter::keep_rest()

Additionally drain_filter can be renamed to extract_filter🚲🏚️ to avoid similarity to Drain which will retain its drain-on-drop behavior since it's less problematic as it doesn't evaluate a closure for each item. To be bikeshed.

Limitations

This may cause surprises with short-circuiting iterators. That can be worked around (unergonomically) by taking by_ref and then exhausting the rest once the main use is completed or by avoiding short-circuiting ops.

Links and related work

What happens now?

This issue is part of the libs-api team API change proposal process. Once this issue is filed the libs-api team will review open proposals in its weekly meeting. You should receive feedback within a week or two.

@Amanieu
Copy link
Member

Amanieu commented Nov 29, 2022

Seconded. I think this is actually quite intuitive: only elements that are returned from the iterator are actually removed from the collection.

@Amanieu Amanieu added the initial-comment-period Will be merged/postponed/closed in ~10 calendar days unless new substational objections are raised. label Nov 29, 2022
@Mark-Simulacrum
Copy link
Member

I think renaming is a good idea, not least because the alternative is breaking people in a pretty subtle way as they upgrade their nightly version. (None of these are stable, right?)

Is the recommended pattern if you want the old behavior something like .for_each(|_| {}) to preserve performance? Or is there something better?

@the8472
Copy link
Member Author

the8472 commented Nov 29, 2022

(None of these are stable, right?)

Correct.

Is the recommended pattern if you want the old behavior something like .for_each(|_| {}) to preserve performance? Or is there something better?

For most collections there's a retain method and my PR directs users to use it when they don't need the iterator.

Only LinkedList doesn't have that. But there you can't do much better than .for_each(drop) anyway.

@Mark-Simulacrum
Copy link
Member

Ah, I see. I guess we stabilized retain_mut on Vec too now. Still, the rename seems like a good idea to avoid future confusion and subtle breakage now, even if most users not actively iterating have a better path in retain today.

@the8472
Copy link
Member Author

the8472 commented Nov 29, 2022

Sure. Any preferences?

  • extract_if
  • extract_filter{ed}
  • take_if
  • ...

@Mark-Simulacrum
Copy link
Member

No particular preferences from me.

@the8472
Copy link
Member Author

the8472 commented Apr 7, 2023

This has been seconded and no objections have been registered, so I'm closing the issue as approved.

@the8472 the8472 closed this as completed Apr 7, 2023
bors added a commit to rust-lang/hashbrown that referenced this issue Apr 11, 2023
Remove drain-on-drop behavior from DrainFilter

This is a breaking change for hashbrown but not for std because in std the drain impl is still unstable.

This is part of stdlib [ACP 136](rust-lang/libs-team#136).
bors added a commit to rust-lang-ci/rust that referenced this issue Jun 15, 2023
Don't drain-on-drop in DrainFilter impls of various collections.

This removes drain-on-drop behavior from various unstable DrainFilter impls (not yet for HashSet/Map) because that behavior [is problematic](rust-lang#43244 (comment)) (because it can lead to panic-in-drop when user closures panic) and may become forbidden if [this draft RFC passes](rust-lang/rfcs#3288).

closes rust-lang#101122

[ACP](rust-lang/libs-team#136)

affected tracking issues
* rust-lang#43244
* rust-lang#70530
* rust-lang#59618

Related hashbrown update: rust-lang/hashbrown#374
oli-obk pushed a commit to oli-obk/miri that referenced this issue Jun 15, 2023
Don't drain-on-drop in DrainFilter impls of various collections.

This removes drain-on-drop behavior from various unstable DrainFilter impls (not yet for HashSet/Map) because that behavior [is problematic](rust-lang/rust#43244 (comment)) (because it can lead to panic-in-drop when user closures panic) and may become forbidden if [this draft RFC passes](rust-lang/rfcs#3288).

closes #101122

[ACP](rust-lang/libs-team#136)

affected tracking issues
* #43244
* #70530
* #59618

Related hashbrown update: rust-lang/hashbrown#374
thomcc pushed a commit to tcdi/postgrestd that referenced this issue Aug 24, 2023
Don't drain-on-drop in DrainFilter impls of various collections.

This removes drain-on-drop behavior from various unstable DrainFilter impls (not yet for HashSet/Map) because that behavior [is problematic](rust-lang/rust#43244 (comment)) (because it can lead to panic-in-drop when user closures panic) and may become forbidden if [this draft RFC passes](rust-lang/rfcs#3288).

closes #101122

[ACP](rust-lang/libs-team#136)

affected tracking issues
* #43244
* #70530
* #59618

Related hashbrown update: rust-lang/hashbrown#374
@dtolnay dtolnay added ACP-accepted API Change Proposal is accepted (seconded with no objections) and removed initial-comment-period Will be merged/postponed/closed in ~10 calendar days unless new substational objections are raised. labels Nov 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ACP-accepted API Change Proposal is accepted (seconded with no objections) api-change-proposal A proposal to add or alter unstable APIs in the standard libraries T-libs-api
Projects
None yet
Development

No branches or pull requests

4 participants