diff options
| author | The8472 <git@infinite-source.de> | 2020-09-03 22:15:47 +0200 |
|---|---|---|
| committer | The8472 <git@infinite-source.de> | 2020-09-03 22:15:47 +0200 |
| commit | 2f23a0fccad2f4d85d2ec923f0ac40b4b42211a8 (patch) | |
| tree | 1a29a504c97885e651353f41d4b3f0fa5aac5719 | |
| parent | 8e5fe5569b5ffd59f57e0dab4380ba04b063330e (diff) | |
| download | rust-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.rs | 22 |
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(); |
