Skip to content

Commit 500bade

Browse files
committed
Vec: remove the drop flag to make it no larger than (*T, uint, uint).
1 parent 397abb7 commit 500bade

File tree

1 file changed

+50
-0
lines changed

1 file changed

+50
-0
lines changed

src/libstd/vec_ng.rs

+50
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use raw::Slice;
3232
use vec::{ImmutableEqVector, ImmutableVector, Items, MutItems, MutableVector};
3333
use vec::{RevItems};
3434

35+
#[unsafe_no_drop_flag]
3536
pub struct Vec<T> {
3637
priv len: uint,
3738
priv cap: uint,
@@ -565,6 +566,8 @@ pub fn append_one<T>(mut lhs: Vec<T>, x: T) -> Vec<T> {
565566
#[unsafe_destructor]
566567
impl<T> Drop for Vec<T> {
567568
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]).
568571
unsafe {
569572
for x in self.as_mut_slice().iter() {
570573
ptr::read(x);
@@ -629,7 +632,54 @@ impl<T> Drop for MoveItems<T> {
629632
mod tests {
630633
use super::Vec;
631634
use iter::{Iterator, range, Extendable};
635+
use mem::{drop, size_of};
636+
use ops::Drop;
632637
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+
}
633683

634684
#[test]
635685
fn test_reserve_additional() {

0 commit comments

Comments
 (0)