about summary refs log tree commit diff
path: root/compiler/rustc_const_eval
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2024-09-26 16:48:32 +0200
committerRalf Jung <post@ralfj.de>2024-09-30 08:37:00 +0200
commit4b8a5bd511814ed97640c46ab2232acc0e0ade41 (patch)
treed364a1b02c32b5bc7a0b89b9ab92fd56bb8c52e7 /compiler/rustc_const_eval
parente9df22f51d2f0f062d0beb83a28c8c76883d2ceb (diff)
panic when an interpreter error gets unintentionally discarded
Diffstat (limited to 'compiler/rustc_const_eval')
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs19
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs38
-rw-r--r--compiler/rustc_const_eval/src/util/check_validity_requirement.rs4
3 files changed, 37 insertions, 24 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index 32f90254a94..05264d32c6b 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -13,9 +13,9 @@ use rustc_target::abi::{Abi, Align, HasDataLayout, Size};
 use tracing::{instrument, trace};
 
 use super::{
-    AllocRef, AllocRefMut, CheckAlignMsg, CtfeProvenance, ImmTy, Immediate, InterpCx, InterpResult,
-    Machine, MemoryKind, Misalignment, OffsetMode, OpTy, Operand, Pointer, Projectable, Provenance,
-    Scalar, alloc_range, mir_assign_valid_types,
+    AllocRef, AllocRefMut, CheckAlignMsg, CtfeProvenance, DiscardInterpError, ImmTy, Immediate,
+    InterpCx, InterpResult, Machine, MemoryKind, Misalignment, OffsetMode, OpTy, Operand, Pointer,
+    Projectable, Provenance, Scalar, alloc_range, mir_assign_valid_types,
 };
 
 #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
@@ -490,9 +490,16 @@ where
         // If an access is both OOB and misaligned, we want to see the bounds error.
         // However we have to call `check_misalign` first to make the borrow checker happy.
         let misalign_err = self.check_misalign(mplace.mplace.misaligned, CheckAlignMsg::BasedOn);
-        let a = self.get_ptr_alloc_mut(mplace.ptr(), size)?;
-        misalign_err?;
-        Ok(a)
+        match self.get_ptr_alloc_mut(mplace.ptr(), size) {
+            Ok(a) => {
+                misalign_err?;
+                Ok(a)
+            }
+            Err(e) => {
+                misalign_err.discard_interp_err();
+                Err(e)
+            }
+        }
     }
 
     /// Turn a local in the current frame into a place.
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 203cceccd9d..3c9fdd73100 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -17,8 +17,8 @@ use rustc_hir as hir;
 use rustc_middle::bug;
 use rustc_middle::mir::interpret::ValidationErrorKind::{self, *};
 use rustc_middle::mir::interpret::{
-    ExpectedKind, InterpError, InvalidMetaKind, Misalignment, PointerKind, Provenance,
-    UnsupportedOpInfo, ValidationErrorInfo, alloc_range,
+    ExpectedKind, InterpError, InterpErrorInfo, InvalidMetaKind, Misalignment, PointerKind,
+    Provenance, UnsupportedOpInfo, ValidationErrorInfo, alloc_range,
 };
 use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, Ty};
@@ -95,16 +95,19 @@ macro_rules! try_validation {
             Ok(x) => x,
             // We catch the error and turn it into a validation failure. We are okay with
             // allocation here as this can only slow down builds that fail anyway.
-            Err(e) => match e.kind() {
-                $(
-                    $($p)|+ =>
-                       throw_validation_failure!(
-                            $where,
-                            $kind
-                        )
-                ),+,
-                #[allow(unreachable_patterns)]
-                _ => Err::<!, _>(e)?,
+            Err(e) => {
+                let (kind, backtrace) = e.into_parts();
+                match kind {
+                    $(
+                        $($p)|+ => {
+                            throw_validation_failure!(
+                                $where,
+                                $kind
+                            )
+                        }
+                    ),+,
+                    _ => Err::<!, _>(InterpErrorInfo::from_parts(kind, backtrace))?,
+                }
             }
         }
     }};
@@ -510,7 +513,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
             Ub(DanglingIntPointer { addr: i, .. }) => DanglingPtrNoProvenance {
                 ptr_kind,
                 // FIXME this says "null pointer" when null but we need translate
-                pointer: format!("{}", Pointer::<Option<AllocId>>::from_addr_invalid(*i))
+                pointer: format!("{}", Pointer::<Option<AllocId>>::from_addr_invalid(i))
             },
             Ub(PointerOutOfBounds { .. }) => DanglingPtrOutOfBounds {
                 ptr_kind
@@ -1231,7 +1234,8 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
                     Err(err) => {
                         // For some errors we might be able to provide extra information.
                         // (This custom logic does not fit the `try_validation!` macro.)
-                        match err.kind() {
+                        let (kind, backtrace) = err.into_parts();
+                        match kind {
                             Ub(InvalidUninitBytes(Some((_alloc_id, access)))) | Unsup(ReadPointerAsInt(Some((_alloc_id, access)))) => {
                                 // Some byte was uninitialized, determine which
                                 // element that byte belongs to so we can
@@ -1242,7 +1246,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
                                 .unwrap();
                                 self.path.push(PathElem::ArrayElem(i));
 
-                                if matches!(err.kind(), Ub(InvalidUninitBytes(_))) {
+                                if matches!(kind, Ub(InvalidUninitBytes(_))) {
                                     throw_validation_failure!(self.path, Uninit { expected })
                                 } else {
                                     throw_validation_failure!(self.path, PointerAsInt { expected })
@@ -1250,7 +1254,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
                             }
 
                             // Propagate upwards (that will also check for unexpected errors).
-                            _ => return Err(err),
+                            _ => return Err(InterpErrorInfo::from_parts(kind, backtrace)),
                         }
                     }
                 }
@@ -1282,7 +1286,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
                     // It's not great to catch errors here, since we can't give a very good path,
                     // but it's better than ICEing.
                     Ub(InvalidVTableTrait { vtable_dyn_type, expected_dyn_type }) => {
-                        InvalidMetaWrongTrait { vtable_dyn_type, expected_dyn_type: *expected_dyn_type }
+                        InvalidMetaWrongTrait { vtable_dyn_type, expected_dyn_type }
                     },
                 );
             }
diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
index 19393188c9a..421648d9e7b 100644
--- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
+++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
@@ -1,4 +1,5 @@
 use rustc_middle::bug;
+use rustc_middle::mir::interpret::DiscardInterpError;
 use rustc_middle::ty::layout::{
     HasTyCtxt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement,
 };
@@ -75,7 +76,8 @@ fn check_validity_requirement_strict<'tcx>(
             /*recursive*/ false,
             /*reset_provenance_and_padding*/ false,
         )
-        .is_ok())
+        .discard_interp_err()
+        .is_some())
 }
 
 /// Implements the 'lax' (default) version of the [`check_validity_requirement`] checks; see that