Skip to content

Commit bddd849

Browse files
committed
fix prepend_from_within not wrapping for non Copy types, add tests
1 parent 5b66d03 commit bddd849

File tree

2 files changed

+187
-6
lines changed

2 files changed

+187
-6
lines changed

library/alloc/src/collections/vec_deque/mod.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3165,14 +3165,31 @@ impl<T: Clone, A: Allocator> SpecExtendFromWithin for VecDeque<T, A> {
31653165
let src = src.start + count;
31663166

31673167
let new_head = self.wrap_sub(self.head, count);
3168+
let cap = self.capacity();
31683169

31693170
unsafe {
31703171
// SAFETY:
31713172
// - Ranges do not overlap: src entirely spans initialized values, dst entirely spans uninitialized values.
31723173
// - Ranges are in bounds: guaranteed by the caller.
31733174
let ranges = self.nonoverlapping_ranges(src, dst, count, new_head);
3174-
for (src, dst, count) in ranges.into_iter().rev() {
3175-
for offset in (0..count).rev() {
3175+
let (src, dst, count) = ranges[1];
3176+
for offset in (0..count).rev() {
3177+
dst.add(offset).write((*src.add(offset)).clone());
3178+
self.head -= 1;
3179+
self.len += 1;
3180+
}
3181+
3182+
let (src, dst, count) = ranges[0];
3183+
let mut iter = (0..count).rev();
3184+
if let Some(offset) = iter.next() {
3185+
dst.add(offset).write((*src.add(offset)).clone());
3186+
if self.head == 0 {
3187+
self.head = cap;
3188+
}
3189+
self.head -= 1;
3190+
self.len += 1;
3191+
3192+
for offset in iter {
31763193
dst.add(offset).write((*src.add(offset)).clone());
31773194
self.head -= 1;
31783195
self.len += 1;

library/alloctests/tests/vec_deque.rs

Lines changed: 168 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use core::cell::Cell;
12
use core::num::NonZero;
23
use std::assert_matches::assert_matches;
34
use std::collections::TryReserveErrorKind::*;
@@ -1863,22 +1864,185 @@ fn test_extend_from_within() {
18631864
assert_eq!(v, [2, 3, 4, 5, 3, 4, 5, 3, 4, 2, 3, 4]);
18641865
}
18651866

1867+
struct CloneTracker<'a> {
1868+
clone: &'a Cell<u32>,
1869+
drop: &'a Cell<u32>,
1870+
panic: bool,
1871+
}
1872+
1873+
impl<'a> Clone for CloneTracker<'a> {
1874+
fn clone(&self) -> Self {
1875+
self.clone.set(self.clone.get() + 1);
1876+
if self.panic {
1877+
panic!();
1878+
}
1879+
Self { clone: self.clone, drop: self.drop, panic: false }
1880+
}
1881+
}
1882+
1883+
impl<'a> Drop for CloneTracker<'a> {
1884+
fn drop(&mut self) {
1885+
self.drop.set(self.drop.get() + 1);
1886+
}
1887+
}
1888+
18661889
#[test]
18671890
fn test_extend_from_within_clone() {
1868-
// keep track of clone count and correct dropping when clone impl panics
1891+
let clone_counts = [const { Cell::new(0) }; 6];
1892+
let drop_count = Cell::new(0);
1893+
let mut v = VecDeque::with_capacity(10);
1894+
v.extend(clone_counts.iter().map(|clone_count| CloneTracker {
1895+
clone: clone_count,
1896+
drop: &drop_count,
1897+
panic: false,
1898+
}));
1899+
v.truncate_front(4);
1900+
1901+
v.extend_from_within(2..);
1902+
v.extend_from_within(1..5);
1903+
assert_eq!(
1904+
v.iter().map(|tr| tr.clone.get()).collect::<Vec<_>>(),
1905+
[0, 1, 3, 2, 3, 2, 1, 3, 2, 3],
1906+
);
1907+
assert_eq!(
1908+
clone_counts.each_ref().map(|c| {
1909+
let old = c.get();
1910+
c.set(0);
1911+
old
1912+
}),
1913+
[0, 0, 0, 1, 3, 2],
1914+
);
1915+
}
1916+
1917+
#[test]
1918+
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
1919+
fn test_extend_from_within_clone_panic() {
1920+
let clone_counts = [const { Cell::new(0) }; 6];
1921+
let drop_count = Cell::new(0);
1922+
let mut v = VecDeque::with_capacity(8);
1923+
v.extend(clone_counts.iter().map(|clone_count| CloneTracker {
1924+
clone: clone_count,
1925+
drop: &drop_count,
1926+
panic: false,
1927+
}));
1928+
1929+
v.truncate_front(4);
1930+
1931+
// panic after wrapping
1932+
v[2].panic = true;
1933+
catch_unwind(AssertUnwindSafe(|| {
1934+
v.extend_from_within(..);
1935+
}))
1936+
.unwrap_err();
1937+
v[2].panic = false;
1938+
assert_eq!(v.iter().map(|tr| tr.clone.get()).collect::<Vec<_>>(), [1, 1, 1, 0, 1, 1]);
1939+
assert_eq!(clone_counts.each_ref().map(|c| c.get()), [0, 0, 1, 1, 1, 0]);
1940+
assert_eq!(drop_count.get(), 2);
1941+
1942+
v.truncate_front(2);
1943+
1944+
// panic before wrapping
1945+
v[1].panic = true;
1946+
catch_unwind(AssertUnwindSafe(|| {
1947+
v.extend_from_within(..);
1948+
}))
1949+
.unwrap_err();
1950+
v[1].panic = false;
1951+
assert_eq!(v.iter().map(|tr| tr.clone.get()).collect::<Vec<_>>(), [2, 2, 2]);
1952+
assert_eq!(clone_counts.each_ref().map(|c| c.get()), [0, 0, 2, 2, 1, 0]);
1953+
assert_eq!(drop_count.get(), 6);
18691954
}
18701955

18711956
#[test]
18721957
fn test_prepend_from_within() {
1873-
// like test_extend_from_within
1958+
let mut v = VecDeque::with_capacity(8);
1959+
v.extend(0..6);
1960+
v.truncate_front(4);
1961+
v.prepend_from_within(..=0);
1962+
assert_eq!(v.as_slices(), ([2, 2, 3, 4, 5].as_slice(), [].as_slice()));
1963+
v.prepend_from_within(2..);
1964+
assert_eq!(v.as_slices(), ([3, 4].as_slice(), [5, 2, 2, 3, 4, 5].as_slice()));
1965+
v.prepend_from_within(..);
1966+
assert_eq!(v, [[3, 4, 5, 2, 2, 3, 4, 5]; 2].as_flattened());
18741967
}
18751968

18761969
#[test]
18771970
fn test_prepend_from_within_clone() {
1878-
// like test_extend_from_within_clone
1971+
let clone_counts = [const { Cell::new(0) }; 6];
1972+
let drop_count = Cell::new(0);
1973+
let mut v = VecDeque::with_capacity(10);
1974+
v.extend(clone_counts.iter().map(|clone_count| CloneTracker {
1975+
clone: clone_count,
1976+
drop: &drop_count,
1977+
panic: false,
1978+
}));
1979+
v.truncate_front(4);
1980+
1981+
v.prepend_from_within(..2);
1982+
v.prepend_from_within(1..5);
1983+
assert_eq!(
1984+
v.iter().map(|tr| tr.clone.get()).collect::<Vec<_>>(),
1985+
[3, 2, 3, 1, 2, 3, 2, 3, 1, 0],
1986+
);
1987+
assert_eq!(
1988+
clone_counts.each_ref().map(|c| {
1989+
let old = c.get();
1990+
c.set(0);
1991+
old
1992+
}),
1993+
[0, 0, 2, 3, 1, 0],
1994+
);
1995+
}
1996+
1997+
#[test]
1998+
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
1999+
fn test_prepend_from_within_clone_panic() {
2000+
let clone_counts = [const { Cell::new(0) }; 6];
2001+
let drop_count = Cell::new(0);
2002+
let mut v = VecDeque::with_capacity(8);
2003+
v.extend(clone_counts.iter().map(|clone_count| CloneTracker {
2004+
clone: clone_count,
2005+
drop: &drop_count,
2006+
panic: false,
2007+
}));
2008+
2009+
v.truncate_front(4);
2010+
2011+
// panic after wrapping
2012+
v[1].panic = true;
2013+
catch_unwind(AssertUnwindSafe(|| {
2014+
v.prepend_from_within(..);
2015+
}))
2016+
.unwrap_err();
2017+
v[1].panic = false;
2018+
assert_eq!(v.iter().map(|tr| tr.clone.get()).collect::<Vec<_>>(), [1, 1, 0, 1, 1, 1]);
2019+
assert_eq!(clone_counts.each_ref().map(|c| c.get()), [0, 0, 0, 1, 1, 1]);
2020+
assert_eq!(drop_count.get(), 2);
2021+
2022+
v.truncate_front(2);
2023+
2024+
// panic before wrapping
2025+
v[0].panic = true;
2026+
catch_unwind(AssertUnwindSafe(|| {
2027+
v.prepend_from_within(..);
2028+
}))
2029+
.unwrap_err();
2030+
v[0].panic = false;
2031+
assert_eq!(v.iter().map(|tr| tr.clone.get()).collect::<Vec<_>>(), [2, 2, 2]);
2032+
assert_eq!(clone_counts.each_ref().map(|c| c.get()), [0, 0, 0, 1, 2, 2]);
2033+
assert_eq!(drop_count.get(), 6);
18792034
}
18802035

18812036
#[test]
18822037
fn test_extend_and_prepend_from_within() {
1883-
// mix extend_from_within and prepend_from_within
2038+
let mut v = ('0'..='9').map(String::from).collect::<VecDeque<_>>();
2039+
v.truncate_front(5);
2040+
v.extend_from_within(4..);
2041+
v.prepend_from_within(..2);
2042+
assert_eq!(v.iter().map(|s| &**s).collect::<String>(), "56567899");
2043+
v.clear();
2044+
v.extend(['1', '2', '3'].into_iter().map(String::from));
2045+
v.prepend_from_within(..);
2046+
v.extend_from_within(..);
2047+
assert_eq!(v.iter().map(|s| &**s).collect::<String>(), "123123123123");
18842048
}

0 commit comments

Comments
 (0)