From 995b0a4a5508279d604f17d3fc4570f5b98d8554 Mon Sep 17 00:00:00 2001 From: xmakro Date: Tue, 2 Jun 2026 09:28:07 -0700 Subject: [PATCH 1/2] Bubble up post-monomorphization errors instead of reading the global count `collect_items_rec` snapshots the error count before processing a mono item and compares it afterwards to decide whether to attach the "the above error was encountered while instantiating ..." note. The mono item graph is walked in parallel, so the global error count can be bumped by an error emitted while collecting a different item on another thread between the two reads, which makes an unrelated item (often lang_start) get blamed. Instead of consulting the global count, bubble up an `ErrorGuaranteed` from the places that actually emit post-monomorphization errors during collection: const-eval failures in `eval_constant` and, through `check_mono_item`, the feature-dependent ABI checks and a `large_assignments` lint that has been escalated to `deny`/`forbid`. `items_of_instance` now returns whether such an error was encountered, and `collect_items_rec` uses that to decide whether to emit the note. This is unaffected by what other threads are doing. `large_assignments` is normally a warning and so does not hand back an `ErrorGuaranteed`. When it is escalated to an error we recover the proof token from the `DiagCtxt` right after emitting, gated on the lint's effective level at the relevant node so the note is only attributed to an instantiation whose own lint became the error. --- compiler/rustc_middle/src/queries.rs | 4 +- compiler/rustc_middle/src/query/erase.rs | 2 +- compiler/rustc_monomorphize/src/collector.rs | 43 +++++---- .../src/mono_checks/abi_check.rs | 91 ++++++++++++------- .../rustc_monomorphize/src/mono_checks/mod.rs | 17 +++- .../src/mono_checks/move_check.rs | 20 +++- 6 files changed, 118 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 5add2cf09b7b8..2547e1a246588 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -2680,11 +2680,11 @@ rustc_queries! { /// Perform monomorphization-time checking on this item. /// This is used for lints/errors that can only be checked once the instance is fully /// monomorphized. - query check_mono_item(key: ty::Instance<'tcx>) { + query check_mono_item(key: ty::Instance<'tcx>) -> Result<(), ErrorGuaranteed> { desc { "monomorphization-time checking" } } - query items_of_instance(key: (ty::Instance<'tcx>, CollectionMode)) -> Result<(&'tcx [Spanned>], &'tcx [Spanned>]), NormalizationErrorInMono> { + query items_of_instance(key: (ty::Instance<'tcx>, CollectionMode)) -> Result<(&'tcx [Spanned>], &'tcx [Spanned>], Option), NormalizationErrorInMono> { desc { "collecting items used by `{}`", key.0 } cache_on_disk } diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 2dacf64f8cf85..e6dd3a4d04bb0 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -193,7 +193,7 @@ impl_erasable_for_types_with_no_type_params! { Result<&'_ traits::ImplSource<'_, ()>, traits::CodegenObligationError>, Result<&'_ ty::List>, ty::util::AlwaysRequiresDrop>, Result<(&'_ Steal>, thir::ExprId), ErrorGuaranteed>, - Result<(&'_ [Spanned>], &'_ [Spanned>]), NormalizationErrorInMono>, + Result<(&'_ [Spanned>], &'_ [Spanned>], Option), NormalizationErrorInMono>, Result<(), ErrorGuaranteed>, Result>>, ErrorGuaranteed>, Result>, ErrorGuaranteed>, diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 9ddd33678c341..cb59d4a6f3019 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -232,7 +232,7 @@ use rustc_middle::ty::{ use rustc_middle::util::Providers; use rustc_middle::{bug, span_bug}; use rustc_session::config::{DebugInfo, EntryFnType}; -use rustc_span::{DUMMY_SP, Span, Spanned, dummy_spanned, respan}; +use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Spanned, dummy_spanned, respan}; use tracing::{debug, instrument, trace}; use crate::errors::{ @@ -408,12 +408,13 @@ fn collect_items_rec<'tcx>( // source. If the cause is in another crate, the goal here is to quickly locate which mono // item in the current crate is ultimately responsible for causing the error. // - // To give at least _some_ context to the user: while collecting mono items, we check the - // error count. If it has changed, a PME occurred, and we trigger some diagnostics about the - // current step of mono items collection. - // - // FIXME: don't rely on global state, instead bubble up errors. Note: this is very hard to do. - let error_count = tcx.dcx().err_count(); + // To give at least _some_ context to the user: while collecting mono items, we track whether a + // post-monomorphization error was encountered while processing this item. Rather than reading + // the global error count (which is racy under the parallel front-end, since errors emitted on + // other threads would be miscounted), we bubble up an `ErrorGuaranteed` from the places that + // actually emit such errors (const-eval, the ABI checks, and a `deny`-level `large_assignments` + // lint) through `items_of_instance`. + let mut encountered_error: Option = None; // In `mentioned_items` we collect items that were mentioned in this MIR but possibly do not // need to be monomorphized. This is done to ensure that optimizing away function calls does not @@ -472,7 +473,8 @@ fn collect_items_rec<'tcx>( )); rustc_data_structures::stack::ensure_sufficient_stack(|| { - let Ok((used, mentioned)) = tcx.items_of_instance((instance, mode)) else { + let Ok((used, mentioned, used_error)) = tcx.items_of_instance((instance, mode)) + else { // Normalization errors here are usually due to trait solving overflow. // FIXME: I assume that there are few type errors at post-analysis stage, but not // entirely sure. @@ -488,6 +490,7 @@ fn collect_items_rec<'tcx>( def_path_str, }); }; + encountered_error = encountered_error.or(used_error); used_items.extend(used.into_iter().copied()); mentioned_items.extend(mentioned.into_iter().copied()); }); @@ -538,7 +541,7 @@ fn collect_items_rec<'tcx>( // Check for PMEs and emit a diagnostic if one happened. To try to show relevant edges of the // mono item graph. - if tcx.dcx().err_count() > error_count + if encountered_error.is_some() && starting_item.node.is_generic_fn() && starting_item.node.is_user_defined() { @@ -686,6 +689,10 @@ struct MirUsedCollector<'a, 'tcx> { /// Note that this contains *not-monomorphized* items! used_mentioned_items: &'a mut UnordSet>, instance: Instance<'tcx>, + /// Set if collection encountered an already-reported post-monomorphization error (e.g. a + /// const-eval failure). Bubbled up so callers can emit the "while instantiating" note without + /// consulting the global error count. + encountered_error: Option, } impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> { @@ -715,8 +722,9 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> { "collection encountered polymorphic constant: {:?}", const_ ), - Err(err @ ErrorHandled::Reported(..)) => { + Err(err @ ErrorHandled::Reported(info, _span)) => { err.emit_note(self.tcx); + self.encountered_error = self.encountered_error.or(Some(info.into())); return None; } } @@ -1303,14 +1311,14 @@ fn collect_items_of_instance<'tcx>( tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, mode: CollectionMode, -) -> Result<(MonoItems<'tcx>, MonoItems<'tcx>), NormalizationErrorInMono> { +) -> Result<(MonoItems<'tcx>, MonoItems<'tcx>, Option), NormalizationErrorInMono> { // This item is getting monomorphized, do mono-time checks. let body = tcx.instance_mir(instance.def); // Plenty of code paths later assume that everything can be normalized. So we have to check // normalization first. // We choose to emit the error outside to provide helpful diagnostics. check_normalization_error(tcx, instance, body)?; - tcx.ensure_ok().check_mono_item(instance); + let mono_check_error = tcx.check_mono_item(instance).err(); // Naively, in "used" collection mode, all functions get added to *both* `used_items` and // `mentioned_items`. Mentioned items processing will then notice that they have already been @@ -1331,6 +1339,7 @@ fn collect_items_of_instance<'tcx>( used_items: &mut used_items, used_mentioned_items: &mut used_mentioned_items, instance, + encountered_error: mono_check_error, }; if mode == CollectionMode::UsedItems { @@ -1361,22 +1370,24 @@ fn collect_items_of_instance<'tcx>( } } - Ok((used_items, mentioned_items)) + let encountered_error = collector.encountered_error; + Ok((used_items, mentioned_items, encountered_error)) } fn items_of_instance<'tcx>( tcx: TyCtxt<'tcx>, (instance, mode): (Instance<'tcx>, CollectionMode), ) -> Result< - (&'tcx [Spanned>], &'tcx [Spanned>]), + (&'tcx [Spanned>], &'tcx [Spanned>], Option), NormalizationErrorInMono, > { - let (used_items, mentioned_items) = collect_items_of_instance(tcx, instance, mode)?; + let (used_items, mentioned_items, encountered_error) = + collect_items_of_instance(tcx, instance, mode)?; let used_items = tcx.arena.alloc_from_iter(used_items); let mentioned_items = tcx.arena.alloc_from_iter(mentioned_items); - Ok((used_items, mentioned_items)) + Ok((used_items, mentioned_items, encountered_error)) } /// `item` must be already monomorphized. diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs index 10218523ca232..4c33dcc1aa155 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs @@ -5,7 +5,7 @@ use rustc_hir::{CRATE_HIR_ID, HirId}; use rustc_middle::mir::{self, Location, traversal}; use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt}; use rustc_span::def_id::DefId; -use rustc_span::{DUMMY_SP, Span, Symbol, sym}; +use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym}; use rustc_target::callconv::{FnAbi, PassMode}; use crate::errors; @@ -57,7 +57,8 @@ fn do_check_simd_vector_abi<'tcx>( def_id: DefId, is_call: bool, loc: impl Fn() -> (Span, HirId), -) { +) -> Option { + let mut res = None; let codegen_attrs = tcx.codegen_fn_attrs(def_id); let have_feature = |feat: Symbol| { let target_feats = tcx.sess.unstable_target_features.contains(&feat); @@ -74,23 +75,25 @@ fn do_check_simd_vector_abi<'tcx>( Some((_, feature)) => feature, None => { let (span, _hir_id) = loc(); - tcx.dcx().emit_err(errors::AbiErrorUnsupportedVectorType { - span, - ty: arg_abi.layout.ty, - is_call, - }); + res = res.or(Some(tcx.dcx().emit_err( + errors::AbiErrorUnsupportedVectorType { + span, + ty: arg_abi.layout.ty, + is_call, + }, + ))); continue; } }; if !feature.is_empty() && !have_feature(Symbol::intern(feature)) { let (span, _hir_id) = loc(); - tcx.dcx().emit_err(errors::AbiErrorDisabledVectorType { + res = res.or(Some(tcx.dcx().emit_err(errors::AbiErrorDisabledVectorType { span, required_feature: feature, ty: arg_abi.layout.ty, is_call, is_scalable: false, - }); + }))); } } UsesVectorRegisters::ScalableVector => { @@ -101,13 +104,13 @@ fn do_check_simd_vector_abi<'tcx>( }; if !required_feature.is_empty() && !have_feature(Symbol::intern(required_feature)) { let (span, _) = loc(); - tcx.dcx().emit_err(errors::AbiErrorDisabledVectorType { + res = res.or(Some(tcx.dcx().emit_err(errors::AbiErrorDisabledVectorType { span, required_feature, ty: arg_abi.layout.ty, is_call, is_scalable: true, - }); + }))); } } UsesVectorRegisters::No => { @@ -118,13 +121,14 @@ fn do_check_simd_vector_abi<'tcx>( // The `vectorcall` ABI is special in that it requires SSE2 no matter which types are being passed. if abi.conv == CanonAbi::X86(X86Call::Vectorcall) && !have_feature(sym::sse2) { let (span, _hir_id) = loc(); - tcx.dcx().emit_err(errors::AbiRequiredTargetFeature { + res = res.or(Some(tcx.dcx().emit_err(errors::AbiRequiredTargetFeature { span, required_feature: "sse2", abi: "vectorcall", is_call, - }); + }))); } + res } /// Emit an error when a non-rustic ABI has unsized parameters. @@ -136,42 +140,47 @@ fn do_check_unsized_params<'tcx>( fn_abi: &FnAbi<'tcx, Ty<'tcx>>, is_call: bool, loc: impl Fn() -> (Span, HirId), -) { +) -> Option { // Unsized parameters are allowed with the (unstable) "Rust" (and similar) ABIs. if fn_abi.conv.is_rustic_abi() { - return; + return None; } + let mut res = None; for arg_abi in fn_abi.args.iter() { if !arg_abi.layout.layout.is_sized() { let (span, _hir_id) = loc(); - tcx.dcx().emit_err(errors::AbiErrorUnsupportedUnsizedParameter { + res = res.or(Some(tcx.dcx().emit_err(errors::AbiErrorUnsupportedUnsizedParameter { span, ty: arg_abi.layout.ty, is_call, - }); + }))); } } + res } /// Checks the ABI of an Instance, emitting an error when: /// /// - a non-rustic ABI uses unsized parameters /// - the signature requires target features that are not enabled -fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { +fn check_instance_abi<'tcx>( + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, +) -> Option { let typing_env = ty::TypingEnv::fully_monomorphized(); let ty = instance.ty(tcx, typing_env); if ty.is_fn() && ty.fn_sig(tcx).abi() == ExternAbi::Unadjusted { // We disable all checks for the unadjusted ABI to allow linking to arbitrary LLVM // intrinsics - return; + return None; } 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; + return None; }; // Unlike the call-site check, we do also check "Rust" ABI functions here. // This should never trigger, *except* if we start making use of vector registers @@ -186,8 +195,11 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { def_id.as_local().map(|did| tcx.local_def_id_to_hir_id(did)).unwrap_or(CRATE_HIR_ID), ) }; - do_check_unsized_params(tcx, abi, /*is_call*/ false, loc); - do_check_simd_vector_abi(tcx, abi, instance.def_id(), /*is_call*/ false, loc); + // Call both checks unconditionally for their diagnostic side effects before combining. + let unsized_res = do_check_unsized_params(tcx, abi, /*is_call*/ false, loc); + let simd_res = + do_check_simd_vector_abi(tcx, abi, instance.def_id(), /*is_call*/ false, loc); + unsized_res.or(simd_res) } /// Check the ABI at a call site, emitting an error when: @@ -199,14 +211,14 @@ fn check_call_site_abi<'tcx>( callee: Ty<'tcx>, caller: InstanceKind<'tcx>, loc: impl Fn() -> (Span, HirId) + Copy, -) { +) -> Option { let extern_abi = callee.fn_sig(tcx).abi(); if extern_abi.is_rustic_abi() || extern_abi == ExternAbi::Unadjusted { // We directly handle the soundness of Rust ABIs -- so let's skip the majority of // call sites to avoid a perf regression. // We disable all checks for the unadjusted ABI to allow linking to arbitrary LLVM // intrinsics - return; + return None; } let typing_env = ty::TypingEnv::fully_monomorphized(); let callee_abi = match *callee.kind() { @@ -216,7 +228,7 @@ fn check_call_site_abi<'tcx>( ty::FnDef(def_id, args) => { // Intrinsics are handled separately by the compiler. if tcx.intrinsic(def_id).is_some() { - return; + return None; } let instance = ty::Instance::expect_resolve(tcx, typing_env, def_id, args, DUMMY_SP); tcx.fn_abi_of_instance(typing_env.as_query_input((instance, ty::List::empty()))) @@ -228,13 +240,21 @@ fn check_call_site_abi<'tcx>( let Ok(callee_abi) = callee_abi else { // ABI failed to compute; this will not get through codegen. - return; + return None; }; - 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); + // Call both checks unconditionally for their diagnostic side effects before combining. + let unsized_res = do_check_unsized_params(tcx, callee_abi, /*is_call*/ true, loc); + let simd_res = + do_check_simd_vector_abi(tcx, callee_abi, caller.def_id(), /*is_call*/ true, loc); + unsized_res.or(simd_res) } -fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &mir::Body<'tcx>) { +fn check_callees_abi<'tcx>( + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, + body: &mir::Body<'tcx>, +) -> Option { + let mut res = None; // Check all function call terminators. for (bb, _data) in traversal::mono_reachable(body, tcx, instance) { let terminator = body.basic_blocks[bb].terminator(); @@ -247,7 +267,7 @@ fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &m ty::TypingEnv::fully_monomorphized(), ty::EarlyBinder::bind(callee_ty), ); - check_call_site_abi(tcx, callee_ty, body.source.instance, || { + res = res.or(check_call_site_abi(tcx, callee_ty, body.source.instance, || { let loc = Location { block: bb, statement_index: body.basic_blocks[bb].statements.len(), @@ -259,18 +279,21 @@ fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &m .lint_root(&body.source_scopes) .unwrap_or(CRATE_HIR_ID), ) - }); + })); } _ => {} } } + res } pub(crate) fn check_feature_dependent_abi<'tcx>( tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &'tcx mir::Body<'tcx>, -) { - check_instance_abi(tcx, instance); - check_callees_abi(tcx, instance, body); +) -> Option { + // Call both checks unconditionally for their diagnostic side effects before combining. + let instance_res = check_instance_abi(tcx, instance); + let callees_res = check_callees_abi(tcx, instance, body); + instance_res.or(callees_res) } diff --git a/compiler/rustc_monomorphize/src/mono_checks/mod.rs b/compiler/rustc_monomorphize/src/mono_checks/mod.rs index 6569eeafec17d..d9be59c4abd2c 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/mod.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/mod.rs @@ -4,14 +4,25 @@ use rustc_middle::query::Providers; use rustc_middle::ty::{Instance, TyCtxt}; +use rustc_span::ErrorGuaranteed; mod abi_check; mod move_check; -fn check_mono_item<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { +fn check_mono_item<'tcx>( + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, +) -> Result<(), ErrorGuaranteed> { let body = tcx.instance_mir(instance.def); - abi_check::check_feature_dependent_abi(tcx, instance, body); - move_check::check_moves(tcx, instance, body); + // Run both checks unconditionally for their diagnostic side effects before combining. Each + // returns `Some` if it emitted a hard post-monomorphization error: `abi_check` for ABI errors, + // and `move_check` when `large_assignments` is escalated to `deny`/`forbid`. + let abi_res = abi_check::check_feature_dependent_abi(tcx, instance, body); + let move_res = move_check::check_moves(tcx, instance, body); + match abi_res.or(move_res) { + Some(guar) => Err(guar), + None => Ok(()), + } } pub(super) fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs index af03e2a0d2d66..5a3c577e0115a 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs @@ -6,7 +6,7 @@ use rustc_middle::mir::visit::Visitor as MirVisitor; use rustc_middle::mir::{self, Location, traversal}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable}; use rustc_session::lint::builtin::LARGE_ASSIGNMENTS; -use rustc_span::{Span, Spanned, sym}; +use rustc_span::{ErrorGuaranteed, Span, Spanned, sym}; use tracing::{debug, trace}; use crate::errors::LargeAssignmentsLint; @@ -17,17 +17,23 @@ struct MoveCheckVisitor<'tcx> { body: &'tcx mir::Body<'tcx>, /// Spans for move size lints already emitted. Helps avoid duplicate lints. move_size_spans: Vec, + /// Set if the `large_assignments` lint was emitted at error level (`deny`/`forbid`). Bubbled up + /// so the post-monomorphization "while instantiating" note can be attached without consulting + /// the global error count. + encountered_error: Option, } pub(crate) fn check_moves<'tcx>( tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &'tcx mir::Body<'tcx>, -) { - let mut visitor = MoveCheckVisitor { tcx, instance, body, move_size_spans: vec![] }; +) -> Option { + let mut visitor = + MoveCheckVisitor { tcx, instance, body, move_size_spans: vec![], encountered_error: None }; for (bb, data) in traversal::mono_reachable(body, tcx, instance) { visitor.visit_basic_block_data(bb, data) } + visitor.encountered_error } impl<'tcx> MirVisitor<'tcx> for MoveCheckVisitor<'tcx> { @@ -184,6 +190,14 @@ impl<'tcx> MoveCheckVisitor<'tcx> { }, ); + // When `large_assignments` is set to `deny`/`forbid` the lint above was emitted as a hard + // error. The lint emission API does not hand back an `ErrorGuaranteed`, so recover the proof + // token from the `DiagCtxt`. We gate on the effective level so we only attribute an error to + // this instantiation when our own lint is the one that escalated to an error. + if self.tcx.lint_level_spec_at_node(LARGE_ASSIGNMENTS, lint_root).level().is_error() { + self.encountered_error = self.encountered_error.or_else(|| self.tcx.dcx().has_errors()); + } + self.move_size_spans.push(reported_span); } } From 208ee048b4e6c0acba7904ddb893521815c1d4e5 Mon Sep 17 00:00:00 2001 From: xmakro Date: Wed, 3 Jun 2026 08:49:45 -0700 Subject: [PATCH 2/2] Re-enable parallel frontend tests for post-monomorphization errors These were marked ignore-parallel-frontend because the spurious instantiation note made their output nondeterministic under -Zthreads. With that fixed they pass reliably. Replace the directive with a blank line rather than deleting it, so the following line numbers stay the same and the expected output is unchanged. Also add a regression test for a deny-level large_assignments lint inside a generic function, which must produce the instantiation note now that the lint is bubbled up as a post-monomorphization error. --- tests/ui/abi/simd-abi-checks-avx.rs | 2 +- .../index-out-of-bounds-never-type.rs | 2 +- tests/ui/consts/const-eval/issue-50814-2.rs | 2 +- tests/ui/consts/const-eval/issue-50814.rs | 2 +- .../ui/consts/mono-reachable-invalid-const.rs | 2 +- .../required-consts/collect-in-called-fn.rs | 2 +- .../collect-in-dead-closure.rs | 2 +- .../required-consts/collect-in-dead-drop.rs | 2 +- .../collect-in-dead-fn-behind-assoc-type.rs | 2 +- .../collect-in-dead-fn-behind-generic.rs | 2 +- .../collect-in-dead-fn-behind-opaque-type.rs | 2 +- .../required-consts/collect-in-dead-fn.rs | 2 +- .../collect-in-dead-fnptr-in-const.rs | 2 +- .../required-consts/collect-in-dead-fnptr.rs | 2 +- .../required-consts/collect-in-dead-forget.rs | 2 +- .../required-consts/collect-in-dead-move.rs | 2 +- .../required-consts/collect-in-dead-vtable.rs | 2 +- .../collect-in-promoted-const.rs | 2 +- .../interpret-in-const-called-fn.rs | 2 +- .../required-consts/interpret-in-promoted.rs | 2 +- .../required-consts/interpret-in-static.rs | 2 +- tests/ui/inline-const/required-const.rs | 2 +- .../large_assignments/copy_into_box_rc_arc.rs | 2 +- .../ui/lint/large_assignments/copy_into_fn.rs | 2 +- tests/ui/lint/large_assignments/inline_mir.rs | 2 +- .../ui/lint/large_assignments/large_future.rs | 2 +- .../large_assignments/move_in_generic_fn.rs | 19 +++++++++++++++++ .../move_in_generic_fn.stderr | 21 +++++++++++++++++++ .../ui/lint/large_assignments/move_into_fn.rs | 2 +- tests/ui/simd/const-err-trumps-simd-err.rs | 2 +- .../structs/default-field-values/post-mono.rs | 2 +- 31 files changed, 69 insertions(+), 29 deletions(-) create mode 100644 tests/ui/lint/large_assignments/move_in_generic_fn.rs create mode 100644 tests/ui/lint/large_assignments/move_in_generic_fn.stderr diff --git a/tests/ui/abi/simd-abi-checks-avx.rs b/tests/ui/abi/simd-abi-checks-avx.rs index c68ba2fb5f890..7432381d15b72 100644 --- a/tests/ui/abi/simd-abi-checks-avx.rs +++ b/tests/ui/abi/simd-abi-checks-avx.rs @@ -1,7 +1,7 @@ //@ only-x86_64 //@ build-fail //@ compile-flags: -C target-feature=-avx -//@ ignore-parallel-frontend post-monomorphization errors + #![feature(portable_simd)] #![feature(simd_ffi)] #![allow(improper_ctypes_definitions)] diff --git a/tests/ui/consts/const-eval/index-out-of-bounds-never-type.rs b/tests/ui/consts/const-eval/index-out-of-bounds-never-type.rs index dbe507e3cd137..6777bee050a16 100644 --- a/tests/ui/consts/const-eval/index-out-of-bounds-never-type.rs +++ b/tests/ui/consts/const-eval/index-out-of-bounds-never-type.rs @@ -1,5 +1,5 @@ //@ build-fail -//@ ignore-parallel-frontend post-monomorphization errors + // Regression test for #66975 #![warn(unconditional_panic)] #![feature(never_type)] diff --git a/tests/ui/consts/const-eval/issue-50814-2.rs b/tests/ui/consts/const-eval/issue-50814-2.rs index 34a200e2887b9..1b917a0916da3 100644 --- a/tests/ui/consts/const-eval/issue-50814-2.rs +++ b/tests/ui/consts/const-eval/issue-50814-2.rs @@ -2,7 +2,7 @@ //@ revisions: normal mir-opt //@ [mir-opt]compile-flags: -Zmir-opt-level=4 //@ dont-require-annotations: NOTE -//@ ignore-parallel-frontend post-monomorphization errors + trait C { const BOO: usize; } diff --git a/tests/ui/consts/const-eval/issue-50814.rs b/tests/ui/consts/const-eval/issue-50814.rs index 3901a2c0c9316..011f065ad814b 100644 --- a/tests/ui/consts/const-eval/issue-50814.rs +++ b/tests/ui/consts/const-eval/issue-50814.rs @@ -1,6 +1,6 @@ //@ build-fail //@ dont-require-annotations: NOTE -//@ ignore-parallel-frontend post-monomorphization errors + trait Unsigned { const MAX: u8; } diff --git a/tests/ui/consts/mono-reachable-invalid-const.rs b/tests/ui/consts/mono-reachable-invalid-const.rs index 3d76e4a65a4e2..aba41dabe71f9 100644 --- a/tests/ui/consts/mono-reachable-invalid-const.rs +++ b/tests/ui/consts/mono-reachable-invalid-const.rs @@ -1,5 +1,5 @@ //@ build-fail -//@ ignore-parallel-frontend post-monomorphization errors + struct Bar; impl Bar { diff --git a/tests/ui/consts/required-consts/collect-in-called-fn.rs b/tests/ui/consts/required-consts/collect-in-called-fn.rs index d07c0927a16a9..2045b8266c792 100644 --- a/tests/ui/consts/required-consts/collect-in-called-fn.rs +++ b/tests/ui/consts/required-consts/collect-in-called-fn.rs @@ -4,7 +4,7 @@ //@[opt] compile-flags: -O //! Make sure we detect erroneous constants post-monomorphization even when they are unused. This is //! crucial, people rely on it for soundness. (https://github.com/rust-lang/rust/issues/112090) -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-closure.rs b/tests/ui/consts/required-consts/collect-in-dead-closure.rs index 825336e9d3ef3..5f8b6bbb174c4 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-closure.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-closure.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-drop.rs b/tests/ui/consts/required-consts/collect-in-dead-drop.rs index fa9b8730c11c9..f7293d162df7b 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-drop.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-drop.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-assoc-type.rs b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-assoc-type.rs index a76481b673132..e6be9f56cb7a0 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-assoc-type.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-assoc-type.rs @@ -4,7 +4,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-generic.rs b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-generic.rs index 4fe05db34d78e..a86902af52677 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-generic.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-generic.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.rs b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.rs index a6132ef1fe07e..4cdb27413540f 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.rs @@ -4,7 +4,7 @@ //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. #![feature(type_alias_impl_trait)] -//@ ignore-parallel-frontend post-monomorphization errors + mod m { struct Fail(T); impl Fail { diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn.rs b/tests/ui/consts/required-consts/collect-in-dead-fn.rs index f4627323249d4..0c4795801068d 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fn.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-fn.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-fnptr-in-const.rs b/tests/ui/consts/required-consts/collect-in-dead-fnptr-in-const.rs index 8808a4e26f0cb..04544cb413984 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fnptr-in-const.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-fnptr-in-const.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Late(T); impl Late { const FAIL: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-fnptr.rs b/tests/ui/consts/required-consts/collect-in-dead-fnptr.rs index 1a9b99f9868f6..4cdb50f4385a1 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fnptr.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-fnptr.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-forget.rs b/tests/ui/consts/required-consts/collect-in-dead-forget.rs index bc717edbe73ee..7586004116c36 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-forget.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-forget.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This passes without optimizations, so it can (and should) also pass with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); diff --git a/tests/ui/consts/required-consts/collect-in-dead-move.rs b/tests/ui/consts/required-consts/collect-in-dead-move.rs index 05491136e8d5e..4e2d959db32c7 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-move.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-move.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-vtable.rs b/tests/ui/consts/required-consts/collect-in-dead-vtable.rs index 1ca52064a3fdd..d4ad730837730 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-vtable.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-vtable.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-promoted-const.rs b/tests/ui/consts/required-consts/collect-in-promoted-const.rs index 415f22fd05dda..c475720938697 100644 --- a/tests/ui/consts/required-consts/collect-in-promoted-const.rs +++ b/tests/ui/consts/required-consts/collect-in-promoted-const.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! Make sure we error on erroneous consts even if they get promoted. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/interpret-in-const-called-fn.rs b/tests/ui/consts/required-consts/interpret-in-const-called-fn.rs index 2d63c620a0384..9309457e22a46 100644 --- a/tests/ui/consts/required-consts/interpret-in-const-called-fn.rs +++ b/tests/ui/consts/required-consts/interpret-in-const-called-fn.rs @@ -2,7 +2,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! Make sure we error on erroneous consts even if they are unused. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR explicit panic diff --git a/tests/ui/consts/required-consts/interpret-in-promoted.rs b/tests/ui/consts/required-consts/interpret-in-promoted.rs index cbb1a309006c5..b223e6d16aa12 100644 --- a/tests/ui/consts/required-consts/interpret-in-promoted.rs +++ b/tests/ui/consts/required-consts/interpret-in-promoted.rs @@ -2,7 +2,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //@ dont-require-annotations: NOTE -//@ ignore-parallel-frontend post-monomorphization errors + //! Make sure we evaluate const fn calls even if they get promoted and their result ignored. const unsafe fn ub() { diff --git a/tests/ui/consts/required-consts/interpret-in-static.rs b/tests/ui/consts/required-consts/interpret-in-static.rs index edc7b1d01fd6c..19ad6be1c9fa7 100644 --- a/tests/ui/consts/required-consts/interpret-in-static.rs +++ b/tests/ui/consts/required-consts/interpret-in-static.rs @@ -2,7 +2,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! Make sure we error on erroneous consts even if they are unused. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR explicit panic diff --git a/tests/ui/inline-const/required-const.rs b/tests/ui/inline-const/required-const.rs index 437652532ec54..8f640e933d019 100644 --- a/tests/ui/inline-const/required-const.rs +++ b/tests/ui/inline-const/required-const.rs @@ -1,6 +1,6 @@ //@ build-fail //@ compile-flags: -Zmir-opt-level=3 -//@ ignore-parallel-frontend post-monomorphization errors + fn foo() { if false { const { panic!() } //~ ERROR E0080 diff --git a/tests/ui/lint/large_assignments/copy_into_box_rc_arc.rs b/tests/ui/lint/large_assignments/copy_into_box_rc_arc.rs index a8e23c0246eeb..dfa0b8015d037 100644 --- a/tests/ui/lint/large_assignments/copy_into_box_rc_arc.rs +++ b/tests/ui/lint/large_assignments/copy_into_box_rc_arc.rs @@ -3,7 +3,7 @@ #![move_size_limit = "1000"] //@ build-fail //@ only-64bit -//@ ignore-parallel-frontend post-monomorphization errors + //@ edition:2018 //@ compile-flags: -Zmir-opt-level=1 diff --git a/tests/ui/lint/large_assignments/copy_into_fn.rs b/tests/ui/lint/large_assignments/copy_into_fn.rs index 8f8e7f0822bbc..5222e833bcc8f 100644 --- a/tests/ui/lint/large_assignments/copy_into_fn.rs +++ b/tests/ui/lint/large_assignments/copy_into_fn.rs @@ -1,5 +1,5 @@ //@ build-fail -//@ ignore-parallel-frontend post-monomorphization errors + #![feature(large_assignments)] #![move_size_limit = "1000"] #![deny(large_assignments)] diff --git a/tests/ui/lint/large_assignments/inline_mir.rs b/tests/ui/lint/large_assignments/inline_mir.rs index 68c5de4902f34..d16aae6ab145b 100644 --- a/tests/ui/lint/large_assignments/inline_mir.rs +++ b/tests/ui/lint/large_assignments/inline_mir.rs @@ -13,7 +13,7 @@ //! ``` //! //! We want the diagnostics to point to the relevant user code. -//@ ignore-parallel-frontend post-monomorphization errors + //@ build-fail //@ compile-flags: -Zmir-opt-level=1 -Zinline-mir diff --git a/tests/ui/lint/large_assignments/large_future.rs b/tests/ui/lint/large_assignments/large_future.rs index 1be66f16313bb..28c358bdbf086 100644 --- a/tests/ui/lint/large_assignments/large_future.rs +++ b/tests/ui/lint/large_assignments/large_future.rs @@ -5,7 +5,7 @@ //@ only-64bit //@ revisions: attribute option //@ [option]compile-flags: -Zmove-size-limit=1000 -//@ ignore-parallel-frontend post-monomorphization errors + //@ edition:2018 //@ compile-flags: -Zmir-opt-level=0 diff --git a/tests/ui/lint/large_assignments/move_in_generic_fn.rs b/tests/ui/lint/large_assignments/move_in_generic_fn.rs new file mode 100644 index 0000000000000..019ac7a5974a5 --- /dev/null +++ b/tests/ui/lint/large_assignments/move_in_generic_fn.rs @@ -0,0 +1,19 @@ +//@ build-fail +// +// When `large_assignments` is escalated to a hard error inside a generic function, the error must +// be attributed to the instantiation that triggered it, producing a "while instantiating" note. +// This exercises the post-monomorphization error bubbling out of the move check. +#![feature(large_assignments)] +#![move_size_limit = "1000"] +#![deny(large_assignments)] +#![allow(unused)] + +struct Data([u8; 9999]); + +fn main() { + instantiate::(); +} + +fn instantiate() { + let data = Data([100; 9999]); //~ ERROR large_assignments +} diff --git a/tests/ui/lint/large_assignments/move_in_generic_fn.stderr b/tests/ui/lint/large_assignments/move_in_generic_fn.stderr new file mode 100644 index 0000000000000..707c8ec249c24 --- /dev/null +++ b/tests/ui/lint/large_assignments/move_in_generic_fn.stderr @@ -0,0 +1,21 @@ +error: moving 9999 bytes + --> $DIR/move_in_generic_fn.rs:18:16 + | +LL | let data = Data([100; 9999]); + | ^^^^^^^^^^^^^^^^^ value moved from here + | + = note: the current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` +note: the lint level is defined here + --> $DIR/move_in_generic_fn.rs:8:9 + | +LL | #![deny(large_assignments)] + | ^^^^^^^^^^^^^^^^^ + +note: the above error was encountered while instantiating `fn instantiate::` + --> $DIR/move_in_generic_fn.rs:14:5 + | +LL | instantiate::(); + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/large_assignments/move_into_fn.rs b/tests/ui/lint/large_assignments/move_into_fn.rs index 1e793a082e3ea..b3b2160ca36e1 100644 --- a/tests/ui/lint/large_assignments/move_into_fn.rs +++ b/tests/ui/lint/large_assignments/move_into_fn.rs @@ -1,5 +1,5 @@ //@ build-fail -//@ ignore-parallel-frontend post-monomorphization errors + #![feature(large_assignments)] #![move_size_limit = "1000"] #![deny(large_assignments)] diff --git a/tests/ui/simd/const-err-trumps-simd-err.rs b/tests/ui/simd/const-err-trumps-simd-err.rs index 282d5dabf72fa..33f0abb06f3ea 100644 --- a/tests/ui/simd/const-err-trumps-simd-err.rs +++ b/tests/ui/simd/const-err-trumps-simd-err.rs @@ -1,6 +1,6 @@ //@build-fail //@ dont-require-annotations: NOTE -//@ ignore-parallel-frontend post-monomorphization errors + //! Make sure that monomorphization-time const errors from `static_assert` take priority over the //! error from simd_extract. Basically this checks that if a const fails to evaluate in some //! function, we don't bother codegen'ing the function. diff --git a/tests/ui/structs/default-field-values/post-mono.rs b/tests/ui/structs/default-field-values/post-mono.rs index 57092083ca102..68dfa391bb485 100644 --- a/tests/ui/structs/default-field-values/post-mono.rs +++ b/tests/ui/structs/default-field-values/post-mono.rs @@ -1,6 +1,6 @@ //@ build-fail //@ revisions: direct indirect -//@ ignore-parallel-frontend post-monomorphization errors + #![feature(default_field_values)] struct Z {