Skip to content

Commit c48f9ca

Browse files
committed
const: make ptr.is_null() stop execution on ambiguity
1 parent 7b18b3e commit c48f9ca

File tree

4 files changed

+45
-20
lines changed

4 files changed

+45
-20
lines changed

library/core/src/ptr/const_ptr.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,16 @@ impl<T: ?Sized> *const T {
4040

4141
#[inline]
4242
const fn const_impl(ptr: *const u8) -> bool {
43-
// Compare via a cast to a thin pointer, so fat pointers are only
44-
// considering their "data" part for null-ness.
4543
match (ptr).guaranteed_eq(null_mut()) {
46-
None => false,
4744
Some(res) => res,
45+
// To remain maximally convervative, we stop execution when we don't
46+
// know whether the pointer is null or not.
47+
None => panic!("null-ness of this pointer cannot be determined in const context"),
4848
}
4949
}
5050

51-
#[allow(unused_unsafe)]
51+
// Compare via a cast to a thin pointer, so fat pointers are only
52+
// considering their "data" part for null-ness.
5253
const_eval_select((self as *const u8,), const_impl, runtime_impl)
5354
}
5455

library/core/src/ptr/mut_ptr.rs

+1-16
Original file line numberDiff line numberDiff line change
@@ -33,22 +33,7 @@ impl<T: ?Sized> *mut T {
3333
#[rustc_diagnostic_item = "ptr_is_null"]
3434
#[inline]
3535
pub const fn is_null(self) -> bool {
36-
#[inline]
37-
fn runtime_impl(ptr: *mut u8) -> bool {
38-
ptr.addr() == 0
39-
}
40-
41-
#[inline]
42-
const fn const_impl(ptr: *mut u8) -> bool {
43-
// Compare via a cast to a thin pointer, so fat pointers are only
44-
// considering their "data" part for null-ness.
45-
match (ptr).guaranteed_eq(null_mut()) {
46-
None => false,
47-
Some(res) => res,
48-
}
49-
}
50-
51-
const_eval_select((self as *mut u8,), const_impl, runtime_impl)
36+
self.cast_const().is_null()
5237
}
5338

5439
/// Casts to a pointer of another type.

tests/ui/consts/const-ptr-is-null.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#![feature(const_ptr_is_null)]
2+
use std::ptr;
3+
4+
const IS_NULL: () = {
5+
assert!(ptr::null::<u8>().is_null());
6+
};
7+
const IS_NOT_NULL: () = {
8+
assert!(!ptr::null::<u8>().wrapping_add(1).is_null());
9+
};
10+
11+
const MAYBE_NULL: () = {
12+
let x = 15;
13+
let ptr = &x as *const i32;
14+
// This one is still unambiguous...
15+
assert!(!ptr.is_null());
16+
// but once we shift outside the allocation, we might become null.
17+
assert!(!ptr.wrapping_sub(512).is_null()); //~inside `MAYBE_NULL`
18+
};
19+
20+
fn main() {}
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0080]: evaluation of constant value failed
2+
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
3+
|
4+
= note: the evaluated program panicked at 'null-ness of this pointer cannot be determined in const context', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
5+
|
6+
note: inside `std::ptr::const_ptr::<impl *const T>::is_null::const_impl`
7+
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
8+
note: inside `std::ptr::const_ptr::<impl *const i32>::is_null`
9+
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
10+
note: inside `MAYBE_NULL`
11+
--> $DIR/const-ptr-is-null.rs:17:14
12+
|
13+
LL | assert!(!ptr.wrapping_sub(512).is_null());
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15+
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
16+
17+
error: aborting due to 1 previous error
18+
19+
For more information about this error, try `rustc --explain E0080`.

0 commit comments

Comments
 (0)