From 7d716505c98fb81d2827a96b515130b5ab09f5ee Mon Sep 17 00:00:00 2001 From: Cristi Cobzarenco Date: Thu, 13 Oct 2016 14:04:30 +0100 Subject: [PATCH 1/3] DO NOT MERGE: implementation of RFC 1769 --- src/libcollections/borrow.rs | 21 +++++++++ src/libcollections/btree/map.rs | 53 +++++++++++++++------- src/libstd/collections/hash/map.rs | 70 +++++++++++++++++++----------- src/libstd/lib.rs | 1 + 4 files changed, 104 insertions(+), 41 deletions(-) diff --git a/src/libcollections/borrow.rs b/src/libcollections/borrow.rs index 6b45c25eb2139..c538732313ff5 100644 --- a/src/libcollections/borrow.rs +++ b/src/libcollections/borrow.rs @@ -69,6 +69,27 @@ impl ToOwned for T where T: Clone { } } +#[unstable(feature = "entry_into_owned", issue = "1")] +pub trait AsBorrowOf: Sized where T: Borrow { + #[unstable(feature = "entry_into_owned", issue = "1")] + fn into_owned(self) -> T; + + #[unstable(feature = "entry_into_owned", issue = "1")] + fn as_borrow_of(&self) -> &B; +} + +#[unstable(feature = "entry_into_owned", issue = "1")] +impl AsBorrowOf for T { + fn into_owned(self) -> T { self } + fn as_borrow_of(&self) -> &Self { self } +} + +#[unstable(feature = "entry_into_owned", issue = "1")] +impl<'a, B: ToOwned + ?Sized> AsBorrowOf for &'a B { + fn into_owned(self) -> B::Owned { self.to_owned() } + fn as_borrow_of(&self) -> &B { *self } +} + /// A clone-on-write smart pointer. /// /// The type `Cow` is a smart pointer providing clone-on-write functionality: it diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 788236c24d063..c4f5a99915f98 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -16,7 +16,7 @@ use core::marker::PhantomData; use core::ops::Index; use core::{fmt, intrinsics, mem, ptr}; -use borrow::Borrow; +use borrow::{Borrow, AsBorrowOf}; use Bound::{self, Excluded, Included, Unbounded}; use super::node::{self, Handle, NodeRef, marker}; @@ -324,11 +324,11 @@ pub struct RangeMut<'a, K: 'a, V: 'a> { /// [`BTreeMap`]: struct.BTreeMap.html /// [`entry`]: struct.BTreeMap.html#method.entry #[stable(feature = "rust1", since = "1.0.0")] -pub enum Entry<'a, K: 'a, V: 'a> { +pub enum Entry<'a, K: 'a, V: 'a, Q: 'a = K> { /// A vacant Entry #[stable(feature = "rust1", since = "1.0.0")] Vacant(#[stable(feature = "rust1", since = "1.0.0")] - VacantEntry<'a, K, V>), + VacantEntry<'a, K, V, Q>), /// An occupied Entry #[stable(feature = "rust1", since = "1.0.0")] @@ -337,7 +337,7 @@ pub enum Entry<'a, K: 'a, V: 'a> { } #[stable(feature= "debug_btree_map", since = "1.12.0")] -impl<'a, K: 'a + Debug + Ord, V: 'a + Debug> Debug for Entry<'a, K, V> { +impl<'a, K: 'a + Debug + Ord, V: 'a + Debug, Q: 'a + Debug> Debug for Entry<'a, K, V, Q> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Vacant(ref v) => f.debug_tuple("Entry") @@ -354,8 +354,8 @@ impl<'a, K: 'a + Debug + Ord, V: 'a + Debug> Debug for Entry<'a, K, V> { /// /// [`Entry`]: enum.Entry.html #[stable(feature = "rust1", since = "1.0.0")] -pub struct VacantEntry<'a, K: 'a, V: 'a> { - key: K, +pub struct VacantEntry<'a, K: 'a, V: 'a, Q: 'a = K> { + key: Q, handle: Handle, K, V, marker::Leaf>, marker::Edge>, length: &'a mut usize, @@ -364,10 +364,10 @@ pub struct VacantEntry<'a, K: 'a, V: 'a> { } #[stable(feature= "debug_btree_map", since = "1.12.0")] -impl<'a, K: 'a + Debug + Ord, V: 'a> Debug for VacantEntry<'a, K, V> { +impl<'a, K: 'a + Debug + Ord, V: 'a, Q: 'a + Debug> Debug for VacantEntry<'a, K, V, Q> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("VacantEntry") - .field(self.key()) + .field(&self.key) .finish() } } @@ -861,8 +861,12 @@ impl BTreeMap { /// assert_eq!(count["a"], 3); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn entry(&mut self, key: K) -> Entry { - match search::search_tree(self.root.as_mut(), &key) { + pub fn entry(&mut self, key: Q) -> Entry + where Q: AsBorrowOf, + K: Borrow, + B: Ord, + { + match search::search_tree(self.root.as_mut(), key.as_borrow_of()) { Found(handle) => { Occupied(OccupiedEntry { handle: handle, @@ -1960,7 +1964,7 @@ impl BTreeMap { } } -impl<'a, K: Ord, V> Entry<'a, K, V> { +impl<'a, K: Ord, V, Q> Entry<'a, K, V, Q> { /// Ensures a value is in the entry by inserting the default if empty, and returns /// a mutable reference to the value in the entry. /// @@ -1975,7 +1979,11 @@ impl<'a, K: Ord, V> Entry<'a, K, V> { /// assert_eq!(map["poneyland"], 12); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn or_insert(self, default: V) -> &'a mut V { + pub fn or_insert(self, default: V) -> &'a mut V + where Q: AsBorrowOf, + K: Borrow, + B: Ord + { match self { Occupied(entry) => entry.into_mut(), Vacant(entry) => entry.insert(default), @@ -1998,13 +2006,19 @@ impl<'a, K: Ord, V> Entry<'a, K, V> { /// assert_eq!(map["poneyland"], "hoho".to_owned()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn or_insert_with V>(self, default: F) -> &'a mut V { + pub fn or_insert_with V, B>(self, default: F) -> &'a mut V + where Q: AsBorrowOf, + K: Borrow, + B: Ord + { match self { Occupied(entry) => entry.into_mut(), Vacant(entry) => entry.insert(default()), } } +} +impl<'a, K: Ord, V> Entry<'a, K, V, K> { /// Returns a reference to this entry's key. /// /// # Examples @@ -2024,7 +2038,7 @@ impl<'a, K: Ord, V> Entry<'a, K, V> { } } -impl<'a, K: Ord, V> VacantEntry<'a, K, V> { +impl<'a, K: Ord, V> VacantEntry<'a, K, V, K> { /// Gets a reference to the key that would be used when inserting a value /// through the VacantEntry. /// @@ -2059,7 +2073,9 @@ impl<'a, K: Ord, V> VacantEntry<'a, K, V> { pub fn into_key(self) -> K { self.key } +} +impl<'a, K: Ord, V, Q> VacantEntry<'a, K, V, Q> { /// Sets the value of the entry with the `VacantEntry`'s key, /// and returns a mutable reference to it. /// @@ -2078,16 +2094,21 @@ impl<'a, K: Ord, V> VacantEntry<'a, K, V> { /// assert_eq!(count["a"], 3); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn insert(self, value: V) -> &'a mut V { + pub fn insert(self, value: V) -> &'a mut V + where Q: AsBorrowOf, + K: Borrow, + B: Ord + { *self.length += 1; let out_ptr; + let key = self.key.into_owned(); let mut ins_k; let mut ins_v; let mut ins_edge; - let mut cur_parent = match self.handle.insert(self.key, value) { + let mut cur_parent = match self.handle.insert(key, value) { (Fit(handle), _) => return handle.into_kv_mut().1, (Split(left, k, v, right), ptr) => { ins_k = k; diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index fb8a0c3c26554..8718abe2e1a90 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -11,7 +11,7 @@ use self::Entry::*; use self::VacantEntryState::*; -use borrow::Borrow; +use borrow::{Borrow, AsBorrowOf}; use cmp::max; use fmt::{self, Debug}; #[allow(deprecated)] @@ -967,10 +967,14 @@ impl HashMap /// assert_eq!(letters.get(&'y'), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn entry(&mut self, key: K) -> Entry { + pub fn entry(&mut self, key: Q) -> Entry + where Q: AsBorrowOf, + K: Borrow, + B: Hash + Eq + { // Gotta resize now. self.reserve(1); - self.search_mut(&key).into_entry(key).expect("unreachable") + self.search_mut(key.as_borrow_of()).into_entry(key).expect("unreachable") } /// Returns the number of elements in the map. @@ -1345,7 +1349,7 @@ impl InternalEntry { impl<'a, K, V> InternalEntry> { #[inline] - fn into_entry(self, key: K) -> Option> { + fn into_entry(self, key: Q) -> Option> { match self { InternalEntry::Occupied { elem } => { Some(Occupied(OccupiedEntry { @@ -1371,20 +1375,20 @@ impl<'a, K, V> InternalEntry> { /// [`HashMap`]: struct.HashMap.html /// [`entry`]: struct.HashMap.html#method.entry #[stable(feature = "rust1", since = "1.0.0")] -pub enum Entry<'a, K: 'a, V: 'a> { +pub enum Entry<'a, K: 'a, V: 'a, Q: 'a = K> { /// An occupied Entry. #[stable(feature = "rust1", since = "1.0.0")] Occupied(#[stable(feature = "rust1", since = "1.0.0")] - OccupiedEntry<'a, K, V>), + OccupiedEntry<'a, K, V, Q>), /// A vacant Entry. #[stable(feature = "rust1", since = "1.0.0")] Vacant(#[stable(feature = "rust1", since = "1.0.0")] - VacantEntry<'a, K, V>), + VacantEntry<'a, K, V, Q>), } #[stable(feature= "debug_hash_map", since = "1.12.0")] -impl<'a, K: 'a + Debug, V: 'a + Debug> Debug for Entry<'a, K, V> { +impl<'a, K: 'a + Debug, V: 'a + Debug, Q: 'a + Debug> Debug for Entry<'a, K, V, Q> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Vacant(ref v) => { @@ -1406,13 +1410,13 @@ impl<'a, K: 'a + Debug, V: 'a + Debug> Debug for Entry<'a, K, V> { /// /// [`Entry`]: enum.Entry.html #[stable(feature = "rust1", since = "1.0.0")] -pub struct OccupiedEntry<'a, K: 'a, V: 'a> { - key: Option, +pub struct OccupiedEntry<'a, K: 'a, V: 'a, Q: 'a = K> { + key: Option, elem: FullBucket>, } #[stable(feature= "debug_hash_map", since = "1.12.0")] -impl<'a, K: 'a + Debug, V: 'a + Debug> Debug for OccupiedEntry<'a, K, V> { +impl<'a, K: 'a + Debug, V: 'a + Debug, Q: 'a> Debug for OccupiedEntry<'a, K, V, Q> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("OccupiedEntry") .field("key", self.key()) @@ -1426,17 +1430,17 @@ impl<'a, K: 'a + Debug, V: 'a + Debug> Debug for OccupiedEntry<'a, K, V> { /// /// [`Entry`]: enum.Entry.html #[stable(feature = "rust1", since = "1.0.0")] -pub struct VacantEntry<'a, K: 'a, V: 'a> { +pub struct VacantEntry<'a, K: 'a, V: 'a, Q: 'a = K> { hash: SafeHash, - key: K, + key: Q, elem: VacantEntryState>, } #[stable(feature= "debug_hash_map", since = "1.12.0")] -impl<'a, K: 'a + Debug, V: 'a> Debug for VacantEntry<'a, K, V> { +impl<'a, K: 'a + Debug, V: 'a, Q: 'a + Debug> Debug for VacantEntry<'a, K, V, Q> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("VacantEntry") - .field(self.key()) + .field(&self.key) .finish() } } @@ -1668,7 +1672,7 @@ impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> { #[unstable(feature = "fused", issue = "35602")] impl<'a, K, V> FusedIterator for Drain<'a, K, V> {} -impl<'a, K, V> Entry<'a, K, V> { +impl<'a, K, V, Q> Entry<'a, K, V, Q> { #[stable(feature = "rust1", since = "1.0.0")] /// Ensures a value is in the entry by inserting the default if empty, and returns /// a mutable reference to the value in the entry. @@ -1686,7 +1690,11 @@ impl<'a, K, V> Entry<'a, K, V> { /// *map.entry("poneyland").or_insert(12) += 10; /// assert_eq!(map["poneyland"], 22); /// ``` - pub fn or_insert(self, default: V) -> &'a mut V { + pub fn or_insert(self, default: V) -> &'a mut V + where Q: AsBorrowOf, + K: Borrow, + B: Hash + Eq + { match self { Occupied(entry) => entry.into_mut(), Vacant(entry) => entry.insert(default), @@ -1709,13 +1717,19 @@ impl<'a, K, V> Entry<'a, K, V> { /// /// assert_eq!(map["poneyland"], "hoho".to_owned()); /// ``` - pub fn or_insert_with V>(self, default: F) -> &'a mut V { + pub fn or_insert_with V, B>(self, default: F) -> &'a mut V + where Q: AsBorrowOf, + K: Borrow, + B: Hash + Eq + { match self { Occupied(entry) => entry.into_mut(), Vacant(entry) => entry.insert(default()), } } +} +impl<'a, K, V> Entry<'a, K, V, K> { /// Returns a reference to this entry's key. /// /// # Examples @@ -1735,7 +1749,7 @@ impl<'a, K, V> Entry<'a, K, V> { } } -impl<'a, K, V> OccupiedEntry<'a, K, V> { +impl<'a, K, V, Q> OccupiedEntry<'a, K, V, Q> { /// Gets a reference to the key in the entry. /// /// # Examples @@ -1898,12 +1912,12 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> { /// Returns a key that was used for search. /// /// The key was retained for further use. - fn take_key(&mut self) -> Option { + fn take_key(&mut self) -> Option { self.key.take() } } -impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { +impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V, K> { /// Gets a reference to the key that would be used when inserting a value /// through the `VacantEntry`. /// @@ -1938,7 +1952,9 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { pub fn into_key(self) -> K { self.key } +} +impl<'a, K: 'a, V: 'a, Q: 'a> VacantEntry<'a, K, V, Q> { /// Sets the value of the entry with the VacantEntry's key, /// and returns a mutable reference to it. /// @@ -1956,10 +1972,14 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { /// assert_eq!(map["poneyland"], 37); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn insert(self, value: V) -> &'a mut V { + pub fn insert(self, value: V) -> &'a mut V + where Q: AsBorrowOf, + K: Borrow, + B: Hash + Eq + { match self.elem { - NeqElem(bucket, ib) => robin_hood(bucket, ib, self.hash, self.key, value), - NoElem(bucket) => bucket.put(self.hash, self.key, value).into_mut_refs().1, + NeqElem(bucket, ib) => robin_hood(bucket, ib, self.hash, self.key.into_owned(), value), + NoElem(bucket) => bucket.put(self.hash, self.key.into_owned(), value).into_mut_refs().1, } } } @@ -2135,7 +2155,7 @@ impl Default for RandomState { } impl super::Recover for HashMap - where K: Eq + Hash + Borrow, + where K: Eq + Hash + Borrow + Borrow, S: BuildHasher, Q: Eq + Hash { diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index c2f6a6f660c48..534f9219fc0c0 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -230,6 +230,7 @@ #![feature(core_intrinsics)] #![feature(dotdot_in_tuple_patterns)] #![feature(dropck_parametricity)] +#![feature(entry_into_owned)] #![feature(float_extras)] #![feature(float_from_str_radix)] #![feature(fn_traits)] From aa418d294e398881de17c428093391d84ec3e65e Mon Sep 17 00:00:00 2001 From: Cristi Cobzarenco Date: Thu, 13 Oct 2016 18:57:06 +0100 Subject: [PATCH 2/3] hacky fix to type inference issues in map entry docs --- src/libcollections/btree/map.rs | 1 + src/libstd/collections/hash/map.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index c4f5a99915f98..8fc0056d688a3 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -112,6 +112,7 @@ use self::Entry::*; /// // type inference lets us omit an explicit type signature (which /// // would be `BTreeMap<&str, u8>` in this example). /// let mut player_stats = BTreeMap::new(); +/// # {let __help_inference_out: &BTreeMap<&_, _> = &player_stats;} /// /// fn random_stat_buff() -> u8 { /// // could actually return some random value here - let's just return diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 8718abe2e1a90..faa1330c2fa4f 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -274,6 +274,7 @@ impl DefaultResizePolicy { /// // type inference lets us omit an explicit type signature (which /// // would be `HashMap<&str, u8>` in this example). /// let mut player_stats = HashMap::new(); +/// # {let __help_inference_out: &HashMap<&_, _> = &player_stats;} /// /// fn random_stat_buff() -> u8 { /// // could actually return some random value here - let's just return From ca81efbf9d01f04c2845ed26de193121c54af4fd Mon Sep 17 00:00:00 2001 From: Cristi Cobzarenco Date: Fri, 14 Oct 2016 16:33:57 +0100 Subject: [PATCH 3/3] update with crater knowledge: * B is now type parameter of `Entry`. * B is ?Sized in `.entry` methods on maps (previous oversight). * Deref coercions are now handled seamlessly by `AsBorrowOf`. --- src/libcollections/borrow.rs | 10 ++++- src/libcollections/btree/map.rs | 60 ++++++++++++++------------- src/libstd/collections/hash/map.rs | 65 +++++++++++++++++------------- 3 files changed, 77 insertions(+), 58 deletions(-) diff --git a/src/libcollections/borrow.rs b/src/libcollections/borrow.rs index c538732313ff5..22f71ca2562ad 100644 --- a/src/libcollections/borrow.rs +++ b/src/libcollections/borrow.rs @@ -80,8 +80,14 @@ pub trait AsBorrowOf: Sized where T: Borrow { #[unstable(feature = "entry_into_owned", issue = "1")] impl AsBorrowOf for T { - fn into_owned(self) -> T { self } - fn as_borrow_of(&self) -> &Self { self } + default fn into_owned(self) -> T { self } + default fn as_borrow_of(&self) -> &Self { self } +} + +#[unstable(feature = "entry_into_owned", issue = "1")] +impl<'a, T: Deref> AsBorrowOf<&'a T::Target, T::Target> for &'a T { + default fn into_owned(self) -> &'a T::Target { self.deref() } + default fn as_borrow_of(&self) -> &T::Target { self.deref() } } #[unstable(feature = "entry_into_owned", issue = "1")] diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 8fc0056d688a3..4a803f2428841 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -220,7 +220,7 @@ impl Clone for BTreeMap { } impl super::Recover for BTreeMap - where K: Borrow + Ord, + where K: Borrow + Borrow + Ord, Q: Ord { type Key = K; @@ -325,11 +325,11 @@ pub struct RangeMut<'a, K: 'a, V: 'a> { /// [`BTreeMap`]: struct.BTreeMap.html /// [`entry`]: struct.BTreeMap.html#method.entry #[stable(feature = "rust1", since = "1.0.0")] -pub enum Entry<'a, K: 'a, V: 'a, Q: 'a = K> { +pub enum Entry<'a, K: 'a, V: 'a, Q: 'a = K, B: 'a + ?Sized = K> { /// A vacant Entry #[stable(feature = "rust1", since = "1.0.0")] Vacant(#[stable(feature = "rust1", since = "1.0.0")] - VacantEntry<'a, K, V, Q>), + VacantEntry<'a, K, V, Q, B>), /// An occupied Entry #[stable(feature = "rust1", since = "1.0.0")] @@ -338,7 +338,12 @@ pub enum Entry<'a, K: 'a, V: 'a, Q: 'a = K> { } #[stable(feature= "debug_btree_map", since = "1.12.0")] -impl<'a, K: 'a + Debug + Ord, V: 'a + Debug, Q: 'a + Debug> Debug for Entry<'a, K, V, Q> { +impl<'a, K, V, Q, B: ?Sized> Debug for Entry<'a, K, V, Q, B> + where K: 'a + Debug + Ord, + V: 'a + Debug, + Q: 'a + Debug, + B: 'a +{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Vacant(ref v) => f.debug_tuple("Entry") @@ -355,17 +360,22 @@ impl<'a, K: 'a + Debug + Ord, V: 'a + Debug, Q: 'a + Debug> Debug for Entry<'a, /// /// [`Entry`]: enum.Entry.html #[stable(feature = "rust1", since = "1.0.0")] -pub struct VacantEntry<'a, K: 'a, V: 'a, Q: 'a = K> { +pub struct VacantEntry<'a, K: 'a, V: 'a, Q: 'a = K, B: 'a + ?Sized = K> { key: Q, handle: Handle, K, V, marker::Leaf>, marker::Edge>, length: &'a mut usize, // Be invariant in `K` and `V` - _marker: PhantomData<&'a mut (K, V)>, + _marker: PhantomData<&'a mut (K, V, B)>, } #[stable(feature= "debug_btree_map", since = "1.12.0")] -impl<'a, K: 'a + Debug + Ord, V: 'a, Q: 'a + Debug> Debug for VacantEntry<'a, K, V, Q> { +impl<'a, K, V, Q, B: ?Sized> Debug for VacantEntry<'a, K, V, Q, B> + where K: 'a + Debug + Ord, + V: 'a, + Q: 'a + Debug, + B: 'a +{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("VacantEntry") .field(&self.key) @@ -862,7 +872,7 @@ impl BTreeMap { /// assert_eq!(count["a"], 3); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn entry(&mut self, key: Q) -> Entry + pub fn entry(&mut self, key: Q) -> Entry where Q: AsBorrowOf, K: Borrow, B: Ord, @@ -1965,7 +1975,10 @@ impl BTreeMap { } } -impl<'a, K: Ord, V, Q> Entry<'a, K, V, Q> { +impl<'a, K, V, Q, B: ?Sized> Entry<'a, K, V, Q, B> + where K: Ord + Borrow, + Q: AsBorrowOf +{ /// Ensures a value is in the entry by inserting the default if empty, and returns /// a mutable reference to the value in the entry. /// @@ -1980,11 +1993,7 @@ impl<'a, K: Ord, V, Q> Entry<'a, K, V, Q> { /// assert_eq!(map["poneyland"], 12); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn or_insert(self, default: V) -> &'a mut V - where Q: AsBorrowOf, - K: Borrow, - B: Ord - { + pub fn or_insert(self, default: V) -> &'a mut V { match self { Occupied(entry) => entry.into_mut(), Vacant(entry) => entry.insert(default), @@ -2007,11 +2016,7 @@ impl<'a, K: Ord, V, Q> Entry<'a, K, V, Q> { /// assert_eq!(map["poneyland"], "hoho".to_owned()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn or_insert_with V, B>(self, default: F) -> &'a mut V - where Q: AsBorrowOf, - K: Borrow, - B: Ord - { + pub fn or_insert_with V>(self, default: F) -> &'a mut V { match self { Occupied(entry) => entry.into_mut(), Vacant(entry) => entry.insert(default()), @@ -2019,7 +2024,7 @@ impl<'a, K: Ord, V, Q> Entry<'a, K, V, Q> { } } -impl<'a, K: Ord, V> Entry<'a, K, V, K> { +impl<'a, K: Ord, V, B: ?Sized> Entry<'a, K, V, K, B> { /// Returns a reference to this entry's key. /// /// # Examples @@ -2039,7 +2044,7 @@ impl<'a, K: Ord, V> Entry<'a, K, V, K> { } } -impl<'a, K: Ord, V> VacantEntry<'a, K, V, K> { +impl<'a, K: Ord, V, B: ?Sized> VacantEntry<'a, K, V, K, B> { /// Gets a reference to the key that would be used when inserting a value /// through the VacantEntry. /// @@ -2076,7 +2081,10 @@ impl<'a, K: Ord, V> VacantEntry<'a, K, V, K> { } } -impl<'a, K: Ord, V, Q> VacantEntry<'a, K, V, Q> { +impl<'a, K, V, Q, B: ?Sized> VacantEntry<'a, K, V, Q, B> + where K: Ord + Borrow, + Q: AsBorrowOf +{ /// Sets the value of the entry with the `VacantEntry`'s key, /// and returns a mutable reference to it. /// @@ -2095,15 +2103,11 @@ impl<'a, K: Ord, V, Q> VacantEntry<'a, K, V, Q> { /// assert_eq!(count["a"], 3); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn insert(self, value: V) -> &'a mut V - where Q: AsBorrowOf, - K: Borrow, - B: Ord - { + pub fn insert(self, value: V) -> &'a mut V { *self.length += 1; let out_ptr; - let key = self.key.into_owned(); + let key = AsBorrowOf::::into_owned(self.key); let mut ins_k; let mut ins_v; diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index faa1330c2fa4f..89dad64a616f1 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -17,6 +17,7 @@ use fmt::{self, Debug}; #[allow(deprecated)] use hash::{Hash, Hasher, BuildHasher, SipHasher13}; use iter::{FromIterator, FusedIterator}; +use marker::PhantomData; use mem::{self, replace}; use ops::{Deref, Index}; use rand::{self, Rng}; @@ -968,7 +969,7 @@ impl HashMap /// assert_eq!(letters.get(&'y'), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn entry(&mut self, key: Q) -> Entry + pub fn entry(&mut self, key: Q) -> Entry where Q: AsBorrowOf, K: Borrow, B: Hash + Eq @@ -1350,7 +1351,11 @@ impl InternalEntry { impl<'a, K, V> InternalEntry> { #[inline] - fn into_entry(self, key: Q) -> Option> { + fn into_entry(self, key: Q) -> Option> + where Q: AsBorrowOf, + K: Borrow, + B: Hash + Eq + { match self { InternalEntry::Occupied { elem } => { Some(Occupied(OccupiedEntry { @@ -1363,6 +1368,7 @@ impl<'a, K, V> InternalEntry> { hash: hash, key: key, elem: elem, + _phantom: PhantomData, })) } InternalEntry::TableIsEmpty => None, @@ -1376,7 +1382,7 @@ impl<'a, K, V> InternalEntry> { /// [`HashMap`]: struct.HashMap.html /// [`entry`]: struct.HashMap.html#method.entry #[stable(feature = "rust1", since = "1.0.0")] -pub enum Entry<'a, K: 'a, V: 'a, Q: 'a = K> { +pub enum Entry<'a, K: 'a, V: 'a, Q: 'a = K, B: ?Sized + 'a = K> { /// An occupied Entry. #[stable(feature = "rust1", since = "1.0.0")] Occupied(#[stable(feature = "rust1", since = "1.0.0")] @@ -1385,11 +1391,13 @@ pub enum Entry<'a, K: 'a, V: 'a, Q: 'a = K> { /// A vacant Entry. #[stable(feature = "rust1", since = "1.0.0")] Vacant(#[stable(feature = "rust1", since = "1.0.0")] - VacantEntry<'a, K, V, Q>), + VacantEntry<'a, K, V, Q, B>), } #[stable(feature= "debug_hash_map", since = "1.12.0")] -impl<'a, K: 'a + Debug, V: 'a + Debug, Q: 'a + Debug> Debug for Entry<'a, K, V, Q> { +impl<'a, K, V, Q, B: ?Sized> Debug for Entry<'a, K, V, Q, B> + where K: 'a + Debug, V: 'a + Debug, Q: 'a + Debug, B: 'a +{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Vacant(ref v) => { @@ -1431,14 +1439,20 @@ impl<'a, K: 'a + Debug, V: 'a + Debug, Q: 'a> Debug for OccupiedEntry<'a, K, V, /// /// [`Entry`]: enum.Entry.html #[stable(feature = "rust1", since = "1.0.0")] -pub struct VacantEntry<'a, K: 'a, V: 'a, Q: 'a = K> { +pub struct VacantEntry<'a, K: 'a, V: 'a, Q: 'a = K, B: ?Sized + 'a = K> { hash: SafeHash, key: Q, elem: VacantEntryState>, + _phantom: PhantomData<&'a B>, } #[stable(feature= "debug_hash_map", since = "1.12.0")] -impl<'a, K: 'a + Debug, V: 'a, Q: 'a + Debug> Debug for VacantEntry<'a, K, V, Q> { +impl<'a, K, V, Q, B: ?Sized> Debug for VacantEntry<'a, K, V, Q, B> + where K: 'a + Debug, + V: 'a, + Q: 'a + Debug, + B: 'a +{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("VacantEntry") .field(&self.key) @@ -1673,7 +1687,9 @@ impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> { #[unstable(feature = "fused", issue = "35602")] impl<'a, K, V> FusedIterator for Drain<'a, K, V> {} -impl<'a, K, V, Q> Entry<'a, K, V, Q> { +impl<'a, K, V, Q, B: ?Sized> Entry<'a, K, V, Q, B> + where K: Borrow, Q: AsBorrowOf +{ #[stable(feature = "rust1", since = "1.0.0")] /// Ensures a value is in the entry by inserting the default if empty, and returns /// a mutable reference to the value in the entry. @@ -1691,11 +1707,7 @@ impl<'a, K, V, Q> Entry<'a, K, V, Q> { /// *map.entry("poneyland").or_insert(12) += 10; /// assert_eq!(map["poneyland"], 22); /// ``` - pub fn or_insert(self, default: V) -> &'a mut V - where Q: AsBorrowOf, - K: Borrow, - B: Hash + Eq - { + pub fn or_insert(self, default: V) -> &'a mut V { match self { Occupied(entry) => entry.into_mut(), Vacant(entry) => entry.insert(default), @@ -1718,11 +1730,7 @@ impl<'a, K, V, Q> Entry<'a, K, V, Q> { /// /// assert_eq!(map["poneyland"], "hoho".to_owned()); /// ``` - pub fn or_insert_with V, B>(self, default: F) -> &'a mut V - where Q: AsBorrowOf, - K: Borrow, - B: Hash + Eq - { + pub fn or_insert_with V>(self, default: F) -> &'a mut V { match self { Occupied(entry) => entry.into_mut(), Vacant(entry) => entry.insert(default()), @@ -1730,7 +1738,7 @@ impl<'a, K, V, Q> Entry<'a, K, V, Q> { } } -impl<'a, K, V> Entry<'a, K, V, K> { +impl<'a, K, V, B: ?Sized> Entry<'a, K, V, K, B> { /// Returns a reference to this entry's key. /// /// # Examples @@ -1918,7 +1926,7 @@ impl<'a, K, V, Q> OccupiedEntry<'a, K, V, Q> { } } -impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V, K> { +impl<'a, K: 'a, V: 'a, B: ?Sized + 'a> VacantEntry<'a, K, V, K, B> { /// Gets a reference to the key that would be used when inserting a value /// through the `VacantEntry`. /// @@ -1955,7 +1963,11 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V, K> { } } -impl<'a, K: 'a, V: 'a, Q: 'a> VacantEntry<'a, K, V, Q> { +impl<'a, K: 'a, V: 'a, Q: 'a, B: ?Sized + 'a> VacantEntry<'a, K, V, Q, B> + where K: 'a + Borrow, + V: 'a, + Q: 'a + AsBorrowOf +{ /// Sets the value of the entry with the VacantEntry's key, /// and returns a mutable reference to it. /// @@ -1973,14 +1985,11 @@ impl<'a, K: 'a, V: 'a, Q: 'a> VacantEntry<'a, K, V, Q> { /// assert_eq!(map["poneyland"], 37); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn insert(self, value: V) -> &'a mut V - where Q: AsBorrowOf, - K: Borrow, - B: Hash + Eq - { + pub fn insert(self, value: V) -> &'a mut V { + let key = AsBorrowOf::::into_owned(self.key); match self.elem { - NeqElem(bucket, ib) => robin_hood(bucket, ib, self.hash, self.key.into_owned(), value), - NoElem(bucket) => bucket.put(self.hash, self.key.into_owned(), value).into_mut_refs().1, + NeqElem(bucket, ib) => robin_hood(bucket, ib, self.hash, key, value), + NoElem(bucket) => bucket.put(self.hash, key, value).into_mut_refs().1, } } }