about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2024-12-02 23:08:55 +0100
committerGitHub <noreply@github.com>2024-12-02 23:08:55 +0100
commitb1a643e599b68e568fe90790dfbe4acd3baa573d (patch)
tree7f50bca4902aac3738367fdc8b8e5d73b5d30dfc /compiler
parent65b0dad824afa54eb23aa9e3c333daaf9037249d (diff)
parenta17294dc0fe106f0a8f12f8bc61ab17eacf251ef (diff)
downloadrust-b1a643e599b68e568fe90790dfbe4acd3baa573d.tar.gz
rust-b1a643e599b68e568fe90790dfbe4acd3baa573d.zip
Rollup merge of #133704 - RalfJung:promoted-size-overflow-ice, r=compiler-errors
fix ICE when promoted has layout size overflow

Turns out there is no reason to distinguish `tainted_by_errors` and `can_be_spurious` here, we can just track whether we allow this even in "infallible" constants.

Fixes https://github.com/rust-lang/rust/issues/125476
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs17
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs11
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs26
3 files changed, 25 insertions, 29 deletions
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index 1271d9d2d0d..3cb77d1dcb5 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -139,12 +139,14 @@ where
     match error {
         // Don't emit a new diagnostic for these errors, they are already reported elsewhere or
         // should remain silent.
+        err_inval!(AlreadyReported(info)) => ErrorHandled::Reported(info, span),
         err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
             ErrorHandled::TooGeneric(span)
         }
-        err_inval!(AlreadyReported(guar)) => ErrorHandled::Reported(guar, span),
         err_inval!(Layout(LayoutError::ReferencesError(guar))) => {
-            ErrorHandled::Reported(ReportedErrorInfo::tainted_by_errors(guar), span)
+            // This can occur in infallible promoteds e.g. when a non-existent type or field is
+            // encountered.
+            ErrorHandled::Reported(ReportedErrorInfo::allowed_in_infallible(guar), span)
         }
         // Report remaining errors.
         _ => {
@@ -152,7 +154,12 @@ where
             let span = span.substitute_dummy(our_span);
             let err = mk(span, frames);
             let mut err = tcx.dcx().create_err(err);
-            let can_be_spurious = matches!(error, InterpErrorKind::ResourceExhaustion(_));
+            // We allow invalid programs in infallible promoteds since invalid layouts can occur
+            // anyway (e.g. due to size overflow). And we allow OOM as that can happen any time.
+            let allowed_in_infallible = matches!(
+                error,
+                InterpErrorKind::ResourceExhaustion(_) | InterpErrorKind::InvalidProgram(_)
+            );
 
             let msg = error.diagnostic_message();
             error.add_args(&mut err);
@@ -160,8 +167,8 @@ where
             // Use *our* span to label the interp error
             err.span_label(our_span, msg);
             let g = err.emit();
-            let reported = if can_be_spurious {
-                ReportedErrorInfo::spurious(g)
+            let reported = if allowed_in_infallible {
+                ReportedErrorInfo::allowed_in_infallible(g)
             } else {
                 ReportedErrorInfo::from(g)
             };
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index fe93a48c2f2..241be5e175c 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -268,7 +268,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         };
         // do not continue if typeck errors occurred (can only occur in local crate)
         if let Some(err) = body.tainted_by_errors {
-            throw_inval!(AlreadyReported(ReportedErrorInfo::tainted_by_errors(err)));
+            throw_inval!(AlreadyReported(ReportedErrorInfo::from(err)));
         }
         interp_ok(body)
     }
@@ -585,13 +585,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                     match err {
                         ErrorHandled::TooGeneric(..) => {},
                         ErrorHandled::Reported(reported, span) => {
-                            if reported.is_tainted_by_errors() {
-                                // const-eval will return "tainted" errors if e.g. the layout cannot
-                                // be computed as the type references non-existing names.
-                                // See <https://github.com/rust-lang/rust/issues/124348>.
-                            } else if reported.can_be_spurious() {
+                            if reported.is_allowed_in_infallible() {
                                 // These errors can just sometimes happen, even when the expression
-                                // is nominally "infallible", e.g. when running out of memory.
+                                // is nominally "infallible", e.g. when running out of memory
+                                // or when some layout could not be computed.
                             } else {
                                 // Looks like the const is not captured by `required_consts`, that's bad.
                                 span_bug!(span, "interpret const eval failure of {val:?} which is not in required_consts");
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 08afa33c6b4..ad5d678178d 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -46,7 +46,7 @@ impl ErrorHandled {
     pub fn emit_note(&self, tcx: TyCtxt<'_>) {
         match self {
             &ErrorHandled::Reported(err, span) => {
-                if !err.is_tainted_by_errors && !span.is_dummy() {
+                if !err.allowed_in_infallible && !span.is_dummy() {
                     tcx.dcx().emit_note(error::ErroneousConstant { span });
                 }
             }
@@ -58,34 +58,26 @@ impl ErrorHandled {
 #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
 pub struct ReportedErrorInfo {
     error: ErrorGuaranteed,
-    is_tainted_by_errors: bool,
-    /// Whether this is the kind of error that can sometimes occur, and sometimes not.
-    /// Used for resource exhaustion errors.
-    can_be_spurious: bool,
+    /// Whether this error is allowed to show up even in otherwise "infallible" promoteds.
+    /// This is for things like overflows during size computation or resource exhaustion.
+    allowed_in_infallible: bool,
 }
 
 impl ReportedErrorInfo {
     #[inline]
-    pub fn tainted_by_errors(error: ErrorGuaranteed) -> ReportedErrorInfo {
-        ReportedErrorInfo { is_tainted_by_errors: true, can_be_spurious: false, error }
-    }
-    #[inline]
-    pub fn spurious(error: ErrorGuaranteed) -> ReportedErrorInfo {
-        ReportedErrorInfo { can_be_spurious: true, is_tainted_by_errors: false, error }
+    pub fn allowed_in_infallible(error: ErrorGuaranteed) -> ReportedErrorInfo {
+        ReportedErrorInfo { allowed_in_infallible: true, error }
     }
 
-    pub fn is_tainted_by_errors(&self) -> bool {
-        self.is_tainted_by_errors
-    }
-    pub fn can_be_spurious(&self) -> bool {
-        self.can_be_spurious
+    pub fn is_allowed_in_infallible(&self) -> bool {
+        self.allowed_in_infallible
     }
 }
 
 impl From<ErrorGuaranteed> for ReportedErrorInfo {
     #[inline]
     fn from(error: ErrorGuaranteed) -> ReportedErrorInfo {
-        ReportedErrorInfo { is_tainted_by_errors: false, can_be_spurious: false, error }
+        ReportedErrorInfo { allowed_in_infallible: false, error }
     }
 }