diff options
| author | Josh Stone <jistone@redhat.com> | 2017-10-10 11:35:41 -0700 |
|---|---|---|
| committer | Josh Stone <jistone@redhat.com> | 2017-10-10 11:35:41 -0700 |
| commit | 604f049cd5060129cf14f7bd340d442811345ea8 (patch) | |
| tree | 63f8e90d66dc57fbae77142dc618feb61236fbf2 /src/libcore | |
| parent | 40a678d8dbaea49a2e9f5451f4db68359a09f67a (diff) | |
Restore `T: Sized` on `ptr::is_null`
The exact semantics of `is_null` on unsized pointers are still debatable, especially for trait objects. It may be legal to call `*mut self` methods on a trait object someday, as with Go interfaces, so `is_null` might need to validate the vtable pointer too. For `as_ref` and `as_mut`, we're assuming that you cannot have a non-null data pointer with a null vtable, so casting the unsized check is fine.
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/nonzero.rs | 3 | ||||
| -rw-r--r-- | src/libcore/ptr.rs | 34 | ||||
| -rw-r--r-- | src/libcore/tests/ptr.rs | 33 |
3 files changed, 15 insertions, 55 deletions
diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs index 8271be5d38f..f075d825f5d 100644 --- a/src/libcore/nonzero.rs +++ b/src/libcore/nonzero.rs @@ -28,7 +28,8 @@ macro_rules! impl_zeroable_for_pointer_types { unsafe impl<T: ?Sized> Zeroable for $Ptr { #[inline] fn is_zero(&self) -> bool { - (*self).is_null() + // Cast because `is_null` is only available on thin pointers + (*self as *mut u8).is_null() } } )+ diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 474658b65a1..7d0cdc27571 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -476,11 +476,6 @@ 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: @@ -492,10 +487,8 @@ impl<T: ?Sized> *const T { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - 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() + pub fn is_null(self) -> bool where T: Sized { + self == null() } /// Returns `None` if the pointer is null, or else returns a reference to @@ -527,7 +520,9 @@ 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> { - if self.is_null() { + // 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() { None } else { Some(&*self) @@ -1114,11 +1109,6 @@ 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: @@ -1130,10 +1120,8 @@ impl<T: ?Sized> *mut T { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - 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() + pub fn is_null(self) -> bool where T: Sized { + self == null_mut() } /// Returns `None` if the pointer is null, or else returns a reference to @@ -1165,7 +1153,9 @@ 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> { - if self.is_null() { + // 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() { None } else { Some(&*self) @@ -1289,7 +1279,9 @@ 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> { - if self.is_null() { + // 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() { None } else { Some(&mut *self) diff --git a/src/libcore/tests/ptr.rs b/src/libcore/tests/ptr.rs index 98436f0e1d1..e93e9be0cd5 100644 --- a/src/libcore/tests/ptr.rs +++ b/src/libcore/tests/ptr.rs @@ -62,39 +62,6 @@ 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] |
