@@ -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 ,
@@ -565,6 +566,8 @@ pub fn append_one<T>(mut lhs: Vec<T>, x: T) -> Vec<T> {
565
566
#[ unsafe_destructor]
566
567
impl < T > Drop for Vec < T > {
567
568
fn drop ( & mut self ) {
569
+ // This is (and should always remain) a no-op if the fields are
570
+ // zeroed (when moving out, because of #[unsafe_no_drop_flag]).
568
571
unsafe {
569
572
for x in self . as_mut_slice ( ) . iter ( ) {
570
573
ptr:: read ( x) ;
@@ -629,7 +632,54 @@ impl<T> Drop for MoveItems<T> {
629
632
mod tests {
630
633
use super :: Vec ;
631
634
use iter:: { Iterator , range, Extendable } ;
635
+ use mem:: { drop, size_of} ;
636
+ use ops:: Drop ;
632
637
use option:: { Some , None } ;
638
+ use ptr;
639
+
640
+ #[ test]
641
+ fn test_small_vec_struct ( ) {
642
+ assert ! ( size_of:: <Vec <u8 >>( ) == size_of:: <uint>( ) * 3 ) ;
643
+ }
644
+
645
+ #[ test]
646
+ fn test_double_drop ( ) {
647
+ struct TwoVec < T > {
648
+ x : Vec < T > ,
649
+ y : Vec < T >
650
+ }
651
+
652
+ struct DropCounter < ' a > {
653
+ count : & ' a mut int
654
+ }
655
+
656
+ #[ unsafe_destructor]
657
+ impl < ' a > Drop for DropCounter < ' a > {
658
+ fn drop ( & mut self ) {
659
+ * self . count += 1 ;
660
+ }
661
+ }
662
+
663
+ let mut count_x @ mut count_y = 0 ;
664
+ {
665
+ let mut tv = TwoVec {
666
+ x : Vec :: new ( ) ,
667
+ y : Vec :: new ( )
668
+ } ;
669
+ tv. x . push ( DropCounter { count : & mut count_x} ) ;
670
+ tv. y . push ( DropCounter { count : & mut count_y} ) ;
671
+
672
+ // If Vec had a drop flag, here is where it would be zeroed.
673
+ // Instead, it should rely on its internal state to prevent
674
+ // doing anything significant when dropped multiple times.
675
+ drop ( tv. x ) ;
676
+
677
+ // Here tv goes out of scope, tv.y should be dropped, but not tv.x.
678
+ }
679
+
680
+ assert_eq ! ( count_x, 1 ) ;
681
+ assert_eq ! ( count_y, 1 ) ;
682
+ }
633
683
634
684
#[ test]
635
685
fn test_reserve_additional ( ) {
0 commit comments