const: make ptr.is_null() stop execution on ambiguity
This commit is contained in:
@@ -40,15 +40,17 @@ impl<T: ?Sized> *const T {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
const fn const_impl(ptr: *const u8) -> bool {
|
const fn const_impl(ptr: *const u8) -> bool {
|
||||||
// Compare via a cast to a thin pointer, so fat pointers are only
|
|
||||||
// considering their "data" part for null-ness.
|
|
||||||
match (ptr).guaranteed_eq(null_mut()) {
|
match (ptr).guaranteed_eq(null_mut()) {
|
||||||
None => false,
|
|
||||||
Some(res) => res,
|
Some(res) => res,
|
||||||
|
// To remain maximally convervative, we stop execution when we don't
|
||||||
|
// know whether the pointer is null or not.
|
||||||
|
// We can *not* return `false` here, that would be unsound in `NonNull::new`!
|
||||||
|
None => panic!("null-ness of this pointer cannot be determined in const context"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_unsafe)]
|
// Compare via a cast to a thin pointer, so fat pointers are only
|
||||||
|
// considering their "data" part for null-ness.
|
||||||
const_eval_select((self as *const u8,), const_impl, runtime_impl)
|
const_eval_select((self as *const u8,), const_impl, runtime_impl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,22 +33,7 @@ impl<T: ?Sized> *mut T {
|
|||||||
#[rustc_diagnostic_item = "ptr_is_null"]
|
#[rustc_diagnostic_item = "ptr_is_null"]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn is_null(self) -> bool {
|
pub const fn is_null(self) -> bool {
|
||||||
#[inline]
|
self.cast_const().is_null()
|
||||||
fn runtime_impl(ptr: *mut u8) -> bool {
|
|
||||||
ptr.addr() == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
const fn const_impl(ptr: *mut u8) -> bool {
|
|
||||||
// Compare via a cast to a thin pointer, so fat pointers are only
|
|
||||||
// considering their "data" part for null-ness.
|
|
||||||
match (ptr).guaranteed_eq(null_mut()) {
|
|
||||||
None => false,
|
|
||||||
Some(res) => res,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const_eval_select((self as *mut u8,), const_impl, runtime_impl)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Casts to a pointer of another type.
|
/// Casts to a pointer of another type.
|
||||||
|
|||||||
20
tests/ui/consts/const-ptr-is-null.rs
Normal file
20
tests/ui/consts/const-ptr-is-null.rs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#![feature(const_ptr_is_null)]
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
const IS_NULL: () = {
|
||||||
|
assert!(ptr::null::<u8>().is_null());
|
||||||
|
};
|
||||||
|
const IS_NOT_NULL: () = {
|
||||||
|
assert!(!ptr::null::<u8>().wrapping_add(1).is_null());
|
||||||
|
};
|
||||||
|
|
||||||
|
const MAYBE_NULL: () = {
|
||||||
|
let x = 15;
|
||||||
|
let ptr = &x as *const i32;
|
||||||
|
// This one is still unambiguous...
|
||||||
|
assert!(!ptr.is_null());
|
||||||
|
// but once we shift outside the allocation, we might become null.
|
||||||
|
assert!(!ptr.wrapping_sub(512).is_null()); //~inside `MAYBE_NULL`
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
19
tests/ui/consts/const-ptr-is-null.stderr
Normal file
19
tests/ui/consts/const-ptr-is-null.stderr
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
error[E0080]: evaluation of constant value failed
|
||||||
|
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||||
|
|
|
||||||
|
= 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
|
||||||
|
|
|
||||||
|
note: inside `std::ptr::const_ptr::<impl *const T>::is_null::const_impl`
|
||||||
|
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||||
|
note: inside `std::ptr::const_ptr::<impl *const i32>::is_null`
|
||||||
|
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||||
|
note: inside `MAYBE_NULL`
|
||||||
|
--> $DIR/const-ptr-is-null.rs:17:14
|
||||||
|
|
|
||||||
|
LL | assert!(!ptr.wrapping_sub(512).is_null());
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= 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)
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0080`.
|
||||||
Reference in New Issue
Block a user