stabilize const_ptr_is_null

This commit is contained in:
Ralf Jung 2024-11-16 18:32:25 +01:00
parent 46e8d20301
commit 5eef5ee38a
9 changed files with 18 additions and 13 deletions

View File

@ -263,6 +263,12 @@ impl<'tcx> CompileTimeInterpCx<'tcx> {
} }
/// See documentation on the `ptr_guaranteed_cmp` intrinsic. /// See documentation on the `ptr_guaranteed_cmp` intrinsic.
/// Returns `2` if the result is unknown.
/// Returns `1` if the pointers are guaranteed equal.
/// Returns `0` if the pointers are guaranteed inequal.
///
/// Note that this intrinsic is exposed on stable for comparison with null. In other words, any
/// change to this function that affects comparison with null is insta-stable!
fn guaranteed_cmp(&mut self, a: Scalar, b: Scalar) -> InterpResult<'tcx, u8> { fn guaranteed_cmp(&mut self, a: Scalar, b: Scalar) -> InterpResult<'tcx, u8> {
interp_ok(match (a, b) { interp_ok(match (a, b) {
// Comparisons between integers are always known. // Comparisons between integers are always known.

View File

@ -3292,8 +3292,8 @@ pub const unsafe fn ptr_offset_from_unsigned<T>(_ptr: *const T, _base: *const T)
/// See documentation of `<*const T>::guaranteed_eq` for details. /// See documentation of `<*const T>::guaranteed_eq` for details.
/// Returns `2` if the result is unknown. /// Returns `2` if the result is unknown.
/// Returns `1` if the pointers are guaranteed equal /// Returns `1` if the pointers are guaranteed equal.
/// Returns `0` if the pointers are guaranteed inequal /// Returns `0` if the pointers are guaranteed inequal.
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020"))] #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020"))]
#[rustc_intrinsic] #[rustc_intrinsic]
#[rustc_nounwind] #[rustc_nounwind]

View File

@ -121,7 +121,6 @@
#![feature(const_heap)] #![feature(const_heap)]
#![feature(const_nonnull_new)] #![feature(const_nonnull_new)]
#![feature(const_pin_2)] #![feature(const_pin_2)]
#![feature(const_ptr_is_null)]
#![feature(const_ptr_sub_ptr)] #![feature(const_ptr_sub_ptr)]
#![feature(const_raw_ptr_comparison)] #![feature(const_raw_ptr_comparison)]
#![feature(const_size_of_val)] #![feature(const_size_of_val)]

View File

@ -29,16 +29,18 @@ impl<T: ?Sized> *const T {
/// assert!(!ptr.is_null()); /// assert!(!ptr.is_null());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")]
#[rustc_diagnostic_item = "ptr_const_is_null"] #[rustc_diagnostic_item = "ptr_const_is_null"]
#[inline] #[inline]
#[rustc_allow_const_fn_unstable(const_eval_select)]
pub const fn is_null(self) -> bool { pub const fn is_null(self) -> bool {
// Compare via a cast to a thin pointer, so fat pointers are only // Compare via a cast to a thin pointer, so fat pointers are only
// considering their "data" part for null-ness. // considering their "data" part for null-ness.
let ptr = self as *const u8; let ptr = self as *const u8;
const_eval_select!( const_eval_select!(
@capture { ptr: *const u8 } -> bool: @capture { ptr: *const u8 } -> bool:
if const #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] { // This use of `const_raw_ptr_comparison` has been explicitly blessed by t-lang.
if const #[rustc_allow_const_fn_unstable(const_raw_ptr_comparison)] {
match (ptr).guaranteed_eq(null_mut()) { match (ptr).guaranteed_eq(null_mut()) {
Some(res) => res, Some(res) => res,
// To remain maximally convervative, we stop execution when we don't // To remain maximally convervative, we stop execution when we don't
@ -280,7 +282,7 @@ impl<T: ?Sized> *const T {
/// } /// }
/// ``` /// ```
#[stable(feature = "ptr_as_ref", since = "1.9.0")] #[stable(feature = "ptr_as_ref", since = "1.9.0")]
#[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")]
#[inline] #[inline]
pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> { pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> {
// SAFETY: the caller must guarantee that `self` is valid // SAFETY: the caller must guarantee that `self` is valid

View File

@ -29,7 +29,7 @@ impl<T: ?Sized> *mut T {
/// assert!(!ptr.is_null()); /// assert!(!ptr.is_null());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")]
#[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 {
@ -271,7 +271,7 @@ impl<T: ?Sized> *mut T {
/// } /// }
/// ``` /// ```
#[stable(feature = "ptr_as_ref", since = "1.9.0")] #[stable(feature = "ptr_as_ref", since = "1.9.0")]
#[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")]
#[inline] #[inline]
pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> { pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> {
// SAFETY: the caller must guarantee that `self` is valid for a // SAFETY: the caller must guarantee that `self` is valid for a
@ -619,7 +619,7 @@ impl<T: ?Sized> *mut T {
/// println!("{s:?}"); // It'll print: "[4, 2, 3]". /// println!("{s:?}"); // It'll print: "[4, 2, 3]".
/// ``` /// ```
#[stable(feature = "ptr_as_ref", since = "1.9.0")] #[stable(feature = "ptr_as_ref", since = "1.9.0")]
#[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")]
#[inline] #[inline]
pub const unsafe fn as_mut<'a>(self) -> Option<&'a mut T> { pub const unsafe fn as_mut<'a>(self) -> Option<&'a mut T> {
// SAFETY: the caller must guarantee that `self` is be valid for // SAFETY: the caller must guarantee that `self` is be valid for

View File

@ -65,7 +65,7 @@ macro_rules! assert_unsafe_precondition {
#[inline] #[inline]
#[rustc_nounwind] #[rustc_nounwind]
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_ub_checks", issue = "none"))] #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_ub_checks", issue = "none"))]
#[rustc_allow_const_fn_unstable(const_ptr_is_null, const_ub_checks)] // only for UB checks #[rustc_allow_const_fn_unstable(const_ub_checks)] // only for UB checks
const fn precondition_check($($name:$ty),*) { const fn precondition_check($($name:$ty),*) {
if !$e { if !$e {
::core::panicking::panic_nounwind( ::core::panicking::panic_nounwind(

View File

@ -1,4 +1,3 @@
#![feature(const_ptr_is_null)]
use std::ptr; use std::ptr;
const IS_NULL: () = { const IS_NULL: () = {

View File

@ -8,7 +8,7 @@ note: inside `std::ptr::const_ptr::<impl *const T>::is_null::compiletime`
note: inside `std::ptr::const_ptr::<impl *const i32>::is_null` note: inside `std::ptr::const_ptr::<impl *const i32>::is_null`
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
note: inside `MAYBE_NULL` note: inside `MAYBE_NULL`
--> $DIR/const-ptr-is-null.rs:17:14 --> $DIR/const-ptr-is-null.rs:16:14
| |
LL | assert!(!ptr.wrapping_sub(512).is_null()); LL | assert!(!ptr.wrapping_sub(512).is_null());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -1,7 +1,6 @@
//@ compile-flags: --crate-type=lib //@ compile-flags: --crate-type=lib
//@ check-pass //@ check-pass
#![feature(const_ptr_is_null)]
#![allow(useless_ptr_null_checks)] #![allow(useless_ptr_null_checks)]
const FOO: &usize = &42; const FOO: &usize = &42;