@@ -32,6 +32,7 @@ use raw::Slice;
32
32
use vec:: { ImmutableEqVector , ImmutableVector , Items , MutItems , MutableVector } ;
33
33
use vec:: { RevItems } ;
34
34
35
+ #[ unsafe_no_drop_flag]
35
36
pub struct Vec < T > {
36
37
priv len: uint ,
37
38
priv cap: uint ,
@@ -585,6 +586,8 @@ pub fn append_one<T>(mut lhs: Vec<T>, x: T) -> Vec<T> {
585
586
#[ unsafe_destructor]
586
587
impl < T > Drop for Vec < T > {
587
588
fn drop ( & mut self ) {
589
+ // This is (and should always remain) a no-op if the fields are
590
+ // zeroed (when moving out, because of #[unsafe_no_drop_flag]).
588
591
unsafe {
589
592
for x in self . as_mut_slice ( ) . iter ( ) {
590
593
ptr:: read ( x) ;
@@ -649,7 +652,54 @@ impl<T> Drop for MoveItems<T> {
649
652
mod tests {
650
653
use super :: Vec ;
651
654
use iter:: { Iterator , range, Extendable } ;
655
+ use mem:: { drop, size_of} ;
656
+ use ops:: Drop ;
652
657
use option:: { Some , None } ;
658
+ use ptr;
659
+
660
+ #[ test]
661
+ fn test_small_vec_struct ( ) {
662
+ assert ! ( size_of:: <Vec <u8 >>( ) == size_of:: <uint>( ) * 3 ) ;
663
+ }
664
+
665
+ #[ test]
666
+ fn test_double_drop ( ) {
667
+ struct TwoVec < T > {
668
+ x : Vec < T > ,
669
+ y : Vec < T >
670
+ }
671
+
672
+ struct DropCounter < ' a > {
673
+ count : & ' a mut int
674
+ }
675
+
676
+ #[ unsafe_destructor]
677
+ impl < ' a > Drop for DropCounter < ' a > {
678
+ fn drop ( & mut self ) {
679
+ * self . count += 1 ;
680
+ }
681
+ }
682
+
683
+ let mut count_x @ mut count_y = 0 ;
684
+ {
685
+ let mut tv = TwoVec {
686
+ x : Vec :: new ( ) ,
687
+ y : Vec :: new ( )
688
+ } ;
689
+ tv. x . push ( DropCounter { count : & mut count_x} ) ;
690
+ tv. y . push ( DropCounter { count : & mut count_y} ) ;
691
+
692
+ // If Vec had a drop flag, here is where it would be zeroed.
693
+ // Instead, it should rely on its internal state to prevent
694
+ // doing anything significant when dropped multiple times.
695
+ drop ( tv. x ) ;
696
+
697
+ // Here tv goes out of scope, tv.y should be dropped, but not tv.x.
698
+ }
699
+
700
+ assert_eq ! ( count_x, 1 ) ;
701
+ assert_eq ! ( count_y, 1 ) ;
702
+ }
653
703
654
704
#[ test]
655
705
fn test_reserve_additional ( ) {
0 commit comments