@@ -32,6 +32,7 @@ use raw::Slice;
3232use vec:: { ImmutableEqVector , ImmutableVector , Items , MutItems , MutableVector } ;
3333use vec:: { RevItems } ;
3434
35+ #[ unsafe_no_drop_flag]
3536pub struct Vec < T > {
3637 priv len: uint ,
3738 priv cap: uint ,
@@ -585,6 +586,8 @@ pub fn append_one<T>(mut lhs: Vec<T>, x: T) -> Vec<T> {
585586#[ unsafe_destructor]
586587impl < T > Drop for Vec < T > {
587588 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]).
588591 unsafe {
589592 for x in self . as_mut_slice ( ) . iter ( ) {
590593 ptr:: read ( x) ;
@@ -649,7 +652,54 @@ impl<T> Drop for MoveItems<T> {
649652mod tests {
650653 use super :: Vec ;
651654 use iter:: { Iterator , range, Extendable } ;
655+ use mem:: { drop, size_of} ;
656+ use ops:: Drop ;
652657 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+ }
653703
654704 #[ test]
655705 fn test_reserve_additional ( ) {
0 commit comments