diff options
| author | Ralf Jung <post@ralfj.de> | 2024-09-08 18:59:30 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2024-09-08 19:07:46 +0200 |
| commit | 11d51aae863d46a73ad39ec607bd7592fdb836e3 (patch) | |
| tree | c42390e46d97b7e37edb5e235af98075a19a7a33 | |
| parent | 7b18b3eb6d45efe45ecbe0b6043a1a93cef4a166 (diff) | |
| download | rust-11d51aae863d46a73ad39ec607bd7592fdb836e3.tar.gz rust-11d51aae863d46a73ad39ec607bd7592fdb836e3.zip | |
const: make ptr.is_null() stop execution on ambiguity
| -rw-r--r-- | library/core/src/ptr/const_ptr.rs | 10 | ||||
| -rw-r--r-- | library/core/src/ptr/mut_ptr.rs | 17 | ||||
| -rw-r--r-- | tests/ui/consts/const-ptr-is-null.rs | 20 | ||||
| -rw-r--r-- | tests/ui/consts/const-ptr-is-null.stderr | 19 |
4 files changed, 46 insertions, 20 deletions
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 3b635e2a4aa..febb3fed963 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -40,15 +40,17 @@ impl<T: ?Sized> *const T { #[inline] 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()) { - None => false, 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) } diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 42975cc927b..bebc4b2f271 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -33,22 +33,7 @@ impl<T: ?Sized> *mut T { #[rustc_diagnostic_item = "ptr_is_null"] #[inline] pub const fn is_null(self) -> bool { - #[inline] - 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) + self.cast_const().is_null() } /// Casts to a pointer of another type. diff --git a/tests/ui/consts/const-ptr-is-null.rs b/tests/ui/consts/const-ptr-is-null.rs new file mode 100644 index 00000000000..82c293c0ad6 --- /dev/null +++ b/tests/ui/consts/const-ptr-is-null.rs @@ -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() {} diff --git a/tests/ui/consts/const-ptr-is-null.stderr b/tests/ui/consts/const-ptr-is-null.stderr new file mode 100644 index 00000000000..20e44a1401f --- /dev/null +++ b/tests/ui/consts/const-ptr-is-null.stderr @@ -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`. |
