about summary refs log tree commit diff
diff options
context:
space:
mode:
authorThe8472 <git@infinite-source.de>2020-09-03 22:15:47 +0200
committerThe8472 <git@infinite-source.de>2020-09-03 22:15:47 +0200
commit2f23a0fccad2f4d85d2ec923f0ac40b4b42211a8 (patch)
tree1a29a504c97885e651353f41d4b3f0fa5aac5719
parent8e5fe5569b5ffd59f57e0dab4380ba04b063330e (diff)
downloadrust-2f23a0fccad2f4d85d2ec923f0ac40b4b42211a8.tar.gz
rust-2f23a0fccad2f4d85d2ec923f0ac40b4b42211a8.zip
fix debug assertion
The InPlaceIterable debug assert checks that the write pointer
did not advance beyond the read pointer. But TrustedRandomAccess
never advances the read pointer, thus triggering the assert.
Skip the assert if the source pointer did not change during iteration.
-rw-r--r--library/alloc/src/vec.rs22
1 files changed, 18 insertions, 4 deletions
diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs
index 5c474ab2cde..9013e3fc16a 100644
--- a/library/alloc/src/vec.rs
+++ b/library/alloc/src/vec.rs
@@ -2285,9 +2285,15 @@ where
             return SpecFromIterNested::from_iter(iterator);
         }
 
-        let (src_buf, dst_buf, dst_end, cap) = unsafe {
+        let (src_buf, src_ptr, dst_buf, dst_end, cap) = unsafe {
             let inner = iterator.as_inner().as_into_iter();
-            (inner.buf.as_ptr(), inner.buf.as_ptr() as *mut T, inner.end as *const T, inner.cap)
+            (
+                inner.buf.as_ptr(),
+                inner.ptr,
+                inner.buf.as_ptr() as *mut T,
+                inner.end as *const T,
+                inner.cap,
+            )
         };
 
         // use try-fold since
@@ -2302,10 +2308,18 @@ where
         let dst = mem::ManuallyDrop::new(sink).dst;
 
         let src = unsafe { iterator.as_inner().as_into_iter() };
-        // check if SourceIter and InPlaceIterable contracts were upheld.
+        // check if SourceIter contract was upheld
         // caveat: if they weren't we may not even make it to this point
         debug_assert_eq!(src_buf, src.buf.as_ptr());
-        debug_assert!(dst as *const _ <= src.ptr, "InPlaceIterable contract violation");
+        // check InPlaceIterable contract. This is only possible if the iterator advanced the
+        // source pointer at all. If it uses unchecked access via TrustedRandomAccess
+        // then the source pointer will stay in its initial position and we can't use it as reference
+        if src.ptr != src_ptr {
+            debug_assert!(
+                dst as *const _ <= src.ptr,
+                "InPlaceIterable contract violation, write pointer advanced beyond read pointer"
+            );
+        }
 
         // drop any remaining values at the tail of the source
         src.drop_remaining();