about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libcore/nonzero.rs3
-rw-r--r--src/libcore/ptr.rs34
-rw-r--r--src/libcore/tests/ptr.rs33
3 files changed, 55 insertions, 15 deletions
diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs
index edc0104f46b..ec277b4ae99 100644
--- a/src/libcore/nonzero.rs
+++ b/src/libcore/nonzero.rs
@@ -28,8 +28,7 @@ macro_rules! impl_zeroable_for_pointer_types {
             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()
+                    (*self).is_null()
                 }
             }
         )+
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 126558e3025..19553d0c37b 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -474,6 +474,11 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
 impl<T: ?Sized> *const T {
     /// Returns `true` if the pointer is null.
     ///
+    /// Note that unsized types have many possible null pointers, as only the
+    /// raw data pointer is considered, not their length, vtable, etc.
+    /// Therefore, two pointers that are null may still not compare equal to
+    /// each other.
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -485,8 +490,10 @@ impl<T: ?Sized> *const T {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn is_null(self) -> bool where T: Sized {
-        self == null()
+    pub fn is_null(self) -> bool {
+        // Compare via a cast to a thin pointer, so fat pointers are only
+        // considering their "data" part for null-ness.
+        (self as *const u8) == null()
     }
 
     /// Returns `None` if the pointer is null, or else returns a reference to
@@ -518,9 +525,7 @@ impl<T: ?Sized> *const T {
     #[stable(feature = "ptr_as_ref", since = "1.9.0")]
     #[inline]
     pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
-        // Check for null via a cast to a thin pointer, so fat pointers are only
-        // considering their "data" part for null-ness.
-        if (self as *const u8).is_null() {
+        if self.is_null() {
             None
         } else {
             Some(&*self)
@@ -1107,6 +1112,11 @@ impl<T: ?Sized> *const T {
 impl<T: ?Sized> *mut T {
     /// Returns `true` if the pointer is null.
     ///
+    /// Note that unsized types have many possible null pointers, as only the
+    /// raw data pointer is considered, not their length, vtable, etc.
+    /// Therefore, two pointers that are null may still not compare equal to
+    /// each other.
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -1118,8 +1128,10 @@ impl<T: ?Sized> *mut T {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn is_null(self) -> bool where T: Sized {
-        self == null_mut()
+    pub fn is_null(self) -> bool {
+        // Compare via a cast to a thin pointer, so fat pointers are only
+        // considering their "data" part for null-ness.
+        (self as *mut u8) == null_mut()
     }
 
     /// Returns `None` if the pointer is null, or else returns a reference to
@@ -1151,9 +1163,7 @@ impl<T: ?Sized> *mut T {
     #[stable(feature = "ptr_as_ref", since = "1.9.0")]
     #[inline]
     pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
-        // Check for null via a cast to a thin pointer, so fat pointers are only
-        // considering their "data" part for null-ness.
-        if (self as *const u8).is_null() {
+        if self.is_null() {
             None
         } else {
             Some(&*self)
@@ -1277,9 +1287,7 @@ impl<T: ?Sized> *mut T {
     #[stable(feature = "ptr_as_ref", since = "1.9.0")]
     #[inline]
     pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> {
-        // Check for null via a cast to a thin pointer, so fat pointers are only
-        // considering their "data" part for null-ness.
-        if (self as *mut u8).is_null() {
+        if self.is_null() {
             None
         } else {
             Some(&mut *self)
diff --git a/src/libcore/tests/ptr.rs b/src/libcore/tests/ptr.rs
index e93e9be0cd5..98436f0e1d1 100644
--- a/src/libcore/tests/ptr.rs
+++ b/src/libcore/tests/ptr.rs
@@ -62,6 +62,39 @@ fn test_is_null() {
 
     let mq = unsafe { mp.offset(1) };
     assert!(!mq.is_null());
+
+    // Pointers to unsized types -- slices
+    let s: &mut [u8] = &mut [1, 2, 3];
+    let cs: *const [u8] = s;
+    assert!(!cs.is_null());
+
+    let ms: *mut [u8] = s;
+    assert!(!ms.is_null());
+
+    let cz: *const [u8] = &[];
+    assert!(!cz.is_null());
+
+    let mz: *mut [u8] = &mut [];
+    assert!(!mz.is_null());
+
+    let ncs: *const [u8] = null::<[u8; 3]>();
+    assert!(ncs.is_null());
+
+    let nms: *mut [u8] = null_mut::<[u8; 3]>();
+    assert!(nms.is_null());
+
+    // Pointers to unsized types -- trait objects
+    let ci: *const ToString = &3;
+    assert!(!ci.is_null());
+
+    let mi: *mut ToString = &mut 3;
+    assert!(!mi.is_null());
+
+    let nci: *const ToString = null::<isize>();
+    assert!(nci.is_null());
+
+    let nmi: *mut ToString = null_mut::<isize>();
+    assert!(nmi.is_null());
 }
 
 #[test]