From 3580c4c58940ad5d62a068609b9b696e8eb31309 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 29 Sep 2017 12:36:32 -0700 Subject: [PATCH] Remove `T: Sized` on `ptr::is_null()`, `as_ref()`, `as_mut()` `NonZero::is_zero()` was already casting all pointers to thin `*mut u8` to check for null. It seems reasonable to apply that for `is_null()` in general, and then unsized fat pointers can also be used with `as_ref()` and `as_mut()` to get fat references. --- src/libcore/nonzero.rs | 3 +-- src/libcore/ptr.rs | 18 ++++++++------ src/libcore/tests/ptr.rs | 54 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 9 deletions(-) diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs index f075d825f5d53..8271be5d38f88 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 4041a3760e5ca..dddeda7f02dec 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -487,8 +487,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 @@ -519,7 +521,7 @@ impl *const T { /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] #[inline] - pub unsafe fn as_ref<'a>(self) -> Option<&'a T> where T: Sized { + pub unsafe fn as_ref<'a>(self) -> Option<&'a T> { if self.is_null() { None } else { @@ -1118,8 +1120,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 @@ -1150,7 +1154,7 @@ impl *mut T { /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] #[inline] - pub unsafe fn as_ref<'a>(self) -> Option<&'a T> where T: Sized { + pub unsafe fn as_ref<'a>(self) -> Option<&'a T> { if self.is_null() { None } else { @@ -1274,7 +1278,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> where T: Sized { + pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> { if self.is_null() { None } else { diff --git a/src/libcore/tests/ptr.rs b/src/libcore/tests/ptr.rs index c2d53840f8f57..4bd725f828f02 100644 --- a/src/libcore/tests/ptr.rs +++ b/src/libcore/tests/ptr.rs @@ -9,6 +9,7 @@ // except according to those terms. use core::ptr::*; +use core::slice; use core::cell::RefCell; #[test] @@ -62,6 +63,28 @@ fn test_is_null() { let mq = unsafe { mp.offset(1) }; assert!(!mq.is_null()); + + // Pointers to unsized types + 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()); + + unsafe { + let ncs: *const [u8] = slice::from_raw_parts(null(), 0); + assert!(ncs.is_null()); + + let nms: *mut [u8] = slice::from_raw_parts_mut(null_mut(), 0); + assert!(nms.is_null()); + } } #[test] @@ -85,6 +108,26 @@ fn test_as_ref() { let p = &u as *const isize; assert_eq!(p.as_ref().unwrap(), &2); } + + // Pointers to unsized types + let s: &mut [u8] = &mut [1, 2, 3]; + let cs: *const [u8] = s; + assert_eq!(cs.as_ref(), Some(&*s)); + + let ms: *mut [u8] = s; + assert_eq!(ms.as_ref(), Some(&*s)); + + let cz: *const [u8] = &[]; + assert_eq!(cz.as_ref(), Some(&[][..])); + + let mz: *mut [u8] = &mut []; + assert_eq!(mz.as_ref(), Some(&[][..])); + + let ncs: *const [u8] = slice::from_raw_parts(null(), 0); + assert_eq!(ncs.as_ref(), None); + + let nms: *mut [u8] = slice::from_raw_parts_mut(null_mut(), 0); + assert_eq!(nms.as_ref(), None); } } @@ -103,6 +146,17 @@ fn test_as_mut() { let p = &mut u as *mut isize; assert!(p.as_mut().unwrap() == &mut 2); } + + // Pointers to unsized types + let s: &mut [u8] = &mut [1, 2, 3]; + let ms: *mut [u8] = s; + assert_eq!(ms.as_mut(), Some(s)); + + let mz: *mut [u8] = &mut []; + assert_eq!(mz.as_mut(), Some(&mut [][..])); + + let nms: *mut [u8] = slice::from_raw_parts_mut(null_mut(), 0); + assert_eq!(nms.as_mut(), None); } }