Skip to content

Commit 94f1261

Browse files
committed
libcore: Use Zeroable trait to try to limit what types may be used with NonZero.
1 parent 27617a1 commit 94f1261

File tree

1 file changed

+57
-3
lines changed

1 file changed

+57
-3
lines changed

src/libcore/nonzero.rs

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,30 @@
1212
1313
use ops::Deref;
1414

15+
/// Unsafe trait to indicate what types are usable with the NonZero struct
16+
pub unsafe trait Zeroable {}
17+
18+
unsafe impl<T> Zeroable for *const T {}
19+
unsafe impl<T> Zeroable for *mut T {}
20+
unsafe impl Zeroable for int {}
21+
unsafe impl Zeroable for uint {}
22+
unsafe impl Zeroable for i8 {}
23+
unsafe impl Zeroable for u8 {}
24+
unsafe impl Zeroable for i16 {}
25+
unsafe impl Zeroable for u16 {}
26+
unsafe impl Zeroable for i32 {}
27+
unsafe impl Zeroable for u32 {}
28+
unsafe impl Zeroable for i64 {}
29+
unsafe impl Zeroable for u64 {}
30+
1531
/// A wrapper type for raw pointers and integers that will never be
1632
/// NULL or 0 that might allow certain optimizations.
1733
#[lang="non_zero"]
1834
#[deriving(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Show)]
1935
#[experimental]
20-
pub struct NonZero<T>(T);
36+
pub struct NonZero<T: Zeroable>(T);
2137

22-
impl<T> NonZero<T> {
38+
impl<T: Zeroable> NonZero<T> {
2339
/// Create an instance of NonZero with the provided value.
2440
/// You must indeed ensure that the value is actually "non-zero".
2541
#[inline(always)]
@@ -28,10 +44,48 @@ impl<T> NonZero<T> {
2844
}
2945
}
3046

31-
impl<T> Deref<T> for NonZero<T> {
47+
impl<T: Zeroable> Deref<T> for NonZero<T> {
3248
#[inline]
3349
fn deref<'a>(&'a self) -> &'a T {
3450
let NonZero(ref inner) = *self;
3551
inner
3652
}
3753
}
54+
55+
#[cfg(test)]
56+
mod test {
57+
use super::NonZero;
58+
59+
#[test]
60+
fn test_create_nonzero_instance() {
61+
let _a = unsafe {
62+
NonZero::new(21)
63+
};
64+
}
65+
66+
#[test]
67+
fn test_size_nonzero_in_option() {
68+
use mem::size_of;
69+
use option::Option;
70+
71+
assert_eq!(size_of::<NonZero<u32>>(), size_of::<Option<NonZero<u32>>>());
72+
}
73+
74+
#[test]
75+
fn test_match_on_nonzero_option() {
76+
use option::Some;
77+
78+
let a = Some(unsafe {
79+
NonZero::new(42)
80+
});
81+
match a {
82+
Some(val) => assert_eq!(*val, 42),
83+
None => panic!("unexpected None while matching on Some(NonZero(_))")
84+
}
85+
86+
match unsafe { NonZero::new(43) } {
87+
Some(val) => assert_eq!(*val, 43),
88+
None => panic!("unexpected None while matching on Some(NonZero(_))")
89+
}
90+
}
91+
}

0 commit comments

Comments
 (0)