From 08b0aca05e3709766fd7e0e01ec56a8511e4c46b Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 9 Apr 2019 13:40:21 -0700 Subject: string: implement From<&String> for String Allow Strings to be created from borrowed Strings. This is mostly to make things like passing &String to an `impl Into` parameter frictionless. --- src/liballoc/string.rs | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/liballoc/string.rs') diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index a3e2098695f..ace2b3ebf55 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -2179,6 +2179,14 @@ impl From<&str> for String { } } +#[stable(feature = "from_ref_string", since = "1.35.0")] +impl From<&String> for String { + #[inline] + fn from(s: &String) -> String { + s.clone() + } +} + // note: test pulls in libstd, which causes errors here #[cfg(not(test))] #[stable(feature = "string_from_box", since = "1.18.0")] -- cgit 1.4.1-3-g733a5 From 3e86cf36b5114f201868bf459934fe346a76a2d4 Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Fri, 19 Apr 2019 21:13:37 -0700 Subject: Add implementations of last in terms of next_back on a bunch of DoubleEndedIterators. r?Manishearth --- src/liballoc/collections/binary_heap.rs | 15 +++++++++++++ src/liballoc/collections/btree/map.rs | 40 +++++++++++++++++++++++++++++++++ src/liballoc/collections/btree/set.rs | 15 +++++++++++++ src/liballoc/string.rs | 4 ++++ src/liballoc/vec.rs | 14 ++++++++++++ src/libcore/ascii.rs | 2 ++ src/libcore/iter/adapters/mod.rs | 5 +++++ src/libcore/slice/mod.rs | 20 +++++++++++++++++ src/libcore/str/mod.rs | 20 +++++++++++++++++ src/libstd/env.rs | 6 +++++ src/libstd/path.rs | 10 +++++++++ src/libstd/sys/unix/args.rs | 2 ++ src/libstd/sys/wasm/args.rs | 4 ++++ src/libstd/sys/windows/args.rs | 2 ++ 14 files changed, 159 insertions(+) (limited to 'src/liballoc/string.rs') diff --git a/src/liballoc/collections/binary_heap.rs b/src/liballoc/collections/binary_heap.rs index 8c142a3d317..2b1e52cbf05 100644 --- a/src/liballoc/collections/binary_heap.rs +++ b/src/liballoc/collections/binary_heap.rs @@ -968,6 +968,11 @@ impl<'a, T> Iterator for Iter<'a, T> { fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + + #[inline] + fn last(mut self) -> Option<&'a T> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1023,6 +1028,11 @@ impl Iterator for IntoIter { fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1069,6 +1079,11 @@ impl Iterator for Drain<'_, T> { fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "drain", since = "1.6.0")] diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index 6b079fc87cc..414abb00ef1 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -1193,6 +1193,11 @@ impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> { fn size_hint(&self) -> (usize, Option) { (self.length, Some(self.length)) } + + #[inline] + fn last(mut self) -> Option<(&'a K, &'a V)> { + self.next_back() + } } #[stable(feature = "fused", since = "1.26.0")] @@ -1253,6 +1258,11 @@ impl<'a, K: 'a, V: 'a> Iterator for IterMut<'a, K, V> { fn size_hint(&self) -> (usize, Option) { (self.length, Some(self.length)) } + + #[inline] + fn last(mut self) -> Option<(&'a K, &'a mut V)> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1359,6 +1369,11 @@ impl Iterator for IntoIter { fn size_hint(&self) -> (usize, Option) { (self.length, Some(self.length)) } + + #[inline] + fn last(mut self) -> Option<(K, V)> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1421,6 +1436,11 @@ impl<'a, K, V> Iterator for Keys<'a, K, V> { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + + #[inline] + fn last(mut self) -> Option<&'a K> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1458,6 +1478,11 @@ impl<'a, K, V> Iterator for Values<'a, K, V> { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + + #[inline] + fn last(mut self) -> Option<&'a V> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1495,6 +1520,11 @@ impl<'a, K, V> Iterator for Range<'a, K, V> { unsafe { Some(self.next_unchecked()) } } } + + #[inline] + fn last(mut self) -> Option<(&'a K, &'a V)> { + self.next_back() + } } #[stable(feature = "map_values_mut", since = "1.10.0")] @@ -1508,6 +1538,11 @@ impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + + #[inline] + fn last(mut self) -> Option<&'a mut V> { + self.next_back() + } } #[stable(feature = "map_values_mut", since = "1.10.0")] @@ -1626,6 +1661,11 @@ impl<'a, K, V> Iterator for RangeMut<'a, K, V> { unsafe { Some(self.next_unchecked()) } } } + + #[inline] + fn last(mut self) -> Option<(&'a K, &'a mut V)> { + self.next_back() + } } impl<'a, K, V> RangeMut<'a, K, V> { diff --git a/src/liballoc/collections/btree/set.rs b/src/liballoc/collections/btree/set.rs index 16a96ca19b8..6f2467dfd6b 100644 --- a/src/liballoc/collections/btree/set.rs +++ b/src/liballoc/collections/btree/set.rs @@ -1019,6 +1019,11 @@ impl<'a, T> Iterator for Iter<'a, T> { fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + + #[inline] + fn last(mut self) -> Option<&'a T> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> DoubleEndedIterator for Iter<'a, T> { @@ -1044,6 +1049,11 @@ impl Iterator for IntoIter { fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for IntoIter { @@ -1073,6 +1083,11 @@ impl<'a, T> Iterator for Range<'a, T> { fn next(&mut self) -> Option<&'a T> { self.iter.next().map(|(k, _)| k) } + + #[inline] + fn last(mut self) -> Option<&'a T> { + self.next_back() + } } #[stable(feature = "btree_range", since = "1.17.0")] diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index a3e2098695f..f01610a7c3f 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -2367,6 +2367,10 @@ impl Iterator for Drain<'_> { fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "drain", since = "1.6.0")] diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index cd62c3e0524..50bb37b6ed2 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2385,6 +2385,11 @@ impl Iterator for IntoIter { fn count(self) -> usize { self.len() } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -2504,6 +2509,11 @@ impl Iterator for Drain<'_, T> { fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "drain", since = "1.6.0")] @@ -2573,6 +2583,10 @@ impl Iterator for Splice<'_, I> { fn size_hint(&self) -> (usize, Option) { self.drain.size_hint() } + + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "vec_splice", since = "1.21.0")] diff --git a/src/libcore/ascii.rs b/src/libcore/ascii.rs index c0ab364380f..ddee02ea232 100644 --- a/src/libcore/ascii.rs +++ b/src/libcore/ascii.rs @@ -117,6 +117,8 @@ impl Iterator for EscapeDefault { type Item = u8; fn next(&mut self) -> Option { self.range.next().map(|i| self.data[i]) } fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } + #[inline] + fn last(mut self) -> Option { self.next_back() } } #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for EscapeDefault { diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index 3ab404a48d3..d814e8a5958 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -73,6 +73,11 @@ impl Iterator for Rev where I: DoubleEndedIterator { { self.iter.position(predicate) } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index bf3dda48dc7..cda4268607f 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -3539,6 +3539,11 @@ impl<'a, T, P> Iterator for Split<'a, T, P> where P: FnMut(&T) -> bool { (1, Some(self.v.len() + 1)) } } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -3637,6 +3642,11 @@ impl<'a, T, P> Iterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool { (1, Some(self.v.len() + 1)) } } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -3702,6 +3712,11 @@ impl<'a, T, P> Iterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "slice_rsplit", since = "1.27.0")] @@ -3766,6 +3781,11 @@ impl<'a, T, P> Iterator for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "slice_rsplit", since = "1.27.0")] diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 379c263c04c..41399d21942 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1331,6 +1331,11 @@ impl<'a> Iterator for Lines<'a> { fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1377,6 +1382,11 @@ impl<'a> Iterator for LinesAny<'a> { fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -4215,6 +4225,11 @@ impl<'a> Iterator for SplitWhitespace<'a> { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "split_whitespace", since = "1.1.0")] @@ -4241,6 +4256,11 @@ impl<'a> Iterator for SplitAsciiWhitespace<'a> { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "split_ascii_whitespace", since = "1.34.0")] diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 01b301cb43d..6cb160067f7 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -740,6 +740,10 @@ impl Iterator for Args { self.inner.next().map(|s| s.into_string().unwrap()) } fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "env", since = "1.0.0")] @@ -775,6 +779,8 @@ impl Iterator for ArgsOs { type Item = OsString; fn next(&mut self) -> Option { self.inner.next() } fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + #[inline] + fn last(mut self) -> Option { self.next_back() } } #[stable(feature = "env", since = "1.0.0")] diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 1bbda9b5bcb..79ba37b2eb5 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -886,6 +886,11 @@ impl<'a> Iterator for Iter<'a> { fn next(&mut self) -> Option<&'a OsStr> { self.inner.next().map(Component::as_os_str) } + + #[inline] + fn last(mut self) -> Option<&'a OsStr> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -949,6 +954,11 @@ impl<'a> Iterator for Components<'a> { } None } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/unix/args.rs b/src/libstd/sys/unix/args.rs index 18de1096df2..f0594bb21bd 100644 --- a/src/libstd/sys/unix/args.rs +++ b/src/libstd/sys/unix/args.rs @@ -35,6 +35,8 @@ impl Iterator for Args { type Item = OsString; fn next(&mut self) -> Option { self.iter.next() } fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + #[inline] + fn last(mut self) -> Option { self.next_back() } } impl ExactSizeIterator for Args { diff --git a/src/libstd/sys/wasm/args.rs b/src/libstd/sys/wasm/args.rs index b3c77b86995..6766099c1ec 100644 --- a/src/libstd/sys/wasm/args.rs +++ b/src/libstd/sys/wasm/args.rs @@ -37,6 +37,10 @@ impl Iterator for Args { fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } impl ExactSizeIterator for Args { diff --git a/src/libstd/sys/windows/args.rs b/src/libstd/sys/windows/args.rs index b04bb484eed..744d7ec59d3 100644 --- a/src/libstd/sys/windows/args.rs +++ b/src/libstd/sys/windows/args.rs @@ -181,6 +181,8 @@ impl Iterator for Args { type Item = OsString; fn next(&mut self) -> Option { self.parsed_args_list.next() } fn size_hint(&self) -> (usize, Option) { self.parsed_args_list.size_hint() } + #[inline] + fn last(mut self) -> Option { self.next_back() } } impl DoubleEndedIterator for Args { -- cgit 1.4.1-3-g733a5 From 9b3583375dbd45b19b8ce8822b89ff79529354d6 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 29 Apr 2019 18:32:05 -0700 Subject: Document the order of {Vec,VecDeque,String}::retain It's natural for `retain` to work in order from beginning to end, but this wasn't actually documented to be the case. If we actually promise this, then the caller can do useful things like track the index of each element being tested, as [discussed in the forum][1]. This is now documented for `Vec`, `VecDeque`, and `String`. [1]: https://users.rust-lang.org/t/vec-retain-by-index/27697 `HashMap` and `HashSet` also have `retain`, and the `hashbrown` implementation does happen to use a plain `iter()` order too, but it's not certain that this should always be the case for these types. --- src/liballoc/collections/vec_deque.rs | 4 ++-- src/liballoc/string.rs | 4 ++-- src/liballoc/vec.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/liballoc/string.rs') diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index d65c24f7350..82a60f92444 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1835,8 +1835,8 @@ impl VecDeque { /// Retains only the elements specified by the predicate. /// /// In other words, remove all elements `e` such that `f(&e)` returns false. - /// This method operates in place and preserves the order of the retained - /// elements. + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. /// /// # Examples /// diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index a3e2098695f..aaa38142693 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -1200,8 +1200,8 @@ impl String { /// Retains only the characters specified by the predicate. /// /// In other words, remove all characters `c` such that `f(c)` returns `false`. - /// This method operates in place and preserves the order of the retained - /// characters. + /// This method operates in place, visiting each character exactly once in the + /// original order, and preserves the order of the retained characters. /// /// # Examples /// diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index cd62c3e0524..a9bc835010f 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -937,8 +937,8 @@ impl Vec { /// Retains only the elements specified by the predicate. /// /// In other words, remove all elements `e` such that `f(&e)` returns `false`. - /// This method operates in place and preserves the order of the retained - /// elements. + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. /// /// # Examples /// -- cgit 1.4.1-3-g733a5 From 0545375ca6822b4b140cd853f368473d69b76227 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 10 May 2019 18:01:50 -0700 Subject: Add examples of ordered retain --- src/liballoc/collections/vec_deque.rs | 14 ++++++++++++++ src/liballoc/string.rs | 10 ++++++++++ src/liballoc/vec.rs | 10 ++++++++++ 3 files changed, 34 insertions(+) (limited to 'src/liballoc/string.rs') diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 82a60f92444..9a8d48083e6 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1848,6 +1848,20 @@ impl VecDeque { /// buf.retain(|&x| x%2 == 0); /// assert_eq!(buf, [2, 4]); /// ``` + /// + /// The exact order may be useful for tracking external state, like an index. + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.extend(1..6); + /// + /// let keep = [false, true, true, false, true]; + /// let mut i = 0; + /// buf.retain(|_| (keep[i], i += 1).0); + /// assert_eq!(buf, [2, 3, 5]); + /// ``` #[stable(feature = "vec_deque_retain", since = "1.4.0")] pub fn retain(&mut self, mut f: F) where F: FnMut(&T) -> bool diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index aaa38142693..3fdcf95ccaa 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -1212,6 +1212,16 @@ impl String { /// /// assert_eq!(s, "foobar"); /// ``` + /// + /// The exact order may be useful for tracking external state, like an index. + /// + /// ``` + /// let mut s = String::from("abcde"); + /// let keep = [false, true, true, false, true]; + /// let mut i = 0; + /// s.retain(|_| (keep[i], i += 1).0); + /// assert_eq!(s, "bce"); + /// ``` #[inline] #[stable(feature = "string_retain", since = "1.26.0")] pub fn retain(&mut self, mut f: F) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index a9bc835010f..073d3ab5937 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -947,6 +947,16 @@ impl Vec { /// vec.retain(|&x| x%2 == 0); /// assert_eq!(vec, [2, 4]); /// ``` + /// + /// The exact order may be useful for tracking external state, like an index. + /// + /// ``` + /// let mut vec = vec![1, 2, 3, 4, 5]; + /// let keep = [false, true, true, false, true]; + /// let mut i = 0; + /// vec.retain(|_| (keep[i], i += 1).0); + /// assert_eq!(vec, [2, 3, 5]); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn retain(&mut self, mut f: F) where F: FnMut(&T) -> bool -- cgit 1.4.1-3-g733a5