Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 604f049

Browse files
committedOct 10, 2017
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.
1 parent 40a678d commit 604f049

File tree

3 files changed

+15
-55
lines changed

3 files changed

+15
-55
lines changed
 

‎src/libcore/nonzero.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ macro_rules! impl_zeroable_for_pointer_types {
2828
unsafe impl<T: ?Sized> Zeroable for $Ptr {
2929
#[inline]
3030
fn is_zero(&self) -> bool {
31-
(*self).is_null()
31+
// Cast because `is_null` is only available on thin pointers
32+
(*self as *mut u8).is_null()
3233
}
3334
}
3435
)+

‎src/libcore/ptr.rs

+13-21
Original file line numberDiff line numberDiff line change
@@ -476,11 +476,6 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
476476
impl<T: ?Sized> *const T {
477477
/// Returns `true` if the pointer is null.
478478
///
479-
/// Note that unsized types have many possible null pointers, as only the
480-
/// raw data pointer is considered, not their length, vtable, etc.
481-
/// Therefore, two pointers that are null may still not compare equal to
482-
/// each other.
483-
///
484479
/// # Examples
485480
///
486481
/// Basic usage:
@@ -492,10 +487,8 @@ impl<T: ?Sized> *const T {
492487
/// ```
493488
#[stable(feature = "rust1", since = "1.0.0")]
494489
#[inline]
495-
pub fn is_null(self) -> bool {
496-
// Compare via a cast to a thin pointer, so fat pointers are only
497-
// considering their "data" part for null-ness.
498-
(self as *const u8) == null()
490+
pub fn is_null(self) -> bool where T: Sized {
491+
self == null()
499492
}
500493

501494
/// Returns `None` if the pointer is null, or else returns a reference to
@@ -527,7 +520,9 @@ impl<T: ?Sized> *const T {
527520
#[stable(feature = "ptr_as_ref", since = "1.9.0")]
528521
#[inline]
529522
pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
530-
if self.is_null() {
523+
// Check for null via a cast to a thin pointer, so fat pointers are only
524+
// considering their "data" part for null-ness.
525+
if (self as *const u8).is_null() {
531526
None
532527
} else {
533528
Some(&*self)
@@ -1114,11 +1109,6 @@ impl<T: ?Sized> *const T {
11141109
impl<T: ?Sized> *mut T {
11151110
/// Returns `true` if the pointer is null.
11161111
///
1117-
/// Note that unsized types have many possible null pointers, as only the
1118-
/// raw data pointer is considered, not their length, vtable, etc.
1119-
/// Therefore, two pointers that are null may still not compare equal to
1120-
/// each other.
1121-
///
11221112
/// # Examples
11231113
///
11241114
/// Basic usage:
@@ -1130,10 +1120,8 @@ impl<T: ?Sized> *mut T {
11301120
/// ```
11311121
#[stable(feature = "rust1", since = "1.0.0")]
11321122
#[inline]
1133-
pub fn is_null(self) -> bool {
1134-
// Compare via a cast to a thin pointer, so fat pointers are only
1135-
// considering their "data" part for null-ness.
1136-
(self as *mut u8) == null_mut()
1123+
pub fn is_null(self) -> bool where T: Sized {
1124+
self == null_mut()
11371125
}
11381126

11391127
/// Returns `None` if the pointer is null, or else returns a reference to
@@ -1165,7 +1153,9 @@ impl<T: ?Sized> *mut T {
11651153
#[stable(feature = "ptr_as_ref", since = "1.9.0")]
11661154
#[inline]
11671155
pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
1168-
if self.is_null() {
1156+
// Check for null via a cast to a thin pointer, so fat pointers are only
1157+
// considering their "data" part for null-ness.
1158+
if (self as *const u8).is_null() {
11691159
None
11701160
} else {
11711161
Some(&*self)
@@ -1289,7 +1279,9 @@ impl<T: ?Sized> *mut T {
12891279
#[stable(feature = "ptr_as_ref", since = "1.9.0")]
12901280
#[inline]
12911281
pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> {
1292-
if self.is_null() {
1282+
// Check for null via a cast to a thin pointer, so fat pointers are only
1283+
// considering their "data" part for null-ness.
1284+
if (self as *mut u8).is_null() {
12931285
None
12941286
} else {
12951287
Some(&mut *self)

‎src/libcore/tests/ptr.rs

-33
Original file line numberDiff line numberDiff line change
@@ -62,39 +62,6 @@ fn test_is_null() {
6262

6363
let mq = unsafe { mp.offset(1) };
6464
assert!(!mq.is_null());
65-
66-
// Pointers to unsized types -- slices
67-
let s: &mut [u8] = &mut [1, 2, 3];
68-
let cs: *const [u8] = s;
69-
assert!(!cs.is_null());
70-
71-
let ms: *mut [u8] = s;
72-
assert!(!ms.is_null());
73-
74-
let cz: *const [u8] = &[];
75-
assert!(!cz.is_null());
76-
77-
let mz: *mut [u8] = &mut [];
78-
assert!(!mz.is_null());
79-
80-
let ncs: *const [u8] = null::<[u8; 3]>();
81-
assert!(ncs.is_null());
82-
83-
let nms: *mut [u8] = null_mut::<[u8; 3]>();
84-
assert!(nms.is_null());
85-
86-
// Pointers to unsized types -- trait objects
87-
let ci: *const ToString = &3;
88-
assert!(!ci.is_null());
89-
90-
let mi: *mut ToString = &mut 3;
91-
assert!(!mi.is_null());
92-
93-
let nci: *const ToString = null::<isize>();
94-
assert!(nci.is_null());
95-
96-
let nmi: *mut ToString = null_mut::<isize>();
97-
assert!(nmi.is_null());
9865
}
9966

10067
#[test]

0 commit comments

Comments
 (0)
Please sign in to comment.