Skip to content

Commit ee22861

Browse files
committed
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.)
2 parents 7f6417e + 604f049 commit ee22861

File tree

2 files changed

+63
-6
lines changed

2 files changed

+63
-6
lines changed

src/libcore/ptr.rs

+12-6
Original file line numberDiff line numberDiff line change
@@ -517,8 +517,10 @@ impl<T: ?Sized> *const T {
517517
/// ```
518518
#[stable(feature = "ptr_as_ref", since = "1.9.0")]
519519
#[inline]
520-
pub unsafe fn as_ref<'a>(self) -> Option<&'a T> where T: Sized {
521-
if self.is_null() {
520+
pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
521+
// Check for null via a cast to a thin pointer, so fat pointers are only
522+
// considering their "data" part for null-ness.
523+
if (self as *const u8).is_null() {
522524
None
523525
} else {
524526
Some(&*self)
@@ -1148,8 +1150,10 @@ impl<T: ?Sized> *mut T {
11481150
/// ```
11491151
#[stable(feature = "ptr_as_ref", since = "1.9.0")]
11501152
#[inline]
1151-
pub unsafe fn as_ref<'a>(self) -> Option<&'a T> where T: Sized {
1152-
if self.is_null() {
1153+
pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
1154+
// Check for null via a cast to a thin pointer, so fat pointers are only
1155+
// considering their "data" part for null-ness.
1156+
if (self as *const u8).is_null() {
11531157
None
11541158
} else {
11551159
Some(&*self)
@@ -1272,8 +1276,10 @@ impl<T: ?Sized> *mut T {
12721276
/// ```
12731277
#[stable(feature = "ptr_as_ref", since = "1.9.0")]
12741278
#[inline]
1275-
pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> where T: Sized {
1276-
if self.is_null() {
1279+
pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> {
1280+
// Check for null via a cast to a thin pointer, so fat pointers are only
1281+
// considering their "data" part for null-ness.
1282+
if (self as *mut u8).is_null() {
12771283
None
12781284
} else {
12791285
Some(&mut *self)

src/libcore/tests/ptr.rs

+51
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,39 @@ fn test_as_ref() {
8585
let p = &u as *const isize;
8686
assert_eq!(p.as_ref().unwrap(), &2);
8787
}
88+
89+
// Pointers to unsized types -- slices
90+
let s: &mut [u8] = &mut [1, 2, 3];
91+
let cs: *const [u8] = s;
92+
assert_eq!(cs.as_ref(), Some(&*s));
93+
94+
let ms: *mut [u8] = s;
95+
assert_eq!(ms.as_ref(), Some(&*s));
96+
97+
let cz: *const [u8] = &[];
98+
assert_eq!(cz.as_ref(), Some(&[][..]));
99+
100+
let mz: *mut [u8] = &mut [];
101+
assert_eq!(mz.as_ref(), Some(&[][..]));
102+
103+
let ncs: *const [u8] = null::<[u8; 3]>();
104+
assert_eq!(ncs.as_ref(), None);
105+
106+
let nms: *mut [u8] = null_mut::<[u8; 3]>();
107+
assert_eq!(nms.as_ref(), None);
108+
109+
// Pointers to unsized types -- trait objects
110+
let ci: *const ToString = &3;
111+
assert!(ci.as_ref().is_some());
112+
113+
let mi: *mut ToString = &mut 3;
114+
assert!(mi.as_ref().is_some());
115+
116+
let nci: *const ToString = null::<isize>();
117+
assert!(nci.as_ref().is_none());
118+
119+
let nmi: *mut ToString = null_mut::<isize>();
120+
assert!(nmi.as_ref().is_none());
88121
}
89122
}
90123

@@ -103,6 +136,24 @@ fn test_as_mut() {
103136
let p = &mut u as *mut isize;
104137
assert!(p.as_mut().unwrap() == &mut 2);
105138
}
139+
140+
// Pointers to unsized types -- slices
141+
let s: &mut [u8] = &mut [1, 2, 3];
142+
let ms: *mut [u8] = s;
143+
assert_eq!(ms.as_mut(), Some(s));
144+
145+
let mz: *mut [u8] = &mut [];
146+
assert_eq!(mz.as_mut(), Some(&mut [][..]));
147+
148+
let nms: *mut [u8] = null_mut::<[u8; 3]>();
149+
assert_eq!(nms.as_mut(), None);
150+
151+
// Pointers to unsized types -- trait objects
152+
let mi: *mut ToString = &mut 3;
153+
assert!(mi.as_mut().is_some());
154+
155+
let nmi: *mut ToString = null_mut::<isize>();
156+
assert!(nmi.as_mut().is_none());
106157
}
107158
}
108159

0 commit comments

Comments
 (0)