Skip to content

BTreeMap: make Ord bound explicit, compile-test its absence #81610

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

Merged
merged 1 commit into from
Feb 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 70 additions & 26 deletions library/alloc/src/collections/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for RangeMut<'_, K, V> {
}
}

impl<K: Ord, V> BTreeMap<K, V> {
impl<K, V> BTreeMap<K, V> {
/// Makes a new, empty `BTreeMap`.
///
/// Does not allocate anything on its own.
Expand All @@ -479,7 +479,10 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_btree_new", issue = "71835")]
pub const fn new() -> BTreeMap<K, V> {
pub const fn new() -> BTreeMap<K, V>
where
K: Ord,
{
BTreeMap { root: None, length: 0 }
}

Expand All @@ -498,7 +501,10 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert!(a.is_empty());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn clear(&mut self) {
pub fn clear(&mut self)
where
K: Ord,
{
*self = BTreeMap::new();
}

Expand All @@ -522,7 +528,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V>
where
K: Borrow<Q>,
K: Borrow<Q> + Ord,
Q: Ord,
{
let root_node = self.root.as_ref()?.reborrow();
Expand Down Expand Up @@ -550,7 +556,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
#[stable(feature = "map_get_key_value", since = "1.40.0")]
pub fn get_key_value<Q: ?Sized>(&self, k: &Q) -> Option<(&K, &V)>
where
K: Borrow<Q>,
K: Borrow<Q> + Ord,
Q: Ord,
{
let root_node = self.root.as_ref()?.reborrow();
Expand Down Expand Up @@ -578,7 +584,10 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert_eq!(map.first_key_value(), Some((&1, &"b")));
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn first_key_value(&self) -> Option<(&K, &V)> {
pub fn first_key_value(&self) -> Option<(&K, &V)>
where
K: Ord,
{
let root_node = self.root.as_ref()?.reborrow();
root_node.first_leaf_edge().right_kv().ok().map(Handle::into_kv)
}
Expand All @@ -604,7 +613,10 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert_eq!(*map.get(&2).unwrap(), "b");
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn first_entry(&mut self) -> Option<OccupiedEntry<'_, K, V>> {
pub fn first_entry(&mut self) -> Option<OccupiedEntry<'_, K, V>>
where
K: Ord,
{
let (map, dormant_map) = DormantMutRef::new(self);
let root_node = map.root.as_mut()?.borrow_mut();
let kv = root_node.first_leaf_edge().right_kv().ok()?;
Expand All @@ -631,7 +643,10 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert!(map.is_empty());
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn pop_first(&mut self) -> Option<(K, V)> {
pub fn pop_first(&mut self) -> Option<(K, V)>
where
K: Ord,
{
self.first_entry().map(|entry| entry.remove_entry())
}

Expand All @@ -652,7 +667,10 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert_eq!(map.last_key_value(), Some((&2, &"a")));
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn last_key_value(&self) -> Option<(&K, &V)> {
pub fn last_key_value(&self) -> Option<(&K, &V)>
where
K: Ord,
{
let root_node = self.root.as_ref()?.reborrow();
root_node.last_leaf_edge().left_kv().ok().map(Handle::into_kv)
}
Expand All @@ -678,7 +696,10 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert_eq!(*map.get(&2).unwrap(), "last");
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn last_entry(&mut self) -> Option<OccupiedEntry<'_, K, V>> {
pub fn last_entry(&mut self) -> Option<OccupiedEntry<'_, K, V>>
where
K: Ord,
{
let (map, dormant_map) = DormantMutRef::new(self);
let root_node = map.root.as_mut()?.borrow_mut();
let kv = root_node.last_leaf_edge().left_kv().ok()?;
Expand All @@ -705,7 +726,10 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert!(map.is_empty());
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn pop_last(&mut self) -> Option<(K, V)> {
pub fn pop_last(&mut self) -> Option<(K, V)>
where
K: Ord,
{
self.last_entry().map(|entry| entry.remove_entry())
}

Expand All @@ -729,7 +753,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
where
K: Borrow<Q>,
K: Borrow<Q> + Ord,
Q: Ord,
{
self.get(key).is_some()
Expand Down Expand Up @@ -758,7 +782,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut<Q: ?Sized>(&mut self, key: &Q) -> Option<&mut V>
where
K: Borrow<Q>,
K: Borrow<Q> + Ord,
Q: Ord,
{
let root_node = self.root.as_mut()?.borrow_mut();
Expand Down Expand Up @@ -795,7 +819,10 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert_eq!(map[&37], "c");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn insert(&mut self, key: K, value: V) -> Option<V> {
pub fn insert(&mut self, key: K, value: V) -> Option<V>
where
K: Ord,
{
match self.entry(key) {
Occupied(mut entry) => Some(entry.insert(value)),
Vacant(entry) => {
Expand Down Expand Up @@ -826,7 +853,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
where
K: Borrow<Q>,
K: Borrow<Q> + Ord,
Q: Ord,
{
self.remove_entry(key).map(|(_, v)| v)
Expand All @@ -853,7 +880,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
#[stable(feature = "btreemap_remove_entry", since = "1.45.0")]
pub fn remove_entry<Q: ?Sized>(&mut self, key: &Q) -> Option<(K, V)>
where
K: Borrow<Q>,
K: Borrow<Q> + Ord,
Q: Ord,
{
let (map, dormant_map) = DormantMutRef::new(self);
Expand Down Expand Up @@ -885,6 +912,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
#[unstable(feature = "btree_retain", issue = "79025")]
pub fn retain<F>(&mut self, mut f: F)
where
K: Ord,
F: FnMut(&K, &mut V) -> bool,
{
self.drain_filter(|k, v| !f(k, v));
Expand Down Expand Up @@ -919,7 +947,10 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert_eq!(a[&5], "f");
/// ```
#[stable(feature = "btree_append", since = "1.11.0")]
pub fn append(&mut self, other: &mut Self) {
pub fn append(&mut self, other: &mut Self)
where
K: Ord,
{
// Do we have to append anything at all?
if other.is_empty() {
return;
Expand Down Expand Up @@ -970,7 +1001,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
pub fn range<T: ?Sized, R>(&self, range: R) -> Range<'_, K, V>
where
T: Ord,
K: Borrow<T>,
K: Borrow<T> + Ord,
R: RangeBounds<T>,
{
if let Some(root) = &self.root {
Expand Down Expand Up @@ -1016,7 +1047,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
pub fn range_mut<T: ?Sized, R>(&mut self, range: R) -> RangeMut<'_, K, V>
where
T: Ord,
K: Borrow<T>,
K: Borrow<T> + Ord,
R: RangeBounds<T>,
{
if let Some(root) = &mut self.root {
Expand Down Expand Up @@ -1047,7 +1078,10 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert_eq!(count["a"], 3);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
pub fn entry(&mut self, key: K) -> Entry<'_, K, V>
where
K: Ord,
{
// FIXME(@porglezomp) Avoid allocating if we don't insert
let (map, dormant_map) = DormantMutRef::new(self);
let root_node = Self::ensure_is_owned(&mut map.root).borrow_mut();
Expand Down Expand Up @@ -1091,7 +1125,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
#[stable(feature = "btree_split_off", since = "1.11.0")]
pub fn split_off<Q: ?Sized + Ord>(&mut self, key: &Q) -> Self
where
K: Borrow<Q>,
K: Borrow<Q> + Ord,
{
if self.is_empty() {
return Self::new();
Expand Down Expand Up @@ -1149,12 +1183,16 @@ impl<K: Ord, V> BTreeMap<K, V> {
#[unstable(feature = "btree_drain_filter", issue = "70530")]
pub fn drain_filter<F>(&mut self, pred: F) -> DrainFilter<'_, K, V, F>
where
K: Ord,
F: FnMut(&K, &mut V) -> bool,
{
DrainFilter { pred, inner: self.drain_filter_inner() }
}

pub(super) fn drain_filter_inner(&mut self) -> DrainFilterInner<'_, K, V> {
pub(super) fn drain_filter_inner(&mut self) -> DrainFilterInner<'_, K, V>
where
K: Ord,
{
if let Some(root) = self.root.as_mut() {
let (root, dormant_root) = DormantMutRef::new(root);
let front = root.borrow_mut().first_leaf_edge();
Expand Down Expand Up @@ -1187,7 +1225,10 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// ```
#[inline]
#[unstable(feature = "map_into_keys_values", issue = "75294")]
pub fn into_keys(self) -> IntoKeys<K, V> {
pub fn into_keys(self) -> IntoKeys<K, V>
where
K: Ord,
{
IntoKeys { inner: self.into_iter() }
}

Expand All @@ -1210,7 +1251,10 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// ```
#[inline]
#[unstable(feature = "map_into_keys_values", issue = "75294")]
pub fn into_values(self) -> IntoValues<K, V> {
pub fn into_values(self) -> IntoValues<K, V>
where
K: Ord,
{
IntoValues { inner: self.into_iter() }
}
}
Expand Down Expand Up @@ -1967,9 +2011,9 @@ impl<K: Debug, V: Debug> Debug for BTreeMap<K, V> {
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<K: Ord, Q: ?Sized, V> Index<&Q> for BTreeMap<K, V>
impl<K, Q: ?Sized, V> Index<&Q> for BTreeMap<K, V>
where
K: Borrow<Q>,
K: Borrow<Q> + Ord,
Q: Ord,
{
type Output = V;
Expand Down
28 changes: 28 additions & 0 deletions library/alloc/src/collections/btree/map/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1706,6 +1706,34 @@ fn test_send() {
}
}

#[allow(dead_code)]
fn test_ord_absence() {
fn map<K>(mut map: BTreeMap<K, ()>) {
map.is_empty();
map.len();
map.iter();
map.iter_mut();
map.keys();
map.values();
map.values_mut();
map.into_iter();
}

fn map_debug<K: Debug>(mut map: BTreeMap<K, ()>) {
format!("{:?}", map);
format!("{:?}", map.iter());
format!("{:?}", map.iter_mut());
format!("{:?}", map.keys());
format!("{:?}", map.values());
format!("{:?}", map.values_mut());
format!("{:?}", map.into_iter());
}

fn map_clone<K: Clone>(mut map: BTreeMap<K, ()>) {
map.clone_from(&map.clone());
}
}

#[allow(dead_code)]
fn test_const() {
const MAP: &'static BTreeMap<(), ()> = &BTreeMap::new();
Expand Down
Loading