about summary refs log tree commit diff
path: root/library/alloc/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-03-22 04:03:53 +0000
committerbors <bors@rust-lang.org>2021-03-22 04:03:53 +0000
commit142c831861ba5a995fd9de99198e7f6074b6b400 (patch)
tree3a43c288d544f23fb39cc4f42834bea8170ebc0e /library/alloc/src
parent35385770ae1ea86a911cc44ac43f856831e44b26 (diff)
parent790c2ad46ac5d29903d75125679b7604dcc206fe (diff)
downloadrust-142c831861ba5a995fd9de99198e7f6074b6b400.tar.gz
rust-142c831861ba5a995fd9de99198e7f6074b6b400.zip
Auto merge of #83360 - Dylan-DPC:rollup-17xulpv, r=Dylan-DPC
Rollup of 9 pull requests

Successful merges:

 - #80193 (stabilize `feature(osstring_ascii)`)
 - #80771 (Make NonNull::as_ref (and friends) return refs with unbound lifetimes)
 - #81607 (Implement TrustedLen and TrustedRandomAccess for Range<integer>, array::IntoIter, VecDequeue's iterators)
 - #82554 (Fix invalid slice access in String::retain)
 - #82686 (Move `std::sys::unix::platform` to `std::sys::unix::ext`)
 - #82771 (slice: Stabilize IterMut::as_slice.)
 - #83329 (Cleanup LLVM debuginfo module docs)
 - #83336 (Fix ICE with `use clippy::a::b;`)
 - #83350 (Download a more recent LLVM version if `src/version` is modified)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'library/alloc/src')
-rw-r--r--library/alloc/src/collections/vec_deque/into_iter.rs32
-rw-r--r--library/alloc/src/collections/vec_deque/iter.rs24
-rw-r--r--library/alloc/src/collections/vec_deque/iter_mut.rs24
-rw-r--r--library/alloc/src/collections/vec_deque/mod.rs2
-rw-r--r--library/alloc/src/string.rs37
5 files changed, 100 insertions, 19 deletions
diff --git a/library/alloc/src/collections/vec_deque/into_iter.rs b/library/alloc/src/collections/vec_deque/into_iter.rs
index 465b058cd98..1c635dd4f27 100644
--- a/library/alloc/src/collections/vec_deque/into_iter.rs
+++ b/library/alloc/src/collections/vec_deque/into_iter.rs
@@ -1,5 +1,5 @@
 use core::fmt;
-use core::iter::FusedIterator;
+use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess};
 
 use super::VecDeque;
 
@@ -36,6 +36,22 @@ impl<T> Iterator for IntoIter<T> {
         let len = self.inner.len();
         (len, Some(len))
     }
+
+    #[inline]
+    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
+    where
+        Self: TrustedRandomAccess,
+    {
+        // Safety: The TrustedRandomAccess contract requires that callers only pass an index
+        // that is in bounds.
+        // Additionally Self: TrustedRandomAccess is only implemented for T: Copy which means even
+        // multiple repeated reads of the same index would be safe and the
+        // values are !Drop, thus won't suffer from double drops.
+        unsafe {
+            let idx = self.inner.wrap_add(self.inner.tail, idx);
+            self.inner.buffer_read(idx)
+        }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -55,3 +71,17 @@ impl<T> ExactSizeIterator for IntoIter<T> {
 
 #[stable(feature = "fused", since = "1.26.0")]
 impl<T> FusedIterator for IntoIter<T> {}
+
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<T> TrustedLen for IntoIter<T> {}
+
+#[doc(hidden)]
+#[unstable(feature = "trusted_random_access", issue = "none")]
+// T: Copy as approximation for !Drop since get_unchecked does not update the pointers
+// and thus we can't implement drop-handling
+unsafe impl<T> TrustedRandomAccess for IntoIter<T>
+where
+    T: Copy,
+{
+    const MAY_HAVE_SIDE_EFFECT: bool = false;
+}
diff --git a/library/alloc/src/collections/vec_deque/iter.rs b/library/alloc/src/collections/vec_deque/iter.rs
index ad31b991cb6..e4cfb3acdfd 100644
--- a/library/alloc/src/collections/vec_deque/iter.rs
+++ b/library/alloc/src/collections/vec_deque/iter.rs
@@ -1,5 +1,5 @@
 use core::fmt;
-use core::iter::FusedIterator;
+use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess};
 use core::ops::Try;
 
 use super::{count, wrap_index, RingSlices};
@@ -101,6 +101,19 @@ impl<'a, T> Iterator for Iter<'a, T> {
     fn last(mut self) -> Option<&'a T> {
         self.next_back()
     }
+
+    #[inline]
+    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
+    where
+        Self: TrustedRandomAccess,
+    {
+        // Safety: The TrustedRandomAccess contract requires that callers only  pass an index
+        // that is in bounds.
+        unsafe {
+            let idx = wrap_index(self.tail.wrapping_add(idx), self.ring.len());
+            self.ring.get_unchecked(idx)
+        }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -157,3 +170,12 @@ impl<T> ExactSizeIterator for Iter<'_, T> {
 
 #[stable(feature = "fused", since = "1.26.0")]
 impl<T> FusedIterator for Iter<'_, T> {}
+
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<T> TrustedLen for Iter<'_, T> {}
+
+#[doc(hidden)]
+#[unstable(feature = "trusted_random_access", issue = "none")]
+unsafe impl<T> TrustedRandomAccess for Iter<'_, T> {
+    const MAY_HAVE_SIDE_EFFECT: bool = false;
+}
diff --git a/library/alloc/src/collections/vec_deque/iter_mut.rs b/library/alloc/src/collections/vec_deque/iter_mut.rs
index 3d0c3094e26..9493676e66b 100644
--- a/library/alloc/src/collections/vec_deque/iter_mut.rs
+++ b/library/alloc/src/collections/vec_deque/iter_mut.rs
@@ -1,5 +1,5 @@
 use core::fmt;
-use core::iter::FusedIterator;
+use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess};
 use core::marker::PhantomData;
 
 use super::{count, wrap_index, RingSlices};
@@ -87,6 +87,19 @@ impl<'a, T> Iterator for IterMut<'a, T> {
     fn last(mut self) -> Option<&'a mut T> {
         self.next_back()
     }
+
+    #[inline]
+    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
+    where
+        Self: TrustedRandomAccess,
+    {
+        // Safety: The TrustedRandomAccess contract requires that callers only  pass an index
+        // that is in bounds.
+        unsafe {
+            let idx = wrap_index(self.tail.wrapping_add(idx), self.ring.len());
+            &mut *self.ring.get_unchecked_mut(idx)
+        }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -126,3 +139,12 @@ impl<T> ExactSizeIterator for IterMut<'_, T> {
 
 #[stable(feature = "fused", since = "1.26.0")]
 impl<T> FusedIterator for IterMut<'_, T> {}
+
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<T> TrustedLen for IterMut<'_, T> {}
+
+#[doc(hidden)]
+#[unstable(feature = "trusted_random_access", issue = "none")]
+unsafe impl<T> TrustedRandomAccess for IterMut<'_, T> {
+    const MAY_HAVE_SIDE_EFFECT: bool = false;
+}
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index 7a0de74eb23..d3e70991ad5 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -58,7 +58,7 @@ mod tests;
 const INITIAL_CAPACITY: usize = 7; // 2^3 - 1
 const MINIMUM_CAPACITY: usize = 1; // 2 - 1
 
-const MAXIMUM_ZST_CAPACITY: usize = 1 << (core::mem::size_of::<usize>() * 8 - 1); // Largest possible power of two
+const MAXIMUM_ZST_CAPACITY: usize = 1 << (usize::BITS - 1); // Largest possible power of two
 
 /// A double-ended queue implemented with a growable ring buffer.
 ///
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index cc2d440010b..f4ec4a36ffd 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -1289,37 +1289,44 @@ impl String {
     where
         F: FnMut(char) -> bool,
     {
-        let len = self.len();
-        let mut del_bytes = 0;
-        let mut idx = 0;
+        struct SetLenOnDrop<'a> {
+            s: &'a mut String,
+            idx: usize,
+            del_bytes: usize,
+        }
 
-        unsafe {
-            self.vec.set_len(0);
+        impl<'a> Drop for SetLenOnDrop<'a> {
+            fn drop(&mut self) {
+                let new_len = self.idx - self.del_bytes;
+                debug_assert!(new_len <= self.s.len());
+                unsafe { self.s.vec.set_len(new_len) };
+            }
         }
 
-        while idx < len {
-            let ch = unsafe { self.get_unchecked(idx..len).chars().next().unwrap() };
+        let len = self.len();
+        let mut guard = SetLenOnDrop { s: self, idx: 0, del_bytes: 0 };
+
+        while guard.idx < len {
+            let ch = unsafe { guard.s.get_unchecked(guard.idx..len).chars().next().unwrap() };
             let ch_len = ch.len_utf8();
 
             if !f(ch) {
-                del_bytes += ch_len;
-            } else if del_bytes > 0 {
+                guard.del_bytes += ch_len;
+            } else if guard.del_bytes > 0 {
                 unsafe {
                     ptr::copy(
-                        self.vec.as_ptr().add(idx),
-                        self.vec.as_mut_ptr().add(idx - del_bytes),
+                        guard.s.vec.as_ptr().add(guard.idx),
+                        guard.s.vec.as_mut_ptr().add(guard.idx - guard.del_bytes),
                         ch_len,
                     );
                 }
             }
 
             // Point idx to the next char
-            idx += ch_len;
+            guard.idx += ch_len;
         }
 
-        unsafe {
-            self.vec.set_len(len - del_bytes);
-        }
+        drop(guard);
     }
 
     /// Inserts a character into this `String` at a byte position.