diff options
author | bors <bors@rust-lang.org> | 2017-11-07 20:55:01 +0000 |
---|---|---|
committer | bors <bors@rust-lang.org> | 2017-11-07 20:55:01 +0000 |
commit | ee2286149a5f0b148334841d4f067dc819dcca3b (patch) | |
tree | 5b4b0668d459e417c61355d519ff3675b6ec80a5 | |
parent | 7f6417e9b72de63666fd92caf1a6b96a778b60ed (diff) | |
parent | 604f049cd5060129cf14f7bd340d442811345ea8 (diff) | |
download | rust-ee2286149a5f0b148334841d4f067dc819dcca3b.tar.gz |
Auto merge of #44932 - cuviper:unsized-ptr-is_null, r=alexcrichton
Remove `T: Sized` on pointer `as_ref()` and `as_mut()`
`NonZero::is_zero()` was already casting all pointers to thin `*mut u8` to check for null. The same test on unsized fat pointers can also be used with `as_ref()` and `as_mut()` to get fat references.
(This PR formerly changed `is_null()` too, but checking just the data pointer is not obviously correct for trait objects, especially if `*const self` sorts of methods are ever allowed.)
-rw-r--r-- | src/libcore/ptr.rs | 18 | ||||
-rw-r--r-- | src/libcore/tests/ptr.rs | 51 |
2 files changed, 63 insertions, 6 deletions
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 5cd672b03ff..126558e3025 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -517,8 +517,10 @@ 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> where T: Sized { - if self.is_null() { + 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() { None } else { Some(&*self) @@ -1148,8 +1150,10 @@ 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> where T: Sized { - if self.is_null() { + 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() { None } else { Some(&*self) @@ -1272,8 +1276,10 @@ 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> where T: Sized { - if self.is_null() { + 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() { None } else { Some(&mut *self) diff --git a/src/libcore/tests/ptr.rs b/src/libcore/tests/ptr.rs index c2d53840f8f..e93e9be0cd5 100644 --- a/src/libcore/tests/ptr.rs +++ b/src/libcore/tests/ptr.rs @@ -85,6 +85,39 @@ fn test_as_ref() { let p = &u as *const isize; assert_eq!(p.as_ref().unwrap(), &2); } + + // Pointers to unsized types -- slices + 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] = null::<[u8; 3]>(); + assert_eq!(ncs.as_ref(), None); + + let nms: *mut [u8] = null_mut::<[u8; 3]>(); + assert_eq!(nms.as_ref(), None); + + // Pointers to unsized types -- trait objects + let ci: *const ToString = &3; + assert!(ci.as_ref().is_some()); + + let mi: *mut ToString = &mut 3; + assert!(mi.as_ref().is_some()); + + let nci: *const ToString = null::<isize>(); + assert!(nci.as_ref().is_none()); + + let nmi: *mut ToString = null_mut::<isize>(); + assert!(nmi.as_ref().is_none()); } } @@ -103,6 +136,24 @@ fn test_as_mut() { let p = &mut u as *mut isize; assert!(p.as_mut().unwrap() == &mut 2); } + + // Pointers to unsized types -- slices + 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] = null_mut::<[u8; 3]>(); + assert_eq!(nms.as_mut(), None); + + // Pointers to unsized types -- trait objects + let mi: *mut ToString = &mut 3; + assert!(mi.as_mut().is_some()); + + let nmi: *mut ToString = null_mut::<isize>(); + assert!(nmi.as_mut().is_none()); } } |