Skip to content

Commit 466135b

Browse files
committed
libcore: Make it unsafe to create NonZero and impl Deref.
1 parent 4af5054 commit 466135b

File tree

4 files changed

+55
-59
lines changed

4 files changed

+55
-59
lines changed

src/liballoc/arc.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ impl<T> Arc<T> {
164164
weak: atomic::AtomicUint::new(1),
165165
data: data,
166166
};
167-
Arc { _ptr: NonZero(unsafe { mem::transmute(x) }) }
167+
Arc { _ptr: unsafe { NonZero::new(mem::transmute(x)) } }
168168
}
169169

170170
/// Downgrades the `Arc<T>` to a `Weak<T>` reference.
@@ -193,8 +193,7 @@ impl<T> Arc<T> {
193193
// pointer is valid. Furthermore, we know that the `ArcInner` structure itself is `Sync`
194194
// because the inner data is `Sync` as well, so we're ok loaning out an immutable pointer
195195
// to these contents.
196-
let NonZero(ptr) = self._ptr;
197-
unsafe { &*ptr }
196+
unsafe { &**self._ptr }
198197
}
199198
}
200199

@@ -281,8 +280,7 @@ impl<T: Send + Sync + Clone> Arc<T> {
281280
// pointer that will ever be returned to T. Our reference count is guaranteed to be 1 at
282281
// this point, and we required the Arc itself to be `mut`, so we're returning the only
283282
// possible reference to the inner data.
284-
let NonZero(ptr) = self._ptr;
285-
let inner = unsafe { &mut *ptr };
283+
let inner = unsafe { &mut **self._ptr };
286284
&mut inner.data
287285
}
288286
}
@@ -317,7 +315,7 @@ impl<T: Sync + Send> Drop for Arc<T> {
317315
fn drop(&mut self) {
318316
// This structure has #[unsafe_no_drop_flag], so this drop glue may run more than once (but
319317
// it is guaranteed to be zeroed after the first if it's run more than once)
320-
let NonZero(ptr) = self._ptr;
318+
let ptr = *self._ptr;
321319
if ptr.is_null() { return }
322320

323321
// Because `fetch_sub` is already atomic, we do not need to synchronize with other threads
@@ -388,8 +386,7 @@ impl<T: Sync + Send> Weak<T> {
388386
#[inline]
389387
fn inner(&self) -> &ArcInner<T> {
390388
// See comments above for why this is "safe"
391-
let NonZero(ptr) = self._ptr;
392-
unsafe { &*ptr }
389+
unsafe { &**self._ptr }
393390
}
394391
}
395392

@@ -445,7 +442,7 @@ impl<T: Sync + Send> Drop for Weak<T> {
445442
/// } // implicit drop
446443
/// ```
447444
fn drop(&mut self) {
448-
let NonZero(ptr) = self._ptr;
445+
let ptr = *self._ptr;
449446

450447
// see comments above for why this check is here
451448
if ptr.is_null() { return }

src/liballoc/rc.rs

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ impl<T> Rc<T> {
195195
// there is an implicit weak pointer owned by all the strong pointers, which
196196
// ensures that the weak destructor never frees the allocation while the strong
197197
// destructor is running, even if the weak pointer is stored inside the strong one.
198-
_ptr: NonZero(transmute(box RcBox {
198+
_ptr: NonZero::new(transmute(box RcBox {
199199
value: value,
200200
strong: Cell::new(1),
201201
weak: Cell::new(1)
@@ -280,8 +280,7 @@ pub fn try_unwrap<T>(rc: Rc<T>) -> Result<T, Rc<T>> {
280280
let val = ptr::read(&*rc); // copy the contained object
281281
// destruct the box and skip our Drop
282282
// we can ignore the refcounts because we know we're unique
283-
let NonZero(ptr) = rc._ptr;
284-
deallocate(ptr as *mut u8, size_of::<RcBox<T>>(),
283+
deallocate(*rc._ptr as *mut u8, size_of::<RcBox<T>>(),
285284
min_align_of::<RcBox<T>>());
286285
forget(rc);
287286
Ok(val)
@@ -311,10 +310,7 @@ pub fn try_unwrap<T>(rc: Rc<T>) -> Result<T, Rc<T>> {
311310
#[experimental]
312311
pub fn get_mut<'a, T>(rc: &'a mut Rc<T>) -> Option<&'a mut T> {
313312
if is_unique(rc) {
314-
let inner = unsafe {
315-
let NonZero(ptr) = rc._ptr;
316-
&mut *ptr
317-
};
313+
let inner = unsafe { &mut **rc._ptr };
318314
Some(&mut inner.value)
319315
} else {
320316
None
@@ -346,10 +342,7 @@ impl<T: Clone> Rc<T> {
346342
// pointer that will ever be returned to T. Our reference count is guaranteed to be 1 at
347343
// this point, and we required the `Rc<T>` itself to be `mut`, so we're returning the only
348344
// possible reference to the inner value.
349-
let inner = unsafe {
350-
let NonZero(ptr) = self._ptr;
351-
&mut *ptr
352-
};
345+
let inner = unsafe { &mut **self._ptr };
353346
&mut inner.value
354347
}
355348
}
@@ -397,7 +390,7 @@ impl<T> Drop for Rc<T> {
397390
/// ```
398391
fn drop(&mut self) {
399392
unsafe {
400-
let NonZero(ptr) = self._ptr;
393+
let ptr = *self._ptr;
401394
if !ptr.is_null() {
402395
self.dec_strong();
403396
if self.strong() == 0 {
@@ -689,7 +682,7 @@ impl<T> Drop for Weak<T> {
689682
/// ```
690683
fn drop(&mut self) {
691684
unsafe {
692-
let NonZero(ptr) = self._ptr;
685+
let ptr = *self._ptr;
693686
if !ptr.is_null() {
694687
self.dec_weak();
695688
// the weak count starts at 1, and will only go to zero if all the strong pointers
@@ -750,18 +743,12 @@ trait RcBoxPtr<T> {
750743

751744
impl<T> RcBoxPtr<T> for Rc<T> {
752745
#[inline(always)]
753-
fn inner(&self) -> &RcBox<T> {
754-
let NonZero(ptr) = self._ptr;
755-
unsafe { &(*ptr) }
756-
}
746+
fn inner(&self) -> &RcBox<T> { unsafe { &(**self._ptr) } }
757747
}
758748

759749
impl<T> RcBoxPtr<T> for Weak<T> {
760750
#[inline(always)]
761-
fn inner(&self) -> &RcBox<T> {
762-
let NonZero(ptr) = self._ptr;
763-
unsafe { &(*ptr) }
764-
}
751+
fn inner(&self) -> &RcBox<T> { unsafe { &(**self._ptr) } }
765752
}
766753

767754
#[cfg(test)]

src/libcollections/vec.rs

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ impl<T> Vec<T> {
176176
// non-null value which is fine since we never call deallocate on the ptr
177177
// if cap is 0. The reason for this is because the pointer of a slice
178178
// being NULL would break the null pointer optimization for enums.
179-
Vec { ptr: NonZero(EMPTY as *mut T), len: 0, cap: 0 }
179+
Vec { ptr: unsafe { NonZero::new(EMPTY as *mut T) }, len: 0, cap: 0 }
180180
}
181181

182182
/// Constructs a new, empty `Vec<T>` with the specified capacity.
@@ -209,15 +209,15 @@ impl<T> Vec<T> {
209209
#[stable]
210210
pub fn with_capacity(capacity: uint) -> Vec<T> {
211211
if mem::size_of::<T>() == 0 {
212-
Vec { ptr: NonZero(EMPTY as *mut T), len: 0, cap: uint::MAX }
212+
Vec { ptr: unsafe { NonZero::new(EMPTY as *mut T) }, len: 0, cap: uint::MAX }
213213
} else if capacity == 0 {
214214
Vec::new()
215215
} else {
216216
let size = capacity.checked_mul(mem::size_of::<T>())
217217
.expect("capacity overflow");
218218
let ptr = unsafe { allocate(size, mem::min_align_of::<T>()) };
219219
if ptr.is_null() { ::alloc::oom() }
220-
Vec { ptr: NonZero(ptr as *mut T), len: 0, cap: capacity }
220+
Vec { ptr: unsafe { NonZero::new(ptr as *mut T) }, len: 0, cap: capacity }
221221
}
222222
}
223223

@@ -284,7 +284,7 @@ impl<T> Vec<T> {
284284
#[unstable = "needs finalization"]
285285
pub unsafe fn from_raw_parts(ptr: *mut T, length: uint,
286286
capacity: uint) -> Vec<T> {
287-
Vec { ptr: NonZero(ptr), len: length, cap: capacity }
287+
Vec { ptr: NonZero::new(ptr), len: length, cap: capacity }
288288
}
289289

290290
/// Creates a vector by copying the elements from a raw pointer.
@@ -792,24 +792,23 @@ impl<T> Vec<T> {
792792
pub fn shrink_to_fit(&mut self) {
793793
if mem::size_of::<T>() == 0 { return }
794794

795-
let NonZero(ptr) = self.ptr;
796795
if self.len == 0 {
797796
if self.cap != 0 {
798797
unsafe {
799-
dealloc(ptr, self.cap)
798+
dealloc(*self.ptr, self.cap)
800799
}
801800
self.cap = 0;
802801
}
803802
} else {
804803
unsafe {
805804
// Overflow check is unnecessary as the vector is already at
806805
// least this large.
807-
let ptr = reallocate(ptr as *mut u8,
806+
let ptr = reallocate(*self.ptr as *mut u8,
808807
self.cap * mem::size_of::<T>(),
809808
self.len * mem::size_of::<T>(),
810809
mem::min_align_of::<T>()) as *mut T;
811810
if ptr.is_null() { ::alloc::oom() }
812-
self.ptr = NonZero(ptr);
811+
self.ptr = NonZero::new(ptr);
813812
}
814813
self.cap = self.len;
815814
}
@@ -867,10 +866,9 @@ impl<T> Vec<T> {
867866
#[inline]
868867
#[stable]
869868
pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
870-
let NonZero(ptr) = self.ptr;
871869
unsafe {
872870
mem::transmute(RawSlice {
873-
data: ptr as *const T,
871+
data: *self.ptr as *const T,
874872
len: self.len,
875873
})
876874
}
@@ -893,7 +891,7 @@ impl<T> Vec<T> {
893891
#[unstable = "matches collection reform specification, waiting for dust to settle"]
894892
pub fn into_iter(self) -> IntoIter<T> {
895893
unsafe {
896-
let NonZero(ptr) = self.ptr;
894+
let ptr = *self.ptr;
897895
let cap = self.cap;
898896
let begin = ptr as *const T;
899897
let end = if mem::size_of::<T>() == 0 {
@@ -1113,16 +1111,15 @@ impl<T> Vec<T> {
11131111
let size = max(old_size, 2 * mem::size_of::<T>()) * 2;
11141112
if old_size > size { panic!("capacity overflow") }
11151113
unsafe {
1116-
let NonZero(ptr) = self.ptr;
1117-
let ptr = alloc_or_realloc(ptr, old_size, size);
1114+
let ptr = alloc_or_realloc(*self.ptr, old_size, size);
11181115
if ptr.is_null() { ::alloc::oom() }
1119-
self.ptr = NonZero(ptr);
1116+
self.ptr = NonZero::new(ptr);
11201117
}
11211118
self.cap = max(self.cap, 2) * 2;
11221119
}
11231120

11241121
unsafe {
1125-
let NonZero(end) = self.ptr.offset(self.len as int);
1122+
let end = *self.ptr.offset(self.len as int);
11261123
ptr::write(&mut *end, value);
11271124
self.len += 1;
11281125
}
@@ -1167,11 +1164,11 @@ impl<T> Vec<T> {
11671164
#[unstable = "matches collection reform specification, waiting for dust to settle"]
11681165
pub fn drain<'a>(&'a mut self) -> Drain<'a, T> {
11691166
unsafe {
1170-
let begin = self.ptr.0 as *const T;
1167+
let begin = *self.ptr as *const T;
11711168
let end = if mem::size_of::<T>() == 0 {
1172-
(self.ptr.0 as uint + self.len()) as *const T
1169+
(*self.ptr as uint + self.len()) as *const T
11731170
} else {
1174-
self.ptr.0.offset(self.len() as int) as *const T
1171+
(*self.ptr).offset(self.len() as int) as *const T
11751172
};
11761173
self.set_len(0);
11771174
Drain {
@@ -1236,10 +1233,9 @@ impl<T> Vec<T> {
12361233
let size = capacity.checked_mul(mem::size_of::<T>())
12371234
.expect("capacity overflow");
12381235
unsafe {
1239-
let NonZero(ptr) = self.ptr;
1240-
let ptr = alloc_or_realloc(ptr, self.cap * mem::size_of::<T>(), size);
1236+
let ptr = alloc_or_realloc(*self.ptr, self.cap * mem::size_of::<T>(), size);
12411237
if ptr.is_null() { ::alloc::oom() }
1242-
self.ptr = NonZero(ptr);
1238+
self.ptr = NonZero::new(ptr);
12431239
}
12441240
self.cap = capacity;
12451241
}
@@ -1360,10 +1356,9 @@ impl<T> AsSlice<T> for Vec<T> {
13601356
#[inline]
13611357
#[stable]
13621358
fn as_slice<'a>(&'a self) -> &'a [T] {
1363-
let NonZero(ptr) = self.ptr;
13641359
unsafe {
13651360
mem::transmute(RawSlice {
1366-
data: ptr as *const T,
1361+
data: *self.ptr as *const T,
13671362
len: self.len
13681363
})
13691364
}
@@ -1388,8 +1383,7 @@ impl<T> Drop for Vec<T> {
13881383
for x in self.iter() {
13891384
ptr::read(x);
13901385
}
1391-
let NonZero(ptr) = self.ptr;
1392-
dealloc(ptr, self.cap)
1386+
dealloc(*self.ptr, self.cap)
13931387
}
13941388
}
13951389
}
@@ -1427,7 +1421,7 @@ impl<T> IntoIter<T> {
14271421
for _x in self { }
14281422
let IntoIter { allocation, cap, ptr: _ptr, end: _end } = self;
14291423
mem::forget(self);
1430-
Vec { ptr: NonZero(allocation), cap: cap, len: 0 }
1424+
Vec { ptr: NonZero::new(allocation), cap: cap, len: 0 }
14311425
}
14321426
}
14331427

src/libcore/ptr.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@
9090
use mem;
9191
use clone::Clone;
9292
use intrinsics;
93-
use kinds::Copy;
93+
use kinds::{Copy, Send, Sync};
94+
use ops::Deref;
9495
use option::Option;
9596
use option::Option::{Some, None};
96-
use kinds::{Send, Sync};
9797

9898
use cmp::{PartialEq, Eq, Ord, PartialOrd, Equiv};
9999
use cmp::Ordering;
@@ -115,7 +115,25 @@ pub use intrinsics::set_memory;
115115
/// NULL or 0 that might allow certain optimizations.
116116
#[lang="non_zero"]
117117
#[deriving(Clone, PartialEq, Eq, PartialOrd)]
118-
pub struct NonZero<T>(pub T);
118+
#[experimental]
119+
pub struct NonZero<T>(T);
120+
121+
impl<T> NonZero<T> {
122+
/// Create an instance of NonZero with the provided value.
123+
/// You must indeed ensure that the value is actually "non-zero".
124+
#[inline(always)]
125+
pub unsafe fn new(inner: T) -> NonZero<T> {
126+
NonZero(inner)
127+
}
128+
}
129+
130+
impl<T> Deref<T> for NonZero<T> {
131+
#[inline]
132+
fn deref<'a>(&'a self) -> &'a T {
133+
let NonZero(ref inner) = *self;
134+
inner
135+
}
136+
}
119137

120138
impl<T: Copy> Copy for NonZero<T> {}
121139

0 commit comments

Comments
 (0)