-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Implement owned ops for HashSet
and BTreeSet
#109402
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
@rust-lang/libs-api: This adds the following binary operator impls shown in bold below. There is a pre-existing more restrictive impl corresponding to each one; the additional bounds required by the pre-existing impls are noted below. All of the following require
All of the following require
|
Team member @dtolnay has proposed to merge this. The next step is review by the rest of the tagged team members: No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
Add `minmax{,_by,_by_key}` functions to `core::cmp` This PR adds the following functions: ```rust // mod core::cmp #![unstable(feature = "cmp_minmax")] pub fn minmax<T>(v1: T, v2: T) -> [T; 2] where T: Ord; pub fn minmax_by<T, F>(v1: T, v2: T, compare: F) -> [T; 2] where F: FnOnce(&T, &T) -> Ordering; pub fn minmax_by_key<T, F, K>(v1: T, v2: T, mut f: F) -> [T; 2] where F: FnMut(&T) -> K, K: Ord; ``` (they are also `const` under `#[feature(const_cmp)]`, I've omitted `const` stuff for simplicity/readability) ---- Semantically these functions are equivalent to `{ let mut arr = [v1, v2]; arr.sort(); arr }`, but since they operate on 2 elements only, they are implemented as a single comparison. Even though that's basically a sort, I think "sort 2 elements" operation is useful on it's own in many cases. Namely, it's a common pattern when you have 2 things, and need to know which one is smaller/bigger to operate on them differently. I've wanted such functions countless times, most recently in rust-lang#109402, so I thought I'd propose them. ---- r? libs-api
Rollup merge of rust-lang#109409 - WaffleLapkin:progamer, r=dtolnay Add `minmax{,_by,_by_key}` functions to `core::cmp` This PR adds the following functions: ```rust // mod core::cmp #![unstable(feature = "cmp_minmax")] pub fn minmax<T>(v1: T, v2: T) -> [T; 2] where T: Ord; pub fn minmax_by<T, F>(v1: T, v2: T, compare: F) -> [T; 2] where F: FnOnce(&T, &T) -> Ordering; pub fn minmax_by_key<T, F, K>(v1: T, v2: T, mut f: F) -> [T; 2] where F: FnMut(&T) -> K, K: Ord; ``` (they are also `const` under `#[feature(const_cmp)]`, I've omitted `const` stuff for simplicity/readability) ---- Semantically these functions are equivalent to `{ let mut arr = [v1, v2]; arr.sort(); arr }`, but since they operate on 2 elements only, they are implemented as a single comparison. Even though that's basically a sort, I think "sort 2 elements" operation is useful on it's own in many cases. Namely, it's a common pattern when you have 2 things, and need to know which one is smaller/bigger to operate on them differently. I've wanted such functions countless times, most recently in rust-lang#109402, so I thought I'd propose them. ---- r? libs-api
It's going to be a small but weird asymmetry and an ergonomics papercut if some operators can take owned arguments and others cannot. Adding all the combinations would also fix the issue that code like |
☔ The latest upstream changes (presumably #128672) made this pull request unmergeable. Please resolve the merge conflicts. |
Approving this, but also, please do update the PR to support |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
The final comment period, with a disposition to merge, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. This will be merged soon. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!
I rebased to fix a trivial conflict with #128309 in library/alloc/src/collections/btree/set.rs.
|
I am on board with those new impls, but it'll need another FCP with the team so let's leave this to a followup PR. |
@bors r+ |
The job Click to see the possible cause of the failure (guessed by this bot)
|
@bors r- |
Method syntax like use std::collections::BTreeSet;
use std::ops::BitAnd;
fn f(a: BTreeSet<i32>, b: BTreeSet<i32>) {
let a = (a,);
let _ = a.0.bitand(&b);
drop(a.0);
} error[E0382]: use of moved value: `a.0`
--> src/main.rs:7:10
|
6 | let _ = a.0.bitand(&b);
| ---------- `a.0` moved due to this method call
7 | drop(a.0);
| ^^^ value used here after move
|
note: `bitand` takes ownership of the receiver `self`, which moves `a.0`
--> /git/rust/library/core/src/ops/bit.rs:161:15
|
161 | fn bitand(self, rhs: Rhs) -> Self::Output;
| ^^^^
= note: move occurs because `a.0` has type `BTreeSet<i32>`, which does not implement the `Copy` trait
help: you can `clone` the value and consume it, but this might not be your desired behavior
|
6 | let _ = a.0.clone().bitand(&b);
| ++++++++ |
Unfortunate that this happens, but ig there is nothing to do. Closing since this introduces a regression. |
This PR implements
ops::{BitAnd, BitOr, BitXor, Sub}
where one, or both arguments are owned (previously we only had impls for references to sets).The main advantage of these impls is lifted
T: Clone
bounds (and, in case ofHashSet
, liftedS: Default
). The secondary one is being able to reuse allocations. Lastly, they may (or may not) be more performant.Added public APIs (insta-stable):
I only added the "important" impls, i.e. such that allow lifting the bounds. Thus union-like ops (or, xor) have both arguments owned (because they need elements from both sets), while difference-like ops (sub, and) have only
self
owned (that's sufficient to not clone elements).Other potentially interesting implementations (in the order of most to least interesting according to myself):
BitAnd<Set<T, ...>> for Set<T, ...>
— optimization potential (can keep either allocation/iterate either set)BitOr<&Set<T, ...>> for Set<T, ...>
andBitOr<&Set<T, ...>> for Set<T, ...>
— still requireT: Clone
, but can keep the allocation/hasherBitOr<Set<T, ...>> for &Set<T, ...>
andBitOr<Set<T, ...>> for &Set<T, ...>
could be added for completenessBitAnd<Set<T, ...>> for &Set<T, ...>
— symmetry for completenessSub<Set<T, ...>> for Set<T, ...>
andSub<Set<T, ...>> for &Set<T, ...>
— completeness (no bounds lifting/optimization gains)r? libs-api