about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-07-26 21:08:38 +0000
committerbors <bors@rust-lang.org>2017-07-26 21:08:38 +0000
commit599be0d18f4c6ddf36366d2a5a2ca6dc65886896 (patch)
treeb45698b672fa56662213f15740197fc32db9252f /src/libcore
parentd02fb3bcf42c05740a47fdfb0d9e5dd8ec24ff37 (diff)
parent959ebd6785b48360ac48e334a18b3abe66beef17 (diff)
downloadrust-599be0d18f4c6ddf36366d2a5a2ca6dc65886896.tar.gz
rust-599be0d18f4c6ddf36366d2a5a2ca6dc65886896.zip
Auto merge of #43487 - Mark-Simulacrum:rollup, r=Mark-Simulacrum
Rollup of 10 pull requests

- Successful merges: #42959, #43447, #43455, #43456, #43458, #43462, #43463, #43465, #43471, #43480
- Failed merges:
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/nonzero.rs89
-rw-r--r--src/libcore/num/mod.rs25
-rw-r--r--src/libcore/ptr.rs62
-rw-r--r--src/libcore/tests/nonzero.rs6
-rw-r--r--src/libcore/tests/num/mod.rs20
-rw-r--r--src/libcore/tests/ptr.rs2
6 files changed, 160 insertions, 44 deletions
diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs
index 977438051d9..3ff1068b937 100644
--- a/src/libcore/nonzero.rs
+++ b/src/libcore/nonzero.rs
@@ -16,22 +16,48 @@
 use ops::CoerceUnsized;
 
 /// Unsafe trait to indicate what types are usable with the NonZero struct
-pub unsafe trait Zeroable {}
-
-unsafe impl<T:?Sized> Zeroable for *const T {}
-unsafe impl<T:?Sized> Zeroable for *mut T {}
-unsafe impl Zeroable for isize {}
-unsafe impl Zeroable for usize {}
-unsafe impl Zeroable for i8 {}
-unsafe impl Zeroable for u8 {}
-unsafe impl Zeroable for i16 {}
-unsafe impl Zeroable for u16 {}
-unsafe impl Zeroable for i32 {}
-unsafe impl Zeroable for u32 {}
-unsafe impl Zeroable for i64 {}
-unsafe impl Zeroable for u64 {}
-unsafe impl Zeroable for i128 {}
-unsafe impl Zeroable for u128 {}
+pub unsafe trait Zeroable {
+    /// Whether this value is zero
+    fn is_zero(&self) -> bool;
+}
+
+macro_rules! impl_zeroable_for_pointer_types {
+    ( $( $Ptr: ty )+ ) => {
+        $(
+            /// For fat pointers to be considered "zero", only the "data" part needs to be null.
+            unsafe impl<T: ?Sized> Zeroable for $Ptr {
+                #[inline]
+                fn is_zero(&self) -> bool {
+                    // Cast because `is_null` is only available on thin pointers
+                    (*self as *mut u8).is_null()
+                }
+            }
+        )+
+    }
+}
+
+macro_rules! impl_zeroable_for_integer_types {
+    ( $( $Int: ty )+ ) => {
+        $(
+            unsafe impl Zeroable for $Int {
+                #[inline]
+                fn is_zero(&self) -> bool {
+                    *self == 0
+                }
+            }
+        )+
+    }
+}
+
+impl_zeroable_for_pointer_types! {
+    *const T
+    *mut T
+}
+
+impl_zeroable_for_integer_types! {
+    usize u8 u16 u32 u64 u128
+    isize i8 i16 i32 i64 i128
+}
 
 /// A wrapper type for raw pointers and integers that will never be
 /// NULL or 0 that might allow certain optimizations.
@@ -43,10 +69,20 @@ impl<T: Zeroable> NonZero<T> {
     /// Creates an instance of NonZero with the provided value.
     /// You must indeed ensure that the value is actually "non-zero".
     #[inline]
-    pub const unsafe fn new(inner: T) -> NonZero<T> {
+    pub const unsafe fn new_unchecked(inner: T) -> Self {
         NonZero(inner)
     }
 
+    /// Creates an instance of NonZero with the provided value.
+    #[inline]
+    pub fn new(inner: T) -> Option<Self> {
+        if inner.is_zero() {
+            None
+        } else {
+            Some(NonZero(inner))
+        }
+    }
+
     /// Gets the inner value.
     pub fn get(self) -> T {
         self.0
@@ -54,3 +90,22 @@ impl<T: Zeroable> NonZero<T> {
 }
 
 impl<T: Zeroable+CoerceUnsized<U>, U: Zeroable> CoerceUnsized<NonZero<U>> for NonZero<T> {}
+
+impl<'a, T: ?Sized> From<&'a mut T> for NonZero<*mut T> {
+    fn from(reference: &'a mut T) -> Self {
+        NonZero(reference)
+    }
+}
+
+impl<'a, T: ?Sized> From<&'a mut T> for NonZero<*const T> {
+    fn from(reference: &'a mut T) -> Self {
+        let ptr: *mut T = reference;
+        NonZero(ptr)
+    }
+}
+
+impl<'a, T: ?Sized> From<&'a T> for NonZero<*const T> {
+    fn from(reference: &'a T) -> Self {
+        NonZero(reference)
+    }
+}
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 185034a5313..d533310625e 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -2622,8 +2622,11 @@ try_from_both_bounded!(i32, u16, u8);
 try_from_both_bounded!(i64, u32, u16, u8);
 try_from_both_bounded!(i128, u64, u32, u16, u8);
 
-#[unstable(feature = "try_from", issue = "33417")]
-pub use self::ptr_try_from_impls::*;
+// usize/isize
+try_from_unbounded!(usize, usize);
+try_from_upper_bounded!(usize, isize);
+try_from_lower_bounded!(isize, usize);
+try_from_unbounded!(isize, isize);
 
 #[cfg(target_pointer_width = "16")]
 mod ptr_try_from_impls {
@@ -2631,12 +2634,12 @@ mod ptr_try_from_impls {
     use convert::TryFrom;
 
     try_from_upper_bounded!(usize, u8);
-    try_from_unbounded!(usize, usize, u16, u32, u64, u128);
-    try_from_upper_bounded!(usize, i8, i16, isize);
+    try_from_unbounded!(usize, u16, u32, u64, u128);
+    try_from_upper_bounded!(usize, i8, i16);
     try_from_unbounded!(usize, i32, i64, i128);
 
     try_from_both_bounded!(isize, u8);
-    try_from_lower_bounded!(isize, usize, u16, u32, u64, u128);
+    try_from_lower_bounded!(isize, u16, u32, u64, u128);
     try_from_both_bounded!(isize, i8);
     try_from_unbounded!(isize, i16, i32, i64, i128);
 
@@ -2657,12 +2660,12 @@ mod ptr_try_from_impls {
     use convert::TryFrom;
 
     try_from_upper_bounded!(usize, u8, u16);
-    try_from_unbounded!(usize, usize, u32, u64, u128);
-    try_from_upper_bounded!(usize, i8, i16, i32, isize);
+    try_from_unbounded!(usize, u32, u64, u128);
+    try_from_upper_bounded!(usize, i8, i16, i32);
     try_from_unbounded!(usize, i64, i128);
 
     try_from_both_bounded!(isize, u8, u16);
-    try_from_lower_bounded!(isize, usize, u32, u64, u128);
+    try_from_lower_bounded!(isize, u32, u64, u128);
     try_from_both_bounded!(isize, i8, i16);
     try_from_unbounded!(isize, i32, i64, i128);
 
@@ -2683,12 +2686,12 @@ mod ptr_try_from_impls {
     use convert::TryFrom;
 
     try_from_upper_bounded!(usize, u8, u16, u32);
-    try_from_unbounded!(usize, usize, u64, u128);
-    try_from_upper_bounded!(usize, i8, i16, i32, i64, isize);
+    try_from_unbounded!(usize, u64, u128);
+    try_from_upper_bounded!(usize, i8, i16, i32, i64);
     try_from_unbounded!(usize, i128);
 
     try_from_both_bounded!(isize, u8, u16, u32);
-    try_from_lower_bounded!(isize, usize, u64, u128);
+    try_from_lower_bounded!(isize, u64, u128);
     try_from_both_bounded!(isize, i8, i16, i32);
     try_from_unbounded!(isize, i64, i128);
 
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index b19e07b8578..60cf1a20530 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -16,6 +16,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+use convert::From;
 use intrinsics;
 use ops::CoerceUnsized;
 use fmt;
@@ -1098,7 +1099,7 @@ impl<T: Sized> Unique<T> {
     pub fn empty() -> Self {
         unsafe {
             let ptr = mem::align_of::<T>() as *mut T;
-            Unique::new(ptr)
+            Unique::new_unchecked(ptr)
         }
     }
 }
@@ -1110,8 +1111,13 @@ impl<T: ?Sized> Unique<T> {
     /// # Safety
     ///
     /// `ptr` must be non-null.
-    pub const unsafe fn new(ptr: *mut T) -> Unique<T> {
-        Unique { pointer: NonZero::new(ptr), _marker: PhantomData }
+    pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
+        Unique { pointer: NonZero::new_unchecked(ptr), _marker: PhantomData }
+    }
+
+    /// Creates a new `Unique` if `ptr` is non-null.
+    pub fn new(ptr: *mut T) -> Option<Self> {
+        NonZero::new(ptr as *const T).map(|nz| Unique { pointer: nz, _marker: PhantomData })
     }
 
     /// Acquires the underlying `*mut` pointer.
@@ -1138,14 +1144,14 @@ impl<T: ?Sized> Unique<T> {
     }
 }
 
-#[unstable(feature = "shared", issue = "27730")]
+#[unstable(feature = "unique", issue = "27730")]
 impl<T: ?Sized> Clone for Unique<T> {
     fn clone(&self) -> Self {
         *self
     }
 }
 
-#[unstable(feature = "shared", issue = "27730")]
+#[unstable(feature = "unique", issue = "27730")]
 impl<T: ?Sized> Copy for Unique<T> { }
 
 #[unstable(feature = "unique", issue = "27730")]
@@ -1158,6 +1164,20 @@ impl<T: ?Sized> fmt::Pointer for Unique<T> {
     }
 }
 
+#[unstable(feature = "unique", issue = "27730")]
+impl<'a, T: ?Sized> From<&'a mut T> for Unique<T> {
+    fn from(reference: &'a mut T) -> Self {
+        Unique { pointer: NonZero::from(reference), _marker: PhantomData }
+    }
+}
+
+#[unstable(feature = "unique", issue = "27730")]
+impl<'a, T: ?Sized> From<&'a T> for Unique<T> {
+    fn from(reference: &'a T) -> Self {
+        Unique { pointer: NonZero::from(reference), _marker: PhantomData }
+    }
+}
+
 /// A wrapper around a raw `*mut T` that indicates that the possessor
 /// of this wrapper has shared ownership of the referent. Useful for
 /// building abstractions like `Rc<T>`, `Arc<T>`, or doubly-linked lists, which
@@ -1212,7 +1232,7 @@ impl<T: Sized> Shared<T> {
     pub fn empty() -> Self {
         unsafe {
             let ptr = mem::align_of::<T>() as *mut T;
-            Shared::new(ptr)
+            Shared::new_unchecked(ptr)
         }
     }
 }
@@ -1224,8 +1244,13 @@ impl<T: ?Sized> Shared<T> {
     /// # Safety
     ///
     /// `ptr` must be non-null.
-    pub unsafe fn new(ptr: *mut T) -> Self {
-        Shared { pointer: NonZero::new(ptr), _marker: PhantomData }
+    pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
+        Shared { pointer: NonZero::new_unchecked(ptr), _marker: PhantomData }
+    }
+
+    /// Creates a new `Shared` if `ptr` is non-null.
+    pub fn new(ptr: *mut T) -> Option<Self> {
+        NonZero::new(ptr as *const T).map(|nz| Shared { pointer: nz, _marker: PhantomData })
     }
 
     /// Acquires the underlying `*mut` pointer.
@@ -1278,3 +1303,24 @@ impl<T: ?Sized> fmt::Pointer for Shared<T> {
         fmt::Pointer::fmt(&self.as_ptr(), f)
     }
 }
+
+#[unstable(feature = "shared", issue = "27730")]
+impl<T: ?Sized> From<Unique<T>> for Shared<T> {
+    fn from(unique: Unique<T>) -> Self {
+        Shared { pointer: unique.pointer, _marker: PhantomData }
+    }
+}
+
+#[unstable(feature = "shared", issue = "27730")]
+impl<'a, T: ?Sized> From<&'a mut T> for Shared<T> {
+    fn from(reference: &'a mut T) -> Self {
+        Shared { pointer: NonZero::from(reference), _marker: PhantomData }
+    }
+}
+
+#[unstable(feature = "shared", issue = "27730")]
+impl<'a, T: ?Sized> From<&'a T> for Shared<T> {
+    fn from(reference: &'a T) -> Self {
+        Shared { pointer: NonZero::from(reference), _marker: PhantomData }
+    }
+}
diff --git a/src/libcore/tests/nonzero.rs b/src/libcore/tests/nonzero.rs
index 588fffda35f..a795dd57504 100644
--- a/src/libcore/tests/nonzero.rs
+++ b/src/libcore/tests/nonzero.rs
@@ -16,7 +16,7 @@ use std::mem::size_of;
 #[test]
 fn test_create_nonzero_instance() {
     let _a = unsafe {
-        NonZero::new(21)
+        NonZero::new_unchecked(21)
     };
 }
 
@@ -28,14 +28,14 @@ fn test_size_nonzero_in_option() {
 #[test]
 fn test_match_on_nonzero_option() {
     let a = Some(unsafe {
-        NonZero::new(42)
+        NonZero::new_unchecked(42)
     });
     match a {
         Some(val) => assert_eq!(val.get(), 42),
         None => panic!("unexpected None while matching on Some(NonZero(_))")
     }
 
-    match unsafe { Some(NonZero::new(43)) } {
+    match unsafe { Some(NonZero::new_unchecked(43)) } {
         Some(val) => assert_eq!(val.get(), 43),
         None => panic!("unexpected None while matching on Some(NonZero(_))")
     }
diff --git a/src/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs
index 3e872b34e43..046b81e19f7 100644
--- a/src/libcore/tests/num/mod.rs
+++ b/src/libcore/tests/num/mod.rs
@@ -279,7 +279,7 @@ test_impl_try_from_always_ok! { test_try_u64u64, u64, u64 }
 test_impl_try_from_always_ok! { test_try_u64u128, u64, u128 }
 test_impl_try_from_always_ok! { test_try_u64i128, u64, i128 }
 
-test_impl_try_from_always_ok! { test_try_u128, u128, u128 }
+test_impl_try_from_always_ok! { test_try_u128u128, u128, u128 }
 
 test_impl_try_from_always_ok! { test_try_i8i8, i8, i8 }
 test_impl_try_from_always_ok! { test_try_i8i16, i8, i16 }
@@ -301,8 +301,12 @@ test_impl_try_from_always_ok! { test_try_i64i128, i64, i128 }
 
 test_impl_try_from_always_ok! { test_try_i128i128, i128, i128 }
 
+test_impl_try_from_always_ok! { test_try_usizeusize, usize, usize }
+test_impl_try_from_always_ok! { test_try_isizeisize, isize, isize }
+
 assume_usize_width! {
     test_impl_try_from_always_ok! { test_try_u8usize, u8, usize }
+    test_impl_try_from_always_ok! { test_try_u8isize, u8, isize }
     test_impl_try_from_always_ok! { test_try_i8isize, i8, isize }
 
     test_impl_try_from_always_ok! { test_try_u16usize, u16, usize }
@@ -317,19 +321,27 @@ assume_usize_width! {
 
     cfg_block!(
         #[cfg(target_pointer_width = "16")] {
-            test_impl_try_from_always_ok! { test_try_u16usize, u16, usize }
-            test_impl_try_from_always_ok! { test_try_i16isize, i16, isize }
+            test_impl_try_from_always_ok! { test_try_usizeu16, usize, u16 }
+            test_impl_try_from_always_ok! { test_try_isizei16, isize, i16 }
+            test_impl_try_from_always_ok! { test_try_usizeu32, usize, u32 }
+            test_impl_try_from_always_ok! { test_try_usizei32, usize, i32 }
+            test_impl_try_from_always_ok! { test_try_isizei32, isize, i32 }
+            test_impl_try_from_always_ok! { test_try_usizei64, usize, i64 }
         }
 
         #[cfg(target_pointer_width = "32")] {
+            test_impl_try_from_always_ok! { test_try_u16isize, u16, isize }
             test_impl_try_from_always_ok! { test_try_usizeu32, usize, u32 }
             test_impl_try_from_always_ok! { test_try_isizei32, isize, i32 }
             test_impl_try_from_always_ok! { test_try_u32usize, u32, usize }
             test_impl_try_from_always_ok! { test_try_i32isize, i32, isize }
+            test_impl_try_from_always_ok! { test_try_usizei64, usize, i64 }
         }
 
         #[cfg(target_pointer_width = "64")] {
+            test_impl_try_from_always_ok! { test_try_u16isize, u16, isize }
             test_impl_try_from_always_ok! { test_try_u32usize, u32, usize }
+            test_impl_try_from_always_ok! { test_try_u32isize, u32, isize }
             test_impl_try_from_always_ok! { test_try_i32isize, i32, isize }
             test_impl_try_from_always_ok! { test_try_u64usize, u64, usize }
             test_impl_try_from_always_ok! { test_try_i64isize, i64, isize }
@@ -451,8 +463,8 @@ assume_usize_width! {
 
     cfg_block!(
         #[cfg(target_pointer_width = "16")] {
+            test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u16isize, u16, isize }
             test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32isize, u32, isize }
-            test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32isize, u64, isize }
         }
 
         #[cfg(target_pointer_width = "32")] {
diff --git a/src/libcore/tests/ptr.rs b/src/libcore/tests/ptr.rs
index e28dc6a6881..c2d53840f8f 100644
--- a/src/libcore/tests/ptr.rs
+++ b/src/libcore/tests/ptr.rs
@@ -167,7 +167,7 @@ fn test_set_memory() {
 #[test]
 fn test_unsized_unique() {
     let xs: &[i32] = &[1, 2, 3];
-    let ptr = unsafe { Unique::new(xs as *const [i32] as *mut [i32]) };
+    let ptr = unsafe { Unique::new_unchecked(xs as *const [i32] as *mut [i32]) };
     let ys = unsafe { ptr.as_ref() };
     let zs: &[i32] = &[1, 2, 3];
     assert!(ys == zs);