-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
BTree: remove Ord bound where it is absent elsewhere #79245
Conversation
I think this should have a reviewer from T-libs. r? @dtolnay , maybe? |
This comment has been minimized.
This comment has been minimized.
354791a
to
df32dbc
Compare
@rustbot modify labels: +S-waiting-on-review -S-waiting-on-author |
@rust-lang/libs: This affects the following individual stable APIs. There are four kinds:
impl<K, V> BTreeMap<K, V> {
pub const fn new() -> BTreeMap<K, V>
- where
- K: Ord;
pub fn clear(&mut self)
- where
- K: Ord;
pub fn get<Q>(&self, key: &Q) -> Option<&V>
where
- K: Ord + Borrow<Q>,
+ K: Borrow<Q>,
Q: ?Sized + Ord;
pub fn get_key_value<Q>(&self, k: &Q) -> Option<(&K, &V)>
where
- K: Ord + Borrow<Q>,
+ K: Borrow<Q>,
Q: ?Sized + Ord;
pub fn contains_key<Q>(&self, key: &Q) -> bool
where
- K: Ord + Borrow<Q>,
+ K: Borrow<Q>,
Q: ?Sized + Ord;
pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
where
- K: Ord + Borrow<Q>,
+ K: Borrow<Q>,
Q: ?Sized + Ord;
pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
where
- K: Ord + Borrow<Q>,
+ K: Borrow<Q>,
Q: ?Sized + Ord;
pub fn remove_entry<Q>(&mut self, key: &Q) -> Option<(K, V)>
where
- K: Ord + Borrow<Q>,
+ K: Borrow<Q>,
Q: ?Sized + Ord;
pub fn range<T, R>(&self, range: R) -> Range<'_, K, V>
where
- K: Ord + Borrow<T>,
+ K: Borrow<T>,
T: ?Sized + Ord,
R: RangeBounds<T>;
pub fn range_mut<T, R>(&mut self, range: R) -> RangeMut<'_, K, V>
where
- K: Ord + Borrow<T>,
+ K: Borrow<T>,
T: ?Sized + Ord,
R: RangeBounds<T>;
pub fn split_off<Q>(&mut self, key: &Q) -> Self
where
- K: Ord + Borrow<Q>,
+ K: Borrow<Q>,
Q: ?Sized + Ord;
}
impl<K, V> Default for BTreeMap<K, V>
- where
- K: Ord;
impl<K, V> Debug for Entry<'_, K, V>
where
- K: Ord + Debug,
+ K: Debug,
V: Debug;
impl<K, V> Debug for VacantEntry<'_, K, V>
where
- K: Ord + Debug,
+ K: Debug;
impl<K, V> Debug for OccupiedEntry<'_, K, V>
where
- K: Ord + Debug,
+ K: Debug,
V: Debug;
impl<'a, K, V> Entry<'a, K, V> {
pub fn or_insert(self, default: V) -> &'a mut V
- where
- K: Ord;
pub fn or_insert_with<F>(self, default: F) -> &'a mut V
where
- K: Ord,
F: FnOnce() -> V;
pub fn key(&self) -> &K
- where
- K: Ord;
pub fn and_modify<F>(self, f: F) -> Self
where
- K: Ord,
F: FnOnce(&mut V);
pub fn or_default(self) -> &'a mut V
where
- K: Ord,
V: Default;
}
impl<'a, K, V> VacantEntry<'a, K, V> {
pub fn key(&self) -> &K
- where
- K: Ord;
pub fn into_key(self) -> K
- where
- K: Ord;
pub fn insert(self, value: V) -> &'a mut V
- where
- K: Ord;
}
impl<'a, K, V> OccupiedEntry<'a, K, V> {
pub fn key(&self) -> &K
- where
- K: Ord;
pub fn remove_entry(self) -> (K, V)
- where
- K: Ord;
pub fn get(&self) -> &V
- where
- K: Ord;
pub fn get_mut(&mut self) -> &mut V
- where
- K: Ord;
pub fn into_mut(self) -> &'a mut V
- where
- K: Ord;
pub fn insert(&mut self, value: V) -> V
- where
- K: Ord;
pub fn remove(self) -> V
- where
- K: Ord;
}
impl<T> BTreeSet<T> {
pub const fn new() -> BTreeSet<T>
- where
- T: Ord;
pub fn range<K, R>(&self, range: R) -> Range<'_, T>
where
- T: Ord + Borrow<K>,
+ T: Borrow<K>,
K: ?Sized + Ord,
R: RangeBounds<K>;
pub fn symmetric_difference<'a>(&'a self, other: &'a BTreeSet<T>) -> SymmetricDifference<'a, T>
- where
- T: Ord;
pub fn union<'a>(&'a self, other: &'a BTreeSet<T>) -> Union<'a, T>
- where
- T: Ord;
pub fn clear(&mut self)
- where
- T: Ord;
pub fn contains<Q>(&self, value: &Q) -> bool
where
+ T: Ord + Borrow<Q>,
- T: Borrow<Q>,
Q: ?Sized + Ord;
pub fn remove<Q>(&mut self, value: &Q) -> bool
where
- T: Ord + Borrow<Q>,
+ T: Borrow<Q>,
Q: ?Sized + Ord;
pub fn split_off<Q>(&mut self, key: &Q) -> Self
where
- T: Ord + Borrow<Q>,
+ T: Borrow<Q>,
Q: ?Sized + Ord;
}
impl<T> Default for BTreeSet<T>
- where
- T: Ord; |
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. |
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.
I would request to keep the Ord
bound on all Entry methods that mutate the collection, and on symmetric_difference/union.
df32dbc
to
4438474
Compare
Does that include the methods that do not actually mutate but allow mutation, i.e., |
4438474
to
21a276c
Compare
Pointing out that inconsistency in the initial form of this PR, answers my implicit question: why impose unused bounds anywhere? It allows tuning the implementation later. Another inconsistency is that That leaves version 2 with this set of changes: impl<K, V> BTreeMap<K, V> {
pub const fn new() -> BTreeMap<K, V>
- where
- K: Ord;
pub fn clear(&mut self)
- where
- K: Ord;
}
impl<K, V> Default for BTreeMap<K, V>
- where
- K: Ord;
}
impl<K, V> Debug for Entry<'_, K, V>
where
- K: Ord + Debug,
+ K: Debug,
V: Debug;
}
impl<K, V> Debug for VacantEntry<'_, K, V>
where
- K: Ord + Debug,
+ K: Debug;
}
impl<K, V> Debug for OccupiedEntry<'_, K, V>
where
- K: Ord + Debug,
+ K: Debug,
V: Debug;
}
impl<'a, K, V> Entry<'a, K, V> {
pub fn key(&self) -> &K
- where
- K: Ord;
}
impl<'a, K, V> VacantEntry<'a, K, V> {
pub fn key(&self) -> &K
- where
- K: Ord;
pub fn into_key(self) -> K
- where
- K: Ord;
}
impl<'a, K, V> OccupiedEntry<'a, K, V> {
pub fn key(&self) -> &K
- where
- K: Ord;
pub fn get(&self) -> &V
- where
- K: Ord;
pub fn get_mut(&mut self) -> &mut V
- where
- K: Ord;
pub fn into_mut(self) -> &'a mut V
- where
- K: Ord;
}
impl<T> BTreeSet<T> {
pub const fn new() -> BTreeSet<T>
- where
- T: Ord;
pub fn clear(&mut self)
- where
- T: Ord;
}
impl<T> Default for BTreeSet<T>
- where
- T: Ord; |
Can someone say why we would want to do this, other than minor simplifications in the type signature? Is there a concrete benefit to this? Conversely, if we do this and accidentally remove |
|
Thanks for explaining! I'm a little skeptical that those things are worth the risk here personally. The last bullet point (writing generic code) seems the most compelling to me I think, but I'm having a hard time of thinking of how that actually happens in practice. |
21a276c
to
083ce57
Compare
…ulacrum BTreeSet: simplify implementation of pop_first/pop_last …and stop it interfering in rust-lang#79245. r? `@Mark-Simulacrum`
…ulacrum BTreeSet: simplify implementation of pop_first/pop_last …and stop it interfering in rust-lang#79245. r? ``@Mark-Simulacrum``
…ulacrum BTreeSet: simplify implementation of pop_first/pop_last …and stop it interfering in rust-lang#79245. r? ```@Mark-Simulacrum```
Could someone make an updated list of every API change, like #79245 (comment)? This PR is difficult to review otherwise because all the API changes are taking place in lines of code that are not touched. |
For review it might even be better to do this as 2 PRs, one moving |
11e7edb
to
a5a4563
Compare
a5a4563
to
9066c73
Compare
I backed out on all changes in |
This is a subset of the changes from the prior completed FCP. impl<K, V> BTreeMap<K, V> {
pub fn clear(&mut self)
- where
- K: Ord;
}
impl<T> BTreeSet<T> {
pub fn clear(&mut self)
- where
- T: Ord;
} and a few unstable ones (tracking issue #75294): impl<K, V> BTreeMap<K, V> {
pub fn into_keys(self) -> IntoKeys<K, V>
- where
- K: Ord;
-
pub fn into_values(self) -> IntoValues<K, V>
- where
- K: Ord;
} |
@bors r+ |
📌 Commit 9066c73 has been approved by |
☀️ Test successful - checks-actions |
|
I wouldn't know the answer even if I understood the question, but as a summary: the only change to the public stable API is that |
BTree: remove Ord bound from new `K: Ord` bound is unnecessary on `BTree{Map,Set}::new` and their `Default` impl. No elements exist so there are nothing to compare anyway, so I don't think "future proof" would be a blocker here. This is analogous to `HashMap::new` not having a `K: Eq + Hash` bound. rust-lang#79245 originally does this and for some reason drops the change to `new` and `Default`. I can see why changes to other methods like `entry` or `symmetric_difference` need to be careful but I couldn't find out any reason not to do it on `new`. Removing the bound also makes the stabilisation of `const fn new` not depending on const trait bounds. cc `@steffahn` who suggests me to make this PR. r? `@dtolnay`
Some btree methods don't really need an Ord bound and don't have one, while some methods that more obviously don't need it, do have one.
An example of the former is
iter
, even though it explicitly exposes the work of the Ord implementation ("sorted by key" - but I'm not suggesting it should have the Ord bound). An example of the latter isnew
, which doesn't involve any keys whatsoever.