From 2f23a0fccad2f4d85d2ec923f0ac40b4b42211a8 Mon Sep 17 00:00:00 2001 From: The8472 Date: Thu, 3 Sep 2020 22:15:47 +0200 Subject: [PATCH] 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. --- library/alloc/src/vec.rs | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs index 5c474ab2cde57..9013e3fc16ab9 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();