From e0f58c6a11c7990a302b47c488dc2f13fab7b9a1 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 10 Oct 2017 11:35:41 -0700 Subject: [PATCH] Remove `T: Sized` on `ptr::is_null()` This reverts commit 604f049cd5060129cf14f7bd340d442811345ea8. This is purely a revert of cuviper's revert "Restore `T: Sized` on `ptr::is_null`". So double revert means this is code written by cuviper! --- src/libcore/nonzero.rs | 3 +-- src/libcore/ptr.rs | 34 +++++++++++++++++++++------------- src/libcore/tests/ptr.rs | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 15 deletions(-) diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs index edc0104f46b5c..ec277b4ae99c7 100644 --- a/src/libcore/nonzero.rs +++ b/src/libcore/nonzero.rs @@ -28,8 +28,7 @@ macro_rules! impl_zeroable_for_pointer_types { unsafe impl 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 126558e3025d5..19553d0c37b83 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -474,6 +474,11 @@ pub unsafe fn write_volatile(dst: *mut T, src: T) { impl *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 *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 *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 *const T { impl *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 *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 *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 *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 e93e9be0cd50b..98436f0e1d1cd 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::(); + assert!(nci.is_null()); + + let nmi: *mut ToString = null_mut::(); + assert!(nmi.is_null()); } #[test]