From 54b751d55a2e2748171c0ba761ae9006552cbe88 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 17 Aug 2026 17:15:59 +0200 Subject: [PATCH 1/4] Remove emit_almost_fatal A fatal error that doesn't actually abort is indistinguishable from a regular error. And the only places where emit_almost_fatal is called, the produced FatalError is ignored. --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 10 ++--- compiler/rustc_errors/src/diagnostic.rs | 7 --- compiler/rustc_errors/src/lib.rs | 46 +++++++------------- 3 files changed, 20 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 1844a8e5c0bca..743145a0e5baf 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -231,11 +231,11 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { } sym::offload => { if tcx.sess.opts.unstable_opts.offload.is_empty() { - let _ = tcx.dcx().emit_almost_fatal(OffloadWithoutEnable); + let _ = tcx.dcx().emit_err(OffloadWithoutEnable); } if tcx.sess.lto() != rustc_session::config::Lto::Fat { - let _ = tcx.dcx().emit_almost_fatal(OffloadWithoutFatLTO); + let _ = tcx.dcx().emit_err(OffloadWithoutFatLTO); } codegen_offload(self, tcx, instance, args); @@ -1752,18 +1752,18 @@ fn codegen_autodiff<'ll, 'tcx>( ) -> IntrinsicResult<'tcx, &'ll Value> { let tcx = bx.tcx; if !tcx.sess.opts.unstable_opts.autodiff.contains(&rustc_session::config::AutoDiff::Enable) { - let _ = tcx.dcx().emit_almost_fatal(AutoDiffWithoutEnable); + let _ = tcx.dcx().emit_err(AutoDiffWithoutEnable); } let ct = tcx.crate_types(); let lto = tcx.sess.lto(); if ct.len() == 1 && ct.contains(&CrateType::Executable) { if lto != rustc_session::config::Lto::Fat { - let _ = tcx.dcx().emit_almost_fatal(AutoDiffWithoutLto); + let _ = tcx.dcx().emit_err(AutoDiffWithoutLto); } } else { if lto != rustc_session::config::Lto::Fat && !tcx.sess.opts.cg.linker_plugin_lto.enabled() { - let _ = tcx.dcx().emit_almost_fatal(AutoDiffWithoutLto); + let _ = tcx.dcx().emit_err(AutoDiffWithoutLto); } } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index d1dc3ab6e9525..caba9e55edcc3 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -73,13 +73,6 @@ impl EmissionGuarantee for FatalAbort { } } -impl EmissionGuarantee for rustc_span::fatal_error::FatalError { - fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult { - diag.emit_producing_nothing(); - rustc_span::fatal_error::FatalError - } -} - /// Trait implemented by error types. This is rarely implemented manually. Instead, use /// `#[derive(Diagnostic)]` -- see [rustc_macros::Diagnostic]. /// diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index f868b11ea6fd2..146eef4096f17 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1026,19 +1026,6 @@ impl<'a> DiagCtxtHandle<'a> { self.create_fatal(fatal).emit() } - #[track_caller] - pub fn create_almost_fatal( - self, - fatal: impl Diagnostic<'a, FatalError>, - ) -> Diag<'a, FatalError> { - fatal.into_diag(self, Fatal) - } - - #[track_caller] - pub fn emit_almost_fatal(self, fatal: impl Diagnostic<'a, FatalError>) -> FatalError { - self.create_almost_fatal(fatal).emit() - } - // FIXME: This method should be removed (every error should have an associated error code). #[track_caller] pub fn struct_err(self, msg: impl Into) -> Diag<'a> { @@ -1582,24 +1569,21 @@ impl DelayedDiagInner { } } -/// | Level | is_error | EmissionGuarantee | Top-level | Sub | Used in lints? -/// | ----- | -------- | ----------------- | --------- | --- | -------------- -/// | Bug | yes | BugAbort | yes | - | - -/// | Fatal | yes | FatalAbort/FatalError[^star] | yes | - | - -/// | Error | yes | ErrorGuaranteed | yes | - | yes -/// | DelayedBug | yes | ErrorGuaranteed | yes | - | - -/// | ForceWarning | - | () | yes | - | lint-only -/// | Warning | - | () | yes | yes | yes -/// | Note | - | () | rare | yes | - -/// | OnceNote | - | () | - | yes | lint-only -/// | Help | - | () | rare | yes | - -/// | OnceHelp | - | () | - | yes | lint-only -/// | FailureNote | - | () | rare | - | - -/// | Allow | - | () | yes | - | lint-only -/// | Expect | - | () | yes | - | lint-only -/// -/// [^star]: `FatalAbort` normally, `FatalError` in the non-aborting "almost fatal" case that is -/// occasionally used. +/// | Level | is_error | EmissionGuarantee | Top-level | Sub | Used in lints? +/// | ----- | -------- | ----------------- | --------- | --- | -------------- +/// | Bug | yes | BugAbort | yes | - | - +/// | Fatal | yes | FatalAbort | yes | - | - +/// | Error | yes | ErrorGuaranteed | yes | - | yes +/// | DelayedBug | yes | ErrorGuaranteed | yes | - | - +/// | ForceWarning | - | () | yes | - | lint-only +/// | Warning | - | () | yes | yes | yes +/// | Note | - | () | rare | yes | - +/// | OnceNote | - | () | - | yes | lint-only +/// | Help | - | () | rare | yes | - +/// | OnceHelp | - | () | - | yes | lint-only +/// | FailureNote | - | () | rare | - | - +/// | Allow | - | () | yes | - | lint-only +/// | Expect | - | () | yes | - | lint-only /// #[derive(Copy, PartialEq, Eq, Clone, Hash, Debug, Encodable, Decodable)] pub enum Level { From 8b71848ed47f0f4f9e041bff45e4ca0aeb11c4a5 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 17 Aug 2026 17:47:40 +0200 Subject: [PATCH 2/4] Avoid fatal errors in raw-dylib handling --- compiler/rustc_metadata/src/native_libs.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 87e0902b1f7f8..eff464bcfc526 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -274,7 +274,8 @@ impl<'tcx> Collector<'tcx> { DllCallingConvention::Vectorcall(self.i686_arg_list_size(item)) } _ => { - self.tcx.dcx().emit_fatal(diagnostics::RawDylibUnsupportedAbi { span }); + self.tcx.dcx().emit_err(diagnostics::RawDylibUnsupportedAbi { span }); + return None; } } } else { @@ -283,7 +284,8 @@ impl<'tcx> Collector<'tcx> { DllCallingConvention::C } _ => { - self.tcx.dcx().emit_fatal(diagnostics::RawDylibUnsupportedAbi { span }); + self.tcx.dcx().emit_err(diagnostics::RawDylibUnsupportedAbi { span }); + return None; } } }; From 052ee70292daaccd4fa5b383a4784ee730f9cc6e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 31 Aug 2026 12:56:40 +0200 Subject: [PATCH 3/4] Don't rely on codegen emitting fn_abi_of_* errors in abi checks This avoids a delayed bug if compilation is aborted between checking function ABIs and codegening all functions. --- .../rustc_codegen_cranelift/src/common.rs | 21 ++------ compiler/rustc_codegen_gcc/src/context.rs | 23 ++------ compiler/rustc_codegen_llvm/src/context.rs | 22 ++------ compiler/rustc_middle/src/ty/layout.rs | 26 ++++++++- .../src/mono_checks/abi_check.rs | 53 ++++++++++++++----- tests/crashes/152204.rs | 9 ---- tests/ui/abi/no_delayed_bug.rs | 15 ++++++ tests/ui/abi/no_delayed_bug.stderr | 11 ++++ tests/ui/limits/issue-17913.32bit.stderr | 5 +- tests/ui/limits/issue-17913.64bit.stderr | 5 +- tests/ui/limits/issue-17913.rs | 1 + 11 files changed, 111 insertions(+), 80 deletions(-) delete mode 100644 tests/crashes/152204.rs create mode 100644 tests/ui/abi/no_delayed_bug.rs create mode 100644 tests/ui/abi/no_delayed_bug.stderr diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 1bdb3efefa1aa..d31c8fc810b2c 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -5,8 +5,9 @@ use rustc_index::IndexVec; use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::layout::{ self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, + codegen_handle_fn_abi_err, }; -use rustc_span::{Spanned, Symbol}; +use rustc_span::Symbol; use rustc_target::callconv::FnAbi; use rustc_target::spec::{Arch, HasTargetSpec, Target}; @@ -453,23 +454,7 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for FullyMonomorphizedLayoutCx<'tcx> { span: Span, fn_abi_request: FnAbiRequest<'tcx>, ) -> ! { - if let FnAbiError::Layout(LayoutError::SizeOverflow(_) | LayoutError::InvalidSimd { .. }) = - err - { - self.0.sess.dcx().emit_fatal(Spanned { span, node: err }) - } else { - match fn_abi_request { - FnAbiRequest::OfFnPtr { sig, extra_args } => { - span_bug!(span, "`fn_abi_of_fn_ptr({sig}, {extra_args:?})` failed: {err:?}"); - } - FnAbiRequest::OfInstance { instance, extra_args } => { - span_bug!( - span, - "`fn_abi_of_instance({instance}, {extra_args:?})` failed: {err:?}" - ); - } - } - } + codegen_handle_fn_abi_err(self.0, err, span, fn_abi_request).raise_fatal() } } diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 19fbe37c27b9e..64f9982ac7de6 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -10,16 +10,15 @@ use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, ToBaseN}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir::interpret::Allocation; use rustc_middle::mono::CodegenUnit; -use rustc_middle::span_bug; use rustc_middle::ty::layout::{ FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, - LayoutOfHelpers, + LayoutOfHelpers, codegen_handle_fn_abi_err, }; use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt}; #[cfg(feature = "master")] use rustc_session::config::DebugInfo; use rustc_session::{PointerAuthSchema, Session}; -use rustc_span::{DUMMY_SP, Span, Symbol, respan}; +use rustc_span::{DUMMY_SP, Span, Symbol}; use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, TlsModel, X86Abi}; #[cfg(feature = "master")] @@ -562,23 +561,7 @@ impl<'gcc, 'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { span: Span, fn_abi_request: FnAbiRequest<'tcx>, ) -> ! { - if let FnAbiError::Layout(LayoutError::SizeOverflow(_) | LayoutError::InvalidSimd { .. }) = - err - { - self.tcx.dcx().emit_fatal(respan(span, err)) - } else { - match fn_abi_request { - FnAbiRequest::OfFnPtr { sig, extra_args } => { - span_bug!(span, "`fn_abi_of_fn_ptr({sig}, {extra_args:?})` failed: {err:?}"); - } - FnAbiRequest::OfInstance { instance, extra_args } => { - span_bug!( - span, - "`fn_abi_of_instance({instance}, {extra_args:?})` failed: {err:?}" - ); - } - } - } + codegen_handle_fn_abi_err(self.tcx, err, span, fn_abi_request).raise_fatal() } } diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 9e127edbd2ff9..3b58a7f00146b 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -14,18 +14,19 @@ use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, ToBaseN}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; +use rustc_middle::bug; use rustc_middle::mono::CodegenUnit; use rustc_middle::ty::layout::{ FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTypingEnv, LayoutError, LayoutOfHelpers, + codegen_handle_fn_abi_err, }; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; -use rustc_middle::{bug, span_bug}; use rustc_sanitizers::ignorelist::{SanitizerIgnoreList, typename_for_ignore_list}; use rustc_session::config::{ BranchProtection, CFGuard, CFProtection, DebugInfo, FunctionReturn, PAuthKey, PacRet, }; use rustc_session::{PointerAuthSchema, Session}; -use rustc_span::{DUMMY_SP, Span, Spanned, Symbol, sym}; +use rustc_span::{DUMMY_SP, Span, Symbol, sym}; use rustc_structures::CrateType; use rustc_target::spec::{ Arch, CfgAbi, Env, FramePointer, HasTargetSpec, Os, RelocModel, SmallDataThresholdSupport, @@ -1316,21 +1317,6 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'_, 'tcx> { span: Span, fn_abi_request: FnAbiRequest<'tcx>, ) -> ! { - match err { - FnAbiError::Layout(LayoutError::SizeOverflow(_) | LayoutError::InvalidSimd { .. }) => { - self.tcx.dcx().emit_fatal(Spanned { span, node: err }); - } - _ => match fn_abi_request { - FnAbiRequest::OfFnPtr { sig, extra_args } => { - span_bug!(span, "`fn_abi_of_fn_ptr({sig}, {extra_args:?})` failed: {err:?}",); - } - FnAbiRequest::OfInstance { instance, extra_args } => { - span_bug!( - span, - "`fn_abi_of_instance({instance}, {extra_args:?})` failed: {err:?}", - ); - } - }, - } + codegen_handle_fn_abi_err(self.tcx, err, span, fn_abi_request).raise_fatal() } } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index c18bf81121377..85e1df8b057a0 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -14,7 +14,7 @@ use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_macros::{StableHash, TyDecodable, TyEncodable, extension}; use rustc_session::config::OptLevel; -use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym}; +use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Spanned, Symbol, sym}; use rustc_structures::Limit; use rustc_target::callconv::FnAbi; use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, X86Abi}; @@ -1374,6 +1374,8 @@ pub trait FnAbiOfHelpers<'tcx>: LayoutOfHelpers<'tcx> { /// but this hook allows e.g. codegen to return only `&FnAbi` from its /// `cx.fn_abi_of_*(...)`, without any `Result<...>` around it to deal with /// (and any `FnAbiError`s are turned into fatal errors or ICEs). + /// + /// Codegen backends should use [`codegen_handle_fn_abi_err`] as implementation. fn handle_fn_abi_err( &self, err: FnAbiError<'tcx>, @@ -1382,6 +1384,28 @@ pub trait FnAbiOfHelpers<'tcx>: LayoutOfHelpers<'tcx> { ) -> >>>::Error; } +/// Implementation of [`FnAbiOfHelpers::handle_fn_abi_err`] for codegen backends. +pub fn codegen_handle_fn_abi_err<'tcx>( + tcx: TyCtxt<'tcx>, + err: FnAbiError<'tcx>, + span: Span, + fn_abi_request: FnAbiRequest<'tcx>, +) -> ErrorGuaranteed { + match err { + FnAbiError::Layout(LayoutError::SizeOverflow(_) | LayoutError::InvalidSimd { .. }) => { + tcx.dcx().emit_err(Spanned { span, node: err }) + } + _ => match fn_abi_request { + FnAbiRequest::OfFnPtr { sig, extra_args } => { + span_bug!(span, "`fn_abi_of_fn_ptr({sig}, {extra_args:?})` failed: {err:?}",); + } + FnAbiRequest::OfInstance { instance, extra_args } => { + span_bug!(span, "`fn_abi_of_instance({instance}, {extra_args:?})` failed: {err:?}",); + } + }, + } +} + /// Blanket extension trait for contexts that can compute `FnAbi`s. pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> { /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs index 885ad6071d91c..1ba48e6829070 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs @@ -3,6 +3,7 @@ use rustc_abi::{BackendRepr, CanonAbi, ExternAbi, RegKind, X86Call}; use rustc_hir::{CRATE_HIR_ID, HirId}; use rustc_middle::mir::{self, Location, traversal}; +use rustc_middle::ty::layout::{FnAbiRequest, codegen_handle_fn_abi_err}; use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt}; use rustc_span::def_id::DefId; use rustc_span::{DUMMY_SP, Span, Symbol, sym}; @@ -173,12 +174,19 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { // LLVM intrinsics return; } - let Ok(abi) = tcx.fn_abi_of_instance(typing_env.as_query_input((instance, ty::List::empty()))) - else { - // An error will be reported during codegen if we cannot determine the ABI of this - // function. - tcx.dcx().delayed_bug("ABI computation failure should lead to compilation failure"); - return; + let abi = match tcx.fn_abi_of_instance(typing_env.as_query_input((instance, ty::List::empty()))) + { + Ok(abi) => abi, + Err(err) => { + codegen_handle_fn_abi_err( + tcx, + *err, + tcx.def_span(instance.def_id()), + FnAbiRequest::OfInstance { instance, extra_args: ty::List::empty() }, + ); + // ABI failed to compute; this will not get through codegen. + return; + } }; // Unlike the call-site check, we do also check "Rust" ABI functions here. This can actually // trigger due to scalable vectors being require for the "Rust" ABI for some types. @@ -214,7 +222,20 @@ fn check_call_site_abi<'tcx>( let typing_env = ty::TypingEnv::fully_monomorphized(); let callee_abi = match *callee.kind() { ty::FnPtr(..) => { - tcx.fn_abi_of_fn_ptr(typing_env.as_query_input((callee.fn_sig(tcx), ty::List::empty()))) + let sig = callee.fn_sig(tcx); + match tcx.fn_abi_of_fn_ptr(typing_env.as_query_input((sig, ty::List::empty()))) { + Ok(callee_abi) => callee_abi, + Err(err) => { + codegen_handle_fn_abi_err( + tcx, + *err, + loc().0, + FnAbiRequest::OfFnPtr { sig, extra_args: ty::List::empty() }, + ); + // ABI failed to compute; this will not get through codegen. + return; + } + } } ty::FnDef(def_id, args) => { // Intrinsics are handled separately by the compiler. @@ -232,17 +253,25 @@ fn check_call_site_abi<'tcx>( // LLVM intrinsics don't have an ABI, so there is nothing to check. return; } - tcx.fn_abi_of_instance(typing_env.as_query_input((instance, ty::List::empty()))) + match tcx.fn_abi_of_instance(typing_env.as_query_input((instance, ty::List::empty()))) { + Ok(callee_abi) => callee_abi, + Err(err) => { + codegen_handle_fn_abi_err( + tcx, + *err, + loc().0, + FnAbiRequest::OfInstance { instance, extra_args: ty::List::empty() }, + ); + // ABI failed to compute; this will not get through codegen. + return; + } + } } _ => { panic!("Invalid function call"); } }; - let Ok(callee_abi) = callee_abi else { - // ABI failed to compute; this will not get through codegen. - return; - }; do_check_unsized_params(tcx, callee_abi, /*is_call*/ true, loc); do_check_simd_vector_abi(tcx, callee_abi, caller.def_id(), /*is_call*/ true, loc); } diff --git a/tests/crashes/152204.rs b/tests/crashes/152204.rs deleted file mode 100644 index 8c9be213d9ea5..0000000000000 --- a/tests/crashes/152204.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ known-bug: #152204 -//@ compile-flags: -Copt-level=0 -#![feature(portable_simd)] - -fn main() { - if false { - let _ = core::simd::Simd::::splat(0); - } -} diff --git a/tests/ui/abi/no_delayed_bug.rs b/tests/ui/abi/no_delayed_bug.rs new file mode 100644 index 0000000000000..9b378ba9d25a7 --- /dev/null +++ b/tests/ui/abi/no_delayed_bug.rs @@ -0,0 +1,15 @@ +// Used to ICE due to the ABI checker emitting a delayed bug when failing to get +// the FnAbi due to a const assert, while codegen skipped the call due to being +// unreachable. +//@ compile-flags: -Copt-level=0 +//@ build-fail + +//~? ERROR the SIMD type `Simd` has more elements than the limit 64 + +#![feature(portable_simd)] + +fn main() { + if false { + let _ = core::simd::Simd::::splat(0); + } +} diff --git a/tests/ui/abi/no_delayed_bug.stderr b/tests/ui/abi/no_delayed_bug.stderr new file mode 100644 index 0000000000000..c21256b86a6c4 --- /dev/null +++ b/tests/ui/abi/no_delayed_bug.stderr @@ -0,0 +1,11 @@ +error: the SIMD type `Simd` has more elements than the limit 64 + --> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/vector.rs:LL:COL + +note: the above error was encountered while instantiating `fn Simd::::splat` + --> $DIR/no_delayed_bug.rs:13:17 + | +LL | let _ = core::simd::Simd::::splat(0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/limits/issue-17913.32bit.stderr b/tests/ui/limits/issue-17913.32bit.stderr index 1e3e3a9f32295..6ddde4b891836 100644 --- a/tests/ui/limits/issue-17913.32bit.stderr +++ b/tests/ui/limits/issue-17913.32bit.stderr @@ -1,3 +1,6 @@ +error: values of the type `[&usize; usize::MAX]` are too big for the target architecture + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + error[E0080]: values of the type `[&usize; usize::MAX]` are too big for the target architecture --> $SRC_DIR/core/src/mem/mod.rs:LL:COL | @@ -9,6 +12,6 @@ note: the above error was encountered while instantiating `fn Box::<[&usize; usi LL | let a: Box<_> = Box::new([&n; SIZE]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/limits/issue-17913.64bit.stderr b/tests/ui/limits/issue-17913.64bit.stderr index 5e92c70a764c4..d35d697d5f3f3 100644 --- a/tests/ui/limits/issue-17913.64bit.stderr +++ b/tests/ui/limits/issue-17913.64bit.stderr @@ -1,3 +1,6 @@ +error: values of the type `[&usize; usize::MAX]` are too big for the target architecture + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + error[E0080]: values of the type `[&usize; usize::MAX]` are too big for the target architecture --> $SRC_DIR/core/src/mem/mod.rs:LL:COL | @@ -9,6 +12,6 @@ note: the above error was encountered while instantiating `fn Box::<[&usize; usi LL | let a: Box<_> = Box::new([&n; SIZE]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/limits/issue-17913.rs b/tests/ui/limits/issue-17913.rs index 9448358edba00..d804b64ab330e 100644 --- a/tests/ui/limits/issue-17913.rs +++ b/tests/ui/limits/issue-17913.rs @@ -18,3 +18,4 @@ fn main() { } //~? ERROR are too big for the target architecture +//~? ERROR are too big for the target architecture From e525d70b9faee49982f1e5cf6bc5ad87e147ed02 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 31 Aug 2026 13:12:15 +0200 Subject: [PATCH 4/4] Avoid panic when metadata encoder is called with errors And remove the encoded metadata if there are any errors or delayed bugs after encoding. --- compiler/rustc_interface/src/passes.rs | 5 ++++- compiler/rustc_metadata/src/fs.rs | 9 +++++++-- compiler/rustc_metadata/src/rmeta/encoder.rs | 15 +++++++++++++-- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 68af061769437..12f3140a8c7b3 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1302,7 +1302,10 @@ pub(crate) fn start_codegen<'tcx>( info!("Pre-codegen\n{:?}", tcx.debug_stats()); - let metadata = rustc_metadata::fs::encode_and_write_metadata(tcx); + let metadata = match rustc_metadata::fs::encode_and_write_metadata(tcx) { + Ok(metadata) => metadata, + Err(guar) => guar.raise_fatal(), + }; let is_host_metadata = tcx .sess diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index 535197b3dc51a..ed177708facc0 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -7,6 +7,7 @@ use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_session::config::{OutFileName, OutputType}; use rustc_session::output::filename_for_metadata; +use rustc_span::ErrorGuaranteed; use rustc_structures::CrateType; use crate::diagnostics::{ @@ -34,7 +35,7 @@ pub fn emit_wrapper_file(sess: &Session, data: &[u8], tmpdir: &Path, name: &str) out_filename } -pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { +pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> Result { let out_filename = filename_for_metadata(tcx.sess, tcx.output_filenames(())); // To avoid races with another rustc process scanning the output directory, // we need to write the file somewhere else and atomically move it to its @@ -70,6 +71,10 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { } } + if let Some(guar) = tcx.sess.dcx().has_errors_or_delayed_bugs() { + return Err(guar); + } + let _prof_timer = tcx.sess.prof.generic_activity("write_crate_metadata"); // If the user requests metadata as output, rename `metadata_filename` @@ -109,7 +114,7 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { tcx.dcx().emit_fatal(FailedCreateEncodedMetadata { err }); }); - metadata + Ok(metadata) } #[cfg(not(target_os = "linux"))] diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 713671c3a5b47..dc4a41ace6b88 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1571,8 +1571,19 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } if let DefKind::Static { .. } = def_kind { if !self.tcx.is_foreign_item(def_id) { - let data = self.tcx.eval_static_initializer(def_id).unwrap(); - record!(self.tables.eval_static_initializer[def_id] <- data); + match self.tcx.eval_static_initializer(def_id) { + Ok(data) => record!(self.tables.eval_static_initializer[def_id] <- data), + Err(err) => match err { + interpret::ErrorHandled::Reported(_, _) => { + self.tcx.dcx().delayed_bug(format!( + "eval_static_initializer returned an error in metadata emission" + )); + } + interpret::ErrorHandled::TooGeneric(span) => { + span_bug!(span, "generic static???"); + } + }, + }; } } if let DefKind::Enum | DefKind::Struct | DefKind::Union = def_kind {