Skip to content

Commit 3871312

Browse files
committed
Move away from the ad-hoc NoDrop unions
1 parent f6e5661 commit 3871312

File tree

5 files changed

+25
-56
lines changed

5 files changed

+25
-56
lines changed

src/libcollections/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#![feature(heap_api)]
4545
#![feature(inclusive_range)]
4646
#![feature(lang_items)]
47+
#![feature(manually_drop)]
4748
#![feature(nonzero)]
4849
#![feature(pattern)]
4950
#![feature(placement_in)]

src/libcollections/slice.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,7 +1558,7 @@ fn insert_head<T, F>(v: &mut [T], is_less: &mut F)
15581558
// performance than with the 2nd method.
15591559
//
15601560
// All methods were benchmarked, and the 3rd showed best results. So we chose that one.
1561-
let mut tmp = NoDrop { value: ptr::read(&v[0]) };
1561+
let mut tmp = mem::ManuallyDrop::new(ptr::read(&v[0]));
15621562

15631563
// Intermediate state of the insertion process is always tracked by `hole`, which
15641564
// serves two purposes:
@@ -1571,13 +1571,13 @@ fn insert_head<T, F>(v: &mut [T], is_less: &mut F)
15711571
// fill the hole in `v` with `tmp`, thus ensuring that `v` still holds every object it
15721572
// initially held exactly once.
15731573
let mut hole = InsertionHole {
1574-
src: &mut tmp.value,
1574+
src: &mut *tmp,
15751575
dest: &mut v[1],
15761576
};
15771577
ptr::copy_nonoverlapping(&v[1], &mut v[0], 1);
15781578

15791579
for i in 2..v.len() {
1580-
if !is_less(&v[i], &tmp.value) {
1580+
if !is_less(&v[i], &*tmp) {
15811581
break;
15821582
}
15831583
ptr::copy_nonoverlapping(&v[i], &mut v[i - 1], 1);
@@ -1587,12 +1587,6 @@ fn insert_head<T, F>(v: &mut [T], is_less: &mut F)
15871587
}
15881588
}
15891589

1590-
// Holds a value, but never drops it.
1591-
#[allow(unions_with_drop_fields)]
1592-
union NoDrop<T> {
1593-
value: T
1594-
}
1595-
15961590
// When dropped, copies from `src` into `dest`.
15971591
struct InsertionHole<T> {
15981592
src: *mut T,

src/libcore/slice/sort.rs

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,6 @@ use cmp;
2020
use mem;
2121
use ptr;
2222

23-
/// Holds a value, but never drops it.
24-
#[allow(unions_with_drop_fields)]
25-
union NoDrop<T> {
26-
value: T
27-
}
28-
2923
/// When dropped, copies from `src` into `dest`.
3024
struct CopyOnDrop<T> {
3125
src: *mut T,
@@ -49,15 +43,15 @@ fn shift_head<T, F>(v: &mut [T], is_less: &mut F)
4943
// Read the first element into a stack-allocated variable. If a following comparison
5044
// operation panics, `hole` will get dropped and automatically write the element back
5145
// into the slice.
52-
let mut tmp = NoDrop { value: ptr::read(v.get_unchecked(0)) };
46+
let mut tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(0)));
5347
let mut hole = CopyOnDrop {
54-
src: &mut tmp.value,
48+
src: &mut *tmp,
5549
dest: v.get_unchecked_mut(1),
5650
};
5751
ptr::copy_nonoverlapping(v.get_unchecked(1), v.get_unchecked_mut(0), 1);
5852

5953
for i in 2..len {
60-
if !is_less(v.get_unchecked(i), &tmp.value) {
54+
if !is_less(v.get_unchecked(i), &*tmp) {
6155
break;
6256
}
6357

@@ -81,15 +75,15 @@ fn shift_tail<T, F>(v: &mut [T], is_less: &mut F)
8175
// Read the last element into a stack-allocated variable. If a following comparison
8276
// operation panics, `hole` will get dropped and automatically write the element back
8377
// into the slice.
84-
let mut tmp = NoDrop { value: ptr::read(v.get_unchecked(len - 1)) };
78+
let mut tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(len - 1)));
8579
let mut hole = CopyOnDrop {
86-
src: &mut tmp.value,
80+
src: &mut *tmp,
8781
dest: v.get_unchecked_mut(len - 2),
8882
};
8983
ptr::copy_nonoverlapping(v.get_unchecked(len - 2), v.get_unchecked_mut(len - 1), 1);
9084

9185
for i in (0..len-2).rev() {
92-
if !is_less(&tmp.value, v.get_unchecked(i)) {
86+
if !is_less(&*tmp, v.get_unchecked(i)) {
9387
break;
9488
}
9589

@@ -403,12 +397,12 @@ fn partition<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> (usize, bool)
403397

404398
// Read the pivot into a stack-allocated variable for efficiency. If a following comparison
405399
// operation panics, the pivot will be automatically written back into the slice.
406-
let mut tmp = NoDrop { value: unsafe { ptr::read(pivot) } };
400+
let mut tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) });
407401
let _pivot_guard = CopyOnDrop {
408-
src: unsafe { &mut tmp.value },
402+
src: &mut *tmp,
409403
dest: pivot,
410404
};
411-
let pivot = unsafe { &tmp.value };
405+
let pivot = &*tmp;
412406

413407
// Find the first pair of out-of-order elements.
414408
let mut l = 0;
@@ -452,12 +446,12 @@ fn partition_equal<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> usize
452446

453447
// Read the pivot into a stack-allocated variable for efficiency. If a following comparison
454448
// operation panics, the pivot will be automatically written back into the slice.
455-
let mut tmp = NoDrop { value: unsafe { ptr::read(pivot) } };
449+
let mut tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) });
456450
let _pivot_guard = CopyOnDrop {
457-
src: unsafe { &mut tmp.value },
451+
src: &mut *tmp,
458452
dest: pivot,
459453
};
460-
let pivot = unsafe { &tmp.value };
454+
let pivot = &*tmp;
461455

462456
// Now partition the slice.
463457
let mut l = 0;

src/librustc_data_structures/array_vec.rs

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,11 @@ use std::fmt;
2020
use std::mem;
2121
use std::collections::range::RangeArgument;
2222
use std::collections::Bound::{Excluded, Included, Unbounded};
23+
use std::mem::ManuallyDrop;
2324

2425
pub unsafe trait Array {
2526
type Element;
26-
type PartialStorage: Default + Unsize<[ManuallyDrop<Self::Element>]>;
27+
type PartialStorage: Unsize<[ManuallyDrop<Self::Element>]>;
2728
const LEN: usize;
2829
}
2930

@@ -66,7 +67,7 @@ impl<A: Array> ArrayVec<A> {
6667
pub fn new() -> Self {
6768
ArrayVec {
6869
count: 0,
69-
values: Default::default(),
70+
values: unsafe { ::std::mem::uninitialized() },
7071
}
7172
}
7273

@@ -81,7 +82,7 @@ impl<A: Array> ArrayVec<A> {
8182
/// Panics when the stack vector is full.
8283
pub fn push(&mut self, el: A::Element) {
8384
let arr = &mut self.values as &mut [ManuallyDrop<_>];
84-
arr[self.count] = ManuallyDrop { value: el };
85+
arr[self.count] = ManuallyDrop::new(el);
8586
self.count += 1;
8687
}
8788

@@ -90,8 +91,8 @@ impl<A: Array> ArrayVec<A> {
9091
let arr = &mut self.values as &mut [ManuallyDrop<_>];
9192
self.count -= 1;
9293
unsafe {
93-
let value = ptr::read(&arr[self.count]);
94-
Some(value.value)
94+
let value = ptr::read(&*arr[self.count]);
95+
Some(value)
9596
}
9697
} else {
9798
None
@@ -210,7 +211,7 @@ impl<A: Array> Iterator for Iter<A> {
210211
fn next(&mut self) -> Option<A::Element> {
211212
let arr = &self.store as &[ManuallyDrop<_>];
212213
unsafe {
213-
self.indices.next().map(|i| ptr::read(&arr[i]).value)
214+
self.indices.next().map(|i| ptr::read(&*arr[i]))
214215
}
215216
}
216217

@@ -233,7 +234,7 @@ impl<'a, A: Array> Iterator for Drain<'a, A> {
233234

234235
#[inline]
235236
fn next(&mut self) -> Option<A::Element> {
236-
self.iter.next().map(|elt| unsafe { ptr::read(elt as *const ManuallyDrop<_>).value })
237+
self.iter.next().map(|elt| unsafe { ptr::read(&**elt) })
237238
}
238239

239240
fn size_hint(&self) -> (usize, Option<usize>) {
@@ -295,25 +296,3 @@ impl<'a, A: Array> IntoIterator for &'a mut ArrayVec<A> {
295296
self.iter_mut()
296297
}
297298
}
298-
299-
// FIXME: This should use repr(transparent) from rust-lang/rfcs#1758.
300-
#[allow(unions_with_drop_fields)]
301-
pub union ManuallyDrop<T> {
302-
value: T,
303-
#[allow(dead_code)]
304-
empty: (),
305-
}
306-
307-
impl<T> ManuallyDrop<T> {
308-
fn new() -> ManuallyDrop<T> {
309-
ManuallyDrop {
310-
empty: ()
311-
}
312-
}
313-
}
314-
315-
impl<T> Default for ManuallyDrop<T> {
316-
fn default() -> Self {
317-
ManuallyDrop::new()
318-
}
319-
}

src/librustc_data_structures/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#![feature(conservative_impl_trait)]
4040
#![feature(discriminant_value)]
4141
#![feature(specialization)]
42+
#![feature(manually_drop)]
4243

4344
#![cfg_attr(unix, feature(libc))]
4445
#![cfg_attr(test, feature(test))]

0 commit comments

Comments
 (0)