summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-11-07 20:55:01 +0000
committerbors <bors@rust-lang.org>2017-11-07 20:55:01 +0000
commitee2286149a5f0b148334841d4f067dc819dcca3b (patch)
tree5b4b0668d459e417c61355d519ff3675b6ec80a5
parent7f6417e9b72de63666fd92caf1a6b96a778b60ed (diff)
parent604f049cd5060129cf14f7bd340d442811345ea8 (diff)
downloadrust-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.rs18
-rw-r--r--src/libcore/tests/ptr.rs51
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());
}
}