@@ -1856,77 +1856,99 @@ fn test_extend_from_within() {
18561856 let mut v = VecDeque :: with_capacity ( 8 ) ;
18571857 v. extend ( 0 ..6 ) ;
18581858 v. truncate_front ( 4 ) ;
1859+ assert_eq ! ( v, [ 2 , 3 , 4 , 5 ] ) ;
18591860 v. extend_from_within ( 1 ..4 ) ;
1861+ assert_eq ! ( v, [ 2 , 3 , 4 , 5 , 3 , 4 , 5 ] ) ;
1862+ // check it really wrapped
18601863 assert_eq ! ( v. as_slices( ) , ( [ 2 , 3 , 4 , 5 , 3 , 4 ] . as_slice( ) , [ 5 ] . as_slice( ) ) ) ;
18611864 v. extend_from_within ( 1 ..=2 ) ;
18621865 assert_eq ! ( v, [ 2 , 3 , 4 , 5 , 3 , 4 , 5 , 3 , 4 ] ) ;
18631866 v. extend_from_within ( ..3 ) ;
18641867 assert_eq ! ( v, [ 2 , 3 , 4 , 5 , 3 , 4 , 5 , 3 , 4 , 2 , 3 , 4 ] ) ;
18651868}
18661869
1870+ /// Struct that allows tracking clone and drop calls and can be set to panic on calling clone.
18671871struct CloneTracker < ' a > {
1868- clone : & ' a Cell < u32 > ,
1869- drop : & ' a Cell < u32 > ,
1872+ id : usize ,
1873+ // Counters can be set to None if not needed.
1874+ clone : Option < & ' a Cell < u32 > > ,
1875+ drop : Option < & ' a Cell < u32 > > ,
18701876 panic : bool ,
18711877}
18721878
1879+ impl < ' a > CloneTracker < ' a > {
1880+ pub const DUMMY : Self = Self { id : 999 , clone : None , drop : None , panic : false } ;
1881+ }
1882+
18731883impl < ' a > Clone for CloneTracker < ' a > {
18741884 fn clone ( & self ) -> Self {
1875- self . clone . set ( self . clone . get ( ) + 1 ) ;
18761885 if self . panic {
18771886 panic ! ( ) ;
18781887 }
1879- Self { clone : self . clone , drop : self . drop , panic : false }
1888+
1889+ if let Some ( clone_count) = self . clone {
1890+ clone_count. update ( |c| c + 1 ) ;
1891+ }
1892+
1893+ Self { id : self . id , clone : self . clone , drop : self . drop , panic : false }
18801894 }
18811895}
18821896
18831897impl < ' a > Drop for CloneTracker < ' a > {
18841898 fn drop ( & mut self ) {
1885- self . drop . set ( self . drop . get ( ) + 1 ) ;
1899+ if let Some ( drop_count) = self . drop {
1900+ drop_count. update ( |c| c + 1 ) ;
1901+ }
18861902 }
18871903}
18881904
18891905#[ test]
18901906fn test_extend_from_within_clone ( ) {
1891- let clone_counts = [ const { Cell :: new ( 0 ) } ; 6 ] ;
1892- let drop_count = Cell :: new ( 0 ) ;
1907+ let clone_counts = [ const { Cell :: new ( 0 ) } ; 4 ] ;
18931908 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,
1909+ // insert 2 dummy elements to have the buffer wrap later
1910+ v. extend ( [ CloneTracker :: DUMMY ; 2 ] ) ;
1911+ v. extend ( clone_counts. iter ( ) . enumerate ( ) . map ( |( id, clone_count) | CloneTracker {
1912+ id,
1913+ clone : Some ( clone_count) ,
1914+ drop : None ,
18971915 panic : false ,
18981916 } ) ) ;
1917+ // remove the dummy elements
18991918 v. truncate_front ( 4 ) ;
1919+ assert_eq ! ( v. iter( ) . map( |tr| tr. id) . collect:: <Vec <_>>( ) , [ 0 , 1 , 2 , 3 ] ) ;
19001920
19011921 v. extend_from_within ( 2 ..) ;
1922+ assert_eq ! ( v. iter( ) . map( |tr| tr. id) . collect:: <Vec <_>>( ) , [ 0 , 1 , 2 , 3 , 2 , 3 ] ) ;
1923+ // elements at index 2 and 3 should have been cloned once
1924+ assert_eq ! ( clone_counts. each_ref( ) . map( Cell :: get) , [ 0 , 0 , 1 , 1 ] ) ;
1925+ // it is important that the deque wraps because of this operation, we want to test if wrapping is handled correctly
19021926 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- ) ;
1927+ // total length is 10, 8 in the first part and 2 in the second part
1928+ assert_eq ! ( v. as_slices( ) . 0 . len( ) , 8 ) ;
1929+ assert_eq ! ( v. iter( ) . map( |tr| tr. id) . collect:: <Vec <_>>( ) , [ 0 , 1 , 2 , 3 , 2 , 3 , 1 , 2 , 3 , 2 ] ) ;
1930+ // the new elements are from indices 1, 2, 3 and 2, those elements should have their clone count
1931+ // incremented (clone count at index 2 gets incremented twice so ends up at 3)
1932+ assert_eq ! ( clone_counts. each_ref( ) . map( Cell :: get) , [ 0 , 1 , 3 , 2 ] ) ;
19151933}
19161934
19171935#[ test]
19181936#[ cfg_attr( not( panic = "unwind" ) , ignore = "test requires unwinding support" ) ]
19191937fn test_extend_from_within_clone_panic ( ) {
1920- let clone_counts = [ const { Cell :: new ( 0 ) } ; 6 ] ;
1938+ let clone_counts = [ const { Cell :: new ( 0 ) } ; 4 ] ;
19211939 let drop_count = Cell :: new ( 0 ) ;
19221940 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,
1941+ // insert 2 dummy elements to have the buffer wrap later
1942+ v. extend ( [ CloneTracker :: DUMMY ; 2 ] ) ;
1943+ v. extend ( clone_counts. iter ( ) . enumerate ( ) . map ( |( id, clone_count) | CloneTracker {
1944+ id,
1945+ clone : Some ( clone_count) ,
1946+ drop : Some ( & drop_count) ,
19261947 panic : false ,
19271948 } ) ) ;
1928-
1949+ // remove the dummy elements
19291950 v. truncate_front ( 4 ) ;
1951+ assert_eq ! ( v. iter( ) . map( |tr| tr. id) . collect:: <Vec <_>>( ) , [ 0 , 1 , 2 , 3 ] ) ;
19301952
19311953 // panic after wrapping
19321954 v[ 2 ] . panic = true ;
@@ -1935,11 +1957,15 @@ fn test_extend_from_within_clone_panic() {
19351957 } ) )
19361958 . unwrap_err ( ) ;
19371959 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 ) ;
1960+ assert_eq ! ( v. iter( ) . map( |tr| tr. id) . collect:: <Vec <_>>( ) , [ 0 , 1 , 2 , 3 , 0 , 1 ] ) ;
1961+ // the first 2 elements were cloned
1962+ assert_eq ! ( clone_counts. each_ref( ) . map( Cell :: get) , [ 1 , 1 , 0 , 0 ] ) ;
1963+ // nothing should have been dropped
1964+ assert_eq ! ( drop_count. get( ) , 0 ) ;
19411965
19421966 v. truncate_front ( 2 ) ;
1967+ assert_eq ! ( drop_count. get( ) , 4 ) ;
1968+ assert_eq ! ( v. iter( ) . map( |tr| tr. id) . collect:: <Vec <_>>( ) , [ 0 , 1 ] ) ;
19431969
19441970 // panic before wrapping
19451971 v[ 1 ] . panic = true ;
@@ -1948,9 +1974,11 @@ fn test_extend_from_within_clone_panic() {
19481974 } ) )
19491975 . unwrap_err ( ) ;
19501976 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 ) ;
1977+ assert_eq ! ( v. iter( ) . map( |tr| tr. id) . collect:: <Vec <_>>( ) , [ 0 , 1 , 0 ] ) ;
1978+ // only the first element was cloned
1979+ assert_eq ! ( clone_counts. each_ref( ) . map( Cell :: get) , [ 2 , 1 , 0 , 0 ] ) ;
1980+ // nothing more should have been dropped
1981+ assert_eq ! ( drop_count. get( ) , 4 ) ;
19541982}
19551983
19561984#[ test]
@@ -1968,45 +1996,46 @@ fn test_prepend_from_within() {
19681996
19691997#[ test]
19701998fn test_prepend_from_within_clone ( ) {
1971- let clone_counts = [ const { Cell :: new ( 0 ) } ; 6 ] ;
1972- let drop_count = Cell :: new ( 0 ) ;
1999+ let clone_counts = [ const { Cell :: new ( 0 ) } ; 4 ] ;
2000+ // insert 2 dummy elements to have the buffer wrap later
19732001 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,
2002+ v. extend ( [ CloneTracker :: DUMMY ; 2 ] ) ;
2003+ v. extend ( clone_counts. iter ( ) . enumerate ( ) . map ( |( id, clone_count) | CloneTracker {
2004+ id,
2005+ clone : Some ( clone_count) ,
2006+ drop : None ,
19772007 panic : false ,
19782008 } ) ) ;
2009+ // remove the dummy elements
19792010 v. truncate_front ( 4 ) ;
2011+ assert_eq ! ( v. iter( ) . map( |tr| tr. id) . collect:: <Vec <_>>( ) , [ 0 , 1 , 2 , 3 ] ) ;
19802012
19812013 v. prepend_from_within ( ..2 ) ;
2014+ assert_eq ! ( v. iter( ) . map( |tr| tr. id) . collect:: <Vec <_>>( ) , [ 0 , 1 , 0 , 1 , 2 , 3 ] ) ;
19822015 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- ) ;
2016+ assert_eq ! ( v. iter( ) . map( |tr| tr. id) . collect:: <Vec <_>>( ) , [ 1 , 0 , 1 , 2 , 0 , 1 , 0 , 1 , 2 , 3 ] ) ;
2017+ // count the number of each element and subtract one (clone should have been called n-1 times if we have n elements)
2018+ // example: 0 appears 3 times so should have been cloned twice, 1 appears 4 times so cloned 3 times, etc
2019+ assert_eq ! ( clone_counts. each_ref( ) . map( Cell :: get) , [ 2 , 3 , 1 , 0 ] ) ;
19952020}
19962021
19972022#[ test]
19982023#[ cfg_attr( not( panic = "unwind" ) , ignore = "test requires unwinding support" ) ]
19992024fn test_prepend_from_within_clone_panic ( ) {
2000- let clone_counts = [ const { Cell :: new ( 0 ) } ; 6 ] ;
2025+ let clone_counts = [ const { Cell :: new ( 0 ) } ; 4 ] ;
20012026 let drop_count = Cell :: new ( 0 ) ;
20022027 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,
2028+ // insert 2 dummy elements to have the buffer wrap later
2029+ v. extend ( [ CloneTracker :: DUMMY ; 2 ] ) ;
2030+ v. extend ( clone_counts. iter ( ) . enumerate ( ) . map ( |( id, clone_count) | CloneTracker {
2031+ id,
2032+ clone : Some ( clone_count) ,
2033+ drop : Some ( & drop_count) ,
20062034 panic : false ,
20072035 } ) ) ;
2008-
2036+ // remove the dummy elements
20092037 v. truncate_front ( 4 ) ;
2038+ assert_eq ! ( v. iter( ) . map( |tr| tr. id) . collect:: <Vec <_>>( ) , [ 0 , 1 , 2 , 3 ] ) ;
20102039
20112040 // panic after wrapping
20122041 v[ 1 ] . panic = true ;
@@ -2015,11 +2044,15 @@ fn test_prepend_from_within_clone_panic() {
20152044 } ) )
20162045 . unwrap_err ( ) ;
20172046 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 ) ;
2047+ assert_eq ! ( v. iter( ) . map( |tr| tr. id) . collect:: <Vec <_>>( ) , [ 2 , 3 , 0 , 1 , 2 , 3 ] ) ;
2048+ // the last 2 elements were cloned
2049+ assert_eq ! ( clone_counts. each_ref( ) . map( Cell :: get) , [ 0 , 0 , 1 , 1 ] ) ;
2050+ // nothing should have been dropped
2051+ assert_eq ! ( drop_count. get( ) , 0 ) ;
20212052
20222053 v. truncate_front ( 2 ) ;
2054+ assert_eq ! ( drop_count. get( ) , 4 ) ;
2055+ assert_eq ! ( v. iter( ) . map( |tr| tr. id) . collect:: <Vec <_>>( ) , [ 2 , 3 ] ) ;
20232056
20242057 // panic before wrapping
20252058 v[ 0 ] . panic = true ;
@@ -2028,9 +2061,11 @@ fn test_prepend_from_within_clone_panic() {
20282061 } ) )
20292062 . unwrap_err ( ) ;
20302063 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 ) ;
2064+ assert_eq ! ( v. iter( ) . map( |tr| tr. id) . collect:: <Vec <_>>( ) , [ 3 , 2 , 3 ] ) ;
2065+ // only the first element was cloned
2066+ assert_eq ! ( clone_counts. each_ref( ) . map( Cell :: get) , [ 0 , 0 , 1 , 2 ] ) ;
2067+ // nothing more should have been dropped
2068+ assert_eq ! ( drop_count. get( ) , 4 ) ;
20342069}
20352070
20362071#[ test]
@@ -2041,7 +2076,7 @@ fn test_extend_and_prepend_from_within() {
20412076 v. prepend_from_within ( ..2 ) ;
20422077 assert_eq ! ( v. iter( ) . map( |s| & * * s) . collect:: <String >( ) , "56567899" ) ;
20432078 v. clear ( ) ;
2044- v. extend ( [ '1' , '2' , '3' ] . into_iter ( ) . map ( String :: from) ) ;
2079+ v. extend ( [ '1' , '2' , '3' ] . map ( String :: from) ) ;
20452080 v. prepend_from_within ( ..) ;
20462081 v. extend_from_within ( ..) ;
20472082 assert_eq ! ( v. iter( ) . map( |s| & * * s) . collect:: <String >( ) , "123123123123" ) ;
0 commit comments