about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-09-24 20:34:31 +0200
committerGitHub <noreply@github.com>2025-09-24 20:34:31 +0200
commitec378dc7732e7a2657539072cfd25c68f8802509 (patch)
treea0d193440aa5f0f1781db2028555338c0f7cf475 /compiler
parent24e19c908840551293a3fb4a9069e3d92b07eccb (diff)
parent8328c3dada0c888b1c570f97314b3f697d4b2a96 (diff)
downloadrust-ec378dc7732e7a2657539072cfd25c68f8802509.tar.gz
rust-ec378dc7732e7a2657539072cfd25c68f8802509.zip
Rollup merge of #146969 - RalfJung:maybe-null-errors, r=oli-obk
const-eval: better wording for errors involving maybe-null pointers

Fixes https://github.com/rust-lang/rust/issues/146748
r? ``@oli-obk``
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_const_eval/messages.ftl14
-rw-r--r--compiler/rustc_const_eval/src/errors.rs17
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs18
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs7
4 files changed, 33 insertions, 23 deletions
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index 700d7c26752..010ffa60c7a 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -476,14 +476,20 @@ const_eval_validation_invalid_vtable_trait = {$front_matter}: wrong trait in wid
 const_eval_validation_mutable_ref_in_const = {$front_matter}: encountered mutable reference in `const` value
 const_eval_validation_mutable_ref_to_immutable = {$front_matter}: encountered mutable reference or box pointing to read-only memory
 const_eval_validation_never_val = {$front_matter}: encountered a value of the never type `!`
-const_eval_validation_null_box = {$front_matter}: encountered a null box
+const_eval_validation_null_box = {$front_matter}: encountered a {$maybe ->
+    [true] maybe-null
+    *[false] null
+  } box
 const_eval_validation_null_fn_ptr = {$front_matter}: encountered a null function pointer
-const_eval_validation_null_ref = {$front_matter}: encountered a null reference
-const_eval_validation_nullable_ptr_out_of_range = {$front_matter}: encountered a potentially null pointer, but expected something that cannot possibly fail to be {$in_range}
+const_eval_validation_null_ref = {$front_matter}: encountered a {$maybe ->
+    [true] maybe-null
+    *[false] null
+  } reference
+const_eval_validation_nonnull_ptr_out_of_range = {$front_matter}: encountered a maybe-null pointer, but expected something that is definitely non-zero
 const_eval_validation_out_of_range = {$front_matter}: encountered {$value}, but expected something {$in_range}
 const_eval_validation_partial_pointer = {$front_matter}: encountered a partial pointer or a mix of pointers
 const_eval_validation_pointer_as_int = {$front_matter}: encountered a pointer, but {$expected}
-const_eval_validation_ptr_out_of_range = {$front_matter}: encountered a pointer, but expected something that cannot possibly fail to be {$in_range}
+const_eval_validation_ptr_out_of_range = {$front_matter}: encountered a pointer with unknown absolute address, but expected something that is definitely {$in_range}
 const_eval_validation_ref_to_uninhabited = {$front_matter}: encountered a reference pointing to uninhabited type {$ty}
 const_eval_validation_unaligned_box = {$front_matter}: encountered an unaligned box (required {$required_bytes} byte alignment but found {$found_bytes})
 const_eval_validation_unaligned_ref = {$front_matter}: encountered an unaligned reference (required {$required_bytes} byte alignment but found {$found_bytes})
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index 2d412ee5ec2..d352a638424 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -668,7 +668,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
             MutableRefInConst => const_eval_validation_mutable_ref_in_const,
             NullFnPtr => const_eval_validation_null_fn_ptr,
             NeverVal => const_eval_validation_never_val,
-            NullablePtrOutOfRange { .. } => const_eval_validation_nullable_ptr_out_of_range,
+            NonnullPtrMaybeNull { .. } => const_eval_validation_nonnull_ptr_out_of_range,
             PtrOutOfRange { .. } => const_eval_validation_ptr_out_of_range,
             OutOfRange { .. } => const_eval_validation_out_of_range,
             UnsafeCellInImmutable => const_eval_validation_unsafe_cell,
@@ -696,8 +696,8 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
             }
             UnalignedPtr { ptr_kind: PointerKind::Box, .. } => const_eval_validation_unaligned_box,
 
-            NullPtr { ptr_kind: PointerKind::Box } => const_eval_validation_null_box,
-            NullPtr { ptr_kind: PointerKind::Ref(_) } => const_eval_validation_null_ref,
+            NullPtr { ptr_kind: PointerKind::Box, .. } => const_eval_validation_null_box,
+            NullPtr { ptr_kind: PointerKind::Ref(_), .. } => const_eval_validation_null_ref,
             DanglingPtrNoProvenance { ptr_kind: PointerKind::Box, .. } => {
                 const_eval_validation_dangling_box_no_provenance
             }
@@ -804,9 +804,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
             | InvalidFnPtr { value } => {
                 err.arg("value", value);
             }
-            NullablePtrOutOfRange { range, max_value } | PtrOutOfRange { range, max_value } => {
-                add_range_arg(range, max_value, err)
-            }
+            PtrOutOfRange { range, max_value } => add_range_arg(range, max_value, err),
             OutOfRange { range, max_value, value } => {
                 err.arg("value", value);
                 add_range_arg(range, max_value, err);
@@ -822,10 +820,13 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
                 err.arg("vtable_dyn_type", vtable_dyn_type.to_string());
                 err.arg("expected_dyn_type", expected_dyn_type.to_string());
             }
-            NullPtr { .. }
-            | MutableRefToImmutable
+            NullPtr { maybe, .. } => {
+                err.arg("maybe", maybe);
+            }
+            MutableRefToImmutable
             | MutableRefInConst
             | NullFnPtr
+            | NonnullPtrMaybeNull
             | NeverVal
             | UnsafeCellInImmutable
             | InvalidMetaSliceTooLarge { .. }
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 9adc3fa4631..5f088fe37e8 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -511,7 +511,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
                 CheckInAllocMsg::Dereferenceable, // will anyway be replaced by validity message
             ),
             self.path,
-            Ub(DanglingIntPointer { addr: 0, .. }) => NullPtr { ptr_kind },
+            Ub(DanglingIntPointer { addr: 0, .. }) => NullPtr { ptr_kind, maybe: false },
             Ub(DanglingIntPointer { addr: i, .. }) => DanglingPtrNoProvenance {
                 ptr_kind,
                 // FIXME this says "null pointer" when null but we need translate
@@ -538,8 +538,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
         );
         // Make sure this is non-null. We checked dereferenceability above, but if `size` is zero
         // that does not imply non-null.
-        if self.ecx.scalar_may_be_null(Scalar::from_maybe_pointer(place.ptr(), self.ecx))? {
-            throw_validation_failure!(self.path, NullPtr { ptr_kind })
+        let scalar = Scalar::from_maybe_pointer(place.ptr(), self.ecx);
+        if self.ecx.scalar_may_be_null(scalar)? {
+            let maybe = !M::Provenance::OFFSET_IS_ADDR && matches!(scalar, Scalar::Ptr(..));
+            throw_validation_failure!(self.path, NullPtr { ptr_kind, maybe })
         }
         // Do not allow references to uninhabited types.
         if place.layout.is_uninhabited() {
@@ -757,6 +759,11 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
                 } else {
                     // Otherwise (for standalone Miri), we have to still check it to be non-null.
                     if self.ecx.scalar_may_be_null(scalar)? {
+                        let maybe =
+                            !M::Provenance::OFFSET_IS_ADDR && matches!(scalar, Scalar::Ptr(..));
+                        // This can't be a "maybe-null" pointer since the check for this being
+                        // a fn ptr at all already ensures that the pointer is inbounds.
+                        assert!(!maybe);
                         throw_validation_failure!(self.path, NullFnPtr);
                     }
                 }
@@ -819,10 +826,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
                 if start == 1 && end == max_value {
                     // Only null is the niche. So make sure the ptr is NOT null.
                     if self.ecx.scalar_may_be_null(scalar)? {
-                        throw_validation_failure!(
-                            self.path,
-                            NullablePtrOutOfRange { range: valid_range, max_value }
-                        )
+                        throw_validation_failure!(self.path, NonnullPtrMaybeNull)
                     } else {
                         return interp_ok(());
                     }
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 7c72a8ec243..951aac503fe 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -499,10 +499,7 @@ pub enum ValidationErrorKind<'tcx> {
     MutableRefInConst,
     NullFnPtr,
     NeverVal,
-    NullablePtrOutOfRange {
-        range: WrappingRange,
-        max_value: u128,
-    },
+    NonnullPtrMaybeNull,
     PtrOutOfRange {
         range: WrappingRange,
         max_value: u128,
@@ -544,6 +541,8 @@ pub enum ValidationErrorKind<'tcx> {
     },
     NullPtr {
         ptr_kind: PointerKind,
+        /// Records whether this pointer is definitely null or just may be null.
+        maybe: bool,
     },
     DanglingPtrNoProvenance {
         ptr_kind: PointerKind,