diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2019-05-21 15:37:07 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2019-05-21 15:37:07 -0700 |
| commit | fe3dd0b50fef21d14591c960a9610bafb224cdbf (patch) | |
| tree | ee0b62d8e500d4ce4b6f50b4fe5d9056b9826072 /src/liballoc | |
| parent | e764f475ca7fffd6167ea991afc7d1b2b3f642dc (diff) | |
| parent | 50a0defd5a93523067ef239936cc2e0755220904 (diff) | |
| download | rust-fe3dd0b50fef21d14591c960a9610bafb224cdbf.tar.gz rust-fe3dd0b50fef21d14591c960a9610bafb224cdbf.zip | |
Merge remote-tracking branch 'origin/master' into azure-pipelines
Diffstat (limited to 'src/liballoc')
| -rw-r--r-- | src/liballoc/Cargo.toml | 1 | ||||
| -rw-r--r-- | src/liballoc/alloc.rs | 18 | ||||
| -rw-r--r-- | src/liballoc/collections/binary_heap.rs | 58 | ||||
| -rw-r--r-- | src/liballoc/collections/btree/map.rs | 40 | ||||
| -rw-r--r-- | src/liballoc/collections/btree/set.rs | 15 | ||||
| -rw-r--r-- | src/liballoc/collections/vec_deque.rs | 26 | ||||
| -rw-r--r-- | src/liballoc/lib.rs | 2 | ||||
| -rw-r--r-- | src/liballoc/rc.rs | 5 | ||||
| -rw-r--r-- | src/liballoc/string.rs | 26 | ||||
| -rw-r--r-- | src/liballoc/sync.rs | 5 | ||||
| -rw-r--r-- | src/liballoc/tests/btree/set.rs | 4 | ||||
| -rw-r--r-- | src/liballoc/tests/lib.rs | 1 | ||||
| -rw-r--r-- | src/liballoc/vec.rs | 28 |
13 files changed, 213 insertions, 16 deletions
diff --git a/src/liballoc/Cargo.toml b/src/liballoc/Cargo.toml index ddf0044c506..bcb27bb5161 100644 --- a/src/liballoc/Cargo.toml +++ b/src/liballoc/Cargo.toml @@ -33,3 +33,4 @@ harness = false [features] compiler-builtins-mem = ['compiler_builtins/mem'] +compiler-builtins-c = ["compiler_builtins/c"] diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index ddc6481eec7..41ff06d70ff 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -37,6 +37,8 @@ extern "Rust" { /// /// Note: while this type is unstable, the functionality it provides can be /// accessed through the [free functions in `alloc`](index.html#functions). +/// +/// [`Alloc`]: trait.Alloc.html #[unstable(feature = "allocator_api", issue = "32838")] #[derive(Copy, Clone, Default, Debug)] pub struct Global; @@ -54,6 +56,10 @@ pub struct Global; /// /// See [`GlobalAlloc::alloc`]. /// +/// [`Global`]: struct.Global.html +/// [`Alloc`]: trait.Alloc.html +/// [`GlobalAlloc::alloc`]: trait.GlobalAlloc.html#tymethod.alloc +/// /// # Examples /// /// ``` @@ -87,6 +93,10 @@ pub unsafe fn alloc(layout: Layout) -> *mut u8 { /// # Safety /// /// See [`GlobalAlloc::dealloc`]. +/// +/// [`Global`]: struct.Global.html +/// [`Alloc`]: trait.Alloc.html +/// [`GlobalAlloc::dealloc`]: trait.GlobalAlloc.html#tymethod.dealloc #[stable(feature = "global_alloc", since = "1.28.0")] #[inline] pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { @@ -105,6 +115,10 @@ pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { /// # Safety /// /// See [`GlobalAlloc::realloc`]. +/// +/// [`Global`]: struct.Global.html +/// [`Alloc`]: trait.Alloc.html +/// [`GlobalAlloc::realloc`]: trait.GlobalAlloc.html#method.realloc #[stable(feature = "global_alloc", since = "1.28.0")] #[inline] pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { @@ -124,6 +138,10 @@ pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 /// /// See [`GlobalAlloc::alloc_zeroed`]. /// +/// [`Global`]: struct.Global.html +/// [`Alloc`]: trait.Alloc.html +/// [`GlobalAlloc::alloc_zeroed`]: trait.GlobalAlloc.html#method.alloc_zeroed +/// /// # Examples /// /// ``` diff --git a/src/liballoc/collections/binary_heap.rs b/src/liballoc/collections/binary_heap.rs index c355361b53c..c5a0b6e877b 100644 --- a/src/liballoc/collections/binary_heap.rs +++ b/src/liballoc/collections/binary_heap.rs @@ -231,6 +231,20 @@ use super::SpecExtend; /// assert_eq!(heap.pop(), Some(Reverse(5))); /// assert_eq!(heap.pop(), None); /// ``` +/// +/// # Time complexity +/// +/// | [push] | [pop] | [peek]/[peek\_mut] | +/// |--------|----------|--------------------| +/// | O(1)~ | O(log n) | O(1) | +/// +/// The value for `push` is an expected cost; the method documentation gives a +/// more detailed analysis. +/// +/// [push]: #method.push +/// [pop]: #method.pop +/// [peek]: #method.peek +/// [peek\_mut]: #method.peek_mut #[stable(feature = "rust1", since = "1.0.0")] pub struct BinaryHeap<T> { data: Vec<T>, @@ -384,6 +398,10 @@ impl<T: Ord> BinaryHeap<T> { /// } /// assert_eq!(heap.peek(), Some(&2)); /// ``` + /// + /// # Time complexity + /// + /// Cost is O(1) in the worst case. #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] pub fn peek_mut(&mut self) -> Option<PeekMut<'_, T>> { if self.is_empty() { @@ -411,6 +429,11 @@ impl<T: Ord> BinaryHeap<T> { /// assert_eq!(heap.pop(), Some(1)); /// assert_eq!(heap.pop(), None); /// ``` + /// + /// # Time complexity + /// + /// The worst case cost of `pop` on a heap containing *n* elements is O(log + /// n). #[stable(feature = "rust1", since = "1.0.0")] pub fn pop(&mut self) -> Option<T> { self.data.pop().map(|mut item| { @@ -438,6 +461,22 @@ impl<T: Ord> BinaryHeap<T> { /// assert_eq!(heap.len(), 3); /// assert_eq!(heap.peek(), Some(&5)); /// ``` + /// + /// # Time complexity + /// + /// The expected cost of `push`, averaged over every possible ordering of + /// the elements being pushed, and over a sufficiently large number of + /// pushes, is O(1). This is the most meaningful cost metric when pushing + /// elements that are *not* already in any sorted pattern. + /// + /// The time complexity degrades if elements are pushed in predominantly + /// ascending order. In the worst case, elements are pushed in ascending + /// sorted order and the amortized cost per push is O(log n) against a heap + /// containing *n* elements. + /// + /// The worst case cost of a *single* call to `push` is O(n). The worst case + /// occurs when capacity is exhausted and needs a resize. The resize cost + /// has been amortized in the previous figures. #[stable(feature = "rust1", since = "1.0.0")] pub fn push(&mut self, item: T) { let old_len = self.len(); @@ -650,6 +689,10 @@ impl<T> BinaryHeap<T> { /// assert_eq!(heap.peek(), Some(&5)); /// /// ``` + /// + /// # Time complexity + /// + /// Cost is O(1) in the worst case. #[stable(feature = "rust1", since = "1.0.0")] pub fn peek(&self) -> Option<&T> { self.data.get(0) @@ -992,6 +1035,11 @@ impl<'a, T> Iterator for Iter<'a, T> { fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } + + #[inline] + fn last(mut self) -> Option<&'a T> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1047,6 +1095,11 @@ impl<T> Iterator for IntoIter<T> { fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } + + #[inline] + fn last(mut self) -> Option<T> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1093,6 +1146,11 @@ impl<T> Iterator for Drain<'_, T> { fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } + + #[inline] + fn last(mut self) -> Option<T> { + 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<usize>) { (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<usize>) { (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<K, V> Iterator for IntoIter<K, V> { fn size_hint(&self) -> (usize, Option<usize>) { (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<usize>) { 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<usize>) { 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<usize>) { 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<usize>) { 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<T> Iterator for IntoIter<T> { fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } + + #[inline] + fn last(mut self) -> Option<T> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] impl<T> DoubleEndedIterator for IntoIter<T> { @@ -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/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index d65c24f7350..31e49d06a7b 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1835,8 +1835,8 @@ impl<T> VecDeque<T> { /// 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 /// @@ -1848,6 +1848,20 @@ impl<T> VecDeque<T> { /// 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<F>(&mut self, mut f: F) where F: FnMut(&T) -> bool @@ -1934,8 +1948,6 @@ impl<T> VecDeque<T> { /// # Examples /// /// ``` - /// #![feature(vecdeque_rotate)] - /// /// use std::collections::VecDeque; /// /// let mut buf: VecDeque<_> = (0..10).collect(); @@ -1949,7 +1961,7 @@ impl<T> VecDeque<T> { /// } /// assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); /// ``` - #[unstable(feature = "vecdeque_rotate", issue = "56686")] + #[stable(feature = "vecdeque_rotate", since = "1.36.0")] pub fn rotate_left(&mut self, mid: usize) { assert!(mid <= self.len()); let k = self.len() - mid; @@ -1979,8 +1991,6 @@ impl<T> VecDeque<T> { /// # Examples /// /// ``` - /// #![feature(vecdeque_rotate)] - /// /// use std::collections::VecDeque; /// /// let mut buf: VecDeque<_> = (0..10).collect(); @@ -1994,7 +2004,7 @@ impl<T> VecDeque<T> { /// } /// assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); /// ``` - #[unstable(feature = "vecdeque_rotate", issue = "56686")] + #[stable(feature = "vecdeque_rotate", since = "1.36.0")] pub fn rotate_right(&mut self, k: usize) { assert!(k <= self.len()); let mid = self.len() - k; diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 2edd946ff11..d90036eaf49 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -109,7 +109,7 @@ #![feature(rustc_const_unstable)] #![feature(const_vec_new)] #![feature(slice_partition_dedup)] -#![feature(maybe_uninit, maybe_uninit_slice, maybe_uninit_array)] +#![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_array)] #![feature(alloc_layout_extra)] #![feature(try_trait)] #![feature(iter_nth_back)] diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 68eecd97ea1..0dffb19476f 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -932,6 +932,11 @@ impl<T: ?Sized + PartialEq> RcEqIdent<T> for Rc<T> { } } +/// We're doing this specialization here, and not as a more general optimization on `&T`, because it +/// would otherwise add a cost to all equality checks on refs. We assume that `Rc`s are used to +/// store large values, that are slow to clone, but also heavy to check for equality, causing this +/// cost to pay off more easily. It's also more likely to have two `Rc` clones, that point to +/// the same value, than two `&T`s. #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized + Eq> RcEqIdent<T> for Rc<T> { #[inline] diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index a3e2098695f..e74d37c1c2b 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 /// @@ -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<F>(&mut self, mut f: F) @@ -2179,6 +2189,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")] @@ -2367,6 +2385,10 @@ impl Iterator for Drain<'_> { fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } + #[inline] + fn last(mut self) -> Option<char> { + self.next_back() + } } #[stable(feature = "drain", since = "1.6.0")] diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 466e806663c..90c7859b3db 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -1377,6 +1377,11 @@ impl<T: ?Sized + PartialEq> ArcEqIdent<T> for Arc<T> { } } +/// We're doing this specialization here, and not as a more general optimization on `&T`, because it +/// would otherwise add a cost to all equality checks on refs. We assume that `Arc`s are used to +/// store large values, that are slow to clone, but also heavy to check for equality, causing this +/// cost to pay off more easily. It's also more likely to have two `Arc` clones, that point to +/// the same value, than two `&T`s. #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized + Eq> ArcEqIdent<T> for Arc<T> { #[inline] diff --git a/src/liballoc/tests/btree/set.rs b/src/liballoc/tests/btree/set.rs index d52814118b3..989beb3b1bf 100644 --- a/src/liballoc/tests/btree/set.rs +++ b/src/liballoc/tests/btree/set.rs @@ -143,8 +143,8 @@ fn test_union() { #[test] // Only tests the simple function definition with respect to intersection fn test_is_disjoint() { - let one = [1].into_iter().collect::<BTreeSet<_>>(); - let two = [2].into_iter().collect::<BTreeSet<_>>(); + let one = [1].iter().collect::<BTreeSet<_>>(); + let two = [2].iter().collect::<BTreeSet<_>>(); assert!(one.is_disjoint(&two)); } diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index b736750c576..ddb3120e89d 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -6,7 +6,6 @@ #![feature(repeat_generic_slice)] #![feature(try_reserve)] #![feature(unboxed_closures)] -#![feature(vecdeque_rotate)] #![deny(rust_2018_idioms)] use std::hash::{Hash, Hasher}; diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index cd62c3e0524..c0cdffe596b 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -937,8 +937,8 @@ impl<T> Vec<T> { /// 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 /// @@ -947,6 +947,16 @@ impl<T> Vec<T> { /// 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<F>(&mut self, mut f: F) where F: FnMut(&T) -> bool @@ -2385,6 +2395,11 @@ impl<T> Iterator for IntoIter<T> { fn count(self) -> usize { self.len() } + + #[inline] + fn last(mut self) -> Option<T> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -2504,6 +2519,11 @@ impl<T> Iterator for Drain<'_, T> { fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } + + #[inline] + fn last(mut self) -> Option<T> { + self.next_back() + } } #[stable(feature = "drain", since = "1.6.0")] @@ -2573,6 +2593,10 @@ impl<I: Iterator> Iterator for Splice<'_, I> { fn size_hint(&self) -> (usize, Option<usize>) { self.drain.size_hint() } + + fn last(mut self) -> Option<Self::Item> { + self.next_back() + } } #[stable(feature = "vec_splice", since = "1.21.0")] |
