@@ -635,14 +635,14 @@ impl<T> Vec<T> {
635
635
/// ```
636
636
pub fn truncate ( & mut self , len : uint ) {
637
637
unsafe {
638
- let mut i = len;
639
638
// drop any extra elements
640
- while i < self . len {
641
- ptr:: read ( self . as_slice ( ) . unsafe_ref ( i) ) ;
642
- i += 1 ;
639
+ while len < self . len {
640
+ // decrement len before the read(), so a failure on Drop doesn't
641
+ // re-drop the just-failed value.
642
+ self . len -= 1 ;
643
+ ptr:: read ( self . as_slice ( ) . unsafe_ref ( self . len ) ) ;
643
644
}
644
645
}
645
- self . len = len;
646
646
}
647
647
648
648
/// Work with `self` as a mutable slice.
@@ -1862,4 +1862,39 @@ mod tests {
1862
1862
assert_eq ! ( b[ 0 ] . x, 42 ) ;
1863
1863
assert_eq ! ( b[ 1 ] . x, 84 ) ;
1864
1864
}
1865
+
1866
+ #[ test]
1867
+ fn test_vec_truncate_drop ( ) {
1868
+ static mut drops: uint = 0 ;
1869
+ struct Elem ( int ) ;
1870
+ impl Drop for Elem {
1871
+ fn drop ( & mut self ) {
1872
+ unsafe { drops += 1 ; }
1873
+ }
1874
+ }
1875
+
1876
+ let mut v = vec ! [ Elem ( 1 ) , Elem ( 2 ) , Elem ( 3 ) , Elem ( 4 ) , Elem ( 5 ) ] ;
1877
+ assert_eq ! ( unsafe { drops } , 0 ) ;
1878
+ v. truncate ( 3 ) ;
1879
+ assert_eq ! ( unsafe { drops } , 2 ) ;
1880
+ v. truncate ( 0 ) ;
1881
+ assert_eq ! ( unsafe { drops } , 5 ) ;
1882
+ }
1883
+
1884
+ #[ test]
1885
+ #[ should_fail]
1886
+ fn test_vec_truncate_fail ( ) {
1887
+ struct BadElem ( int ) ;
1888
+ impl Drop for BadElem {
1889
+ fn drop ( & mut self ) {
1890
+ let BadElem ( ref mut x) = * self ;
1891
+ if * x == 0xbadbeef {
1892
+ fail ! ( "BadElem failure: 0xbadbeef" )
1893
+ }
1894
+ }
1895
+ }
1896
+
1897
+ let mut v = vec ! [ BadElem ( 1 ) , BadElem ( 2 ) , BadElem ( 0xbadbeef ) , BadElem ( 4 ) ] ;
1898
+ v. truncate ( 0 ) ;
1899
+ }
1865
1900
}
0 commit comments