diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index 32202ac3eded1..eab6d8168ca8e 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -20,6 +20,7 @@ //! | ----------------------- | ------------------- | ------------------------------- | //! | `Lrc` | `rc::Rc` | `sync::Arc` | //! |` Weak` | `rc::Weak` | `sync::Weak` | +//! | `LRef<'a, T>` [^2] | `&'a mut T` | `&'a T` | //! | | | | //! | `AtomicBool` | `Cell` | `atomic::AtomicBool` | //! | `AtomicU32` | `Cell` | `atomic::AtomicU32` | @@ -38,7 +39,7 @@ //! of a `RefCell`. This is appropriate when interior mutability is not //! required. //! -//! [^2] `MTLockRef` is a typedef. +//! [^2] `MTRef`, `MTLockRef` are type aliases. pub use crate::marker::*; use std::collections::HashMap; @@ -208,7 +209,7 @@ cfg_match! { use std::cell::RefCell as InnerRwLock; - pub type MTLockRef<'a, T> = &'a mut MTLock; + pub type LRef<'a, T> = &'a mut T; #[derive(Debug, Default)] pub struct MTLock(T); @@ -274,7 +275,7 @@ cfg_match! { pub use std::sync::Arc as Lrc; pub use std::sync::Weak as Weak; - pub type MTLockRef<'a, T> = &'a MTLock; + pub type LRef<'a, T> = &'a T; #[derive(Debug, Default)] pub struct MTLock(Lock); @@ -314,6 +315,8 @@ cfg_match! { } } +pub type MTLockRef<'a, T> = LRef<'a, MTLock>; + #[derive(Default)] #[cfg_attr(parallel_compiler, repr(align(64)))] pub struct CacheAligned(pub T); diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index d57ffc0f8b5c5..6c9d5c670825f 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -20,6 +20,7 @@ use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; use rustc_hir::{self, CoroutineDesugaring, CoroutineKind, ImplicitSelfKind}; use rustc_hir::{self as hir, HirId}; use rustc_session::Session; +use rustc_span::source_map::Spanned; use rustc_target::abi::{FieldIdx, VariantIdx}; use polonius_engine::Atom; @@ -312,6 +313,16 @@ impl<'tcx> CoroutineInfo<'tcx> { } } +/// Some item that needs to monomorphize successfully for a MIR body to be considered well-formed. +#[derive(Copy, Clone, PartialEq, Debug, HashStable, TyEncodable, TyDecodable)] +#[derive(TypeFoldable, TypeVisitable)] +pub enum MentionedItem<'tcx> { + Fn(DefId, GenericArgsRef<'tcx>), + Drop(Ty<'tcx>), + // FIXME: add Vtable { source_ty: Ty<'tcx>, target_ty: Ty<'tcx> }, + // FIXME: do we have to add closures? +} + /// The lowered representation of a single function. #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable, TypeVisitable)] pub struct Body<'tcx> { @@ -375,8 +386,18 @@ pub struct Body<'tcx> { /// Constants that are required to evaluate successfully for this MIR to be well-formed. /// We hold in this field all the constants we are not able to evaluate yet. + /// + /// This is soundness-critical, we make a guarantee that all consts syntactically mentioned in a + /// function have successfully evaluated if the function ever gets executed at runtime. pub required_consts: Vec>, + /// Further items that were mentioned in this function and hence *may* become monomorphized, + /// depending on optimizations. We use this to ensure their consts evaluate successfully even if + /// they do not get monomorphized, to avoid optimization-dependent compile errors. + /// + /// This is *not* soundness-critical and the contents of this list are *not* a stable guarantee. + pub mentioned_items: Vec>>, + /// Does this body use generic parameters. This is used for the `ConstEvaluatable` check. /// /// Note that this does not actually mean that this body is not computable right now. @@ -453,6 +474,7 @@ impl<'tcx> Body<'tcx> { var_debug_info, span, required_consts: Vec::new(), + mentioned_items: Vec::new(), is_polymorphic: false, injection_phase: None, tainted_by_errors, @@ -482,6 +504,7 @@ impl<'tcx> Body<'tcx> { spread_arg: None, span: DUMMY_SP, required_consts: Vec::new(), + mentioned_items: Vec::new(), var_debug_info: Vec::new(), is_polymorphic: false, injection_phase: None, diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs index 288b787798b49..109ffedec5506 100644 --- a/compiler/rustc_mir_build/src/build/custom/mod.rs +++ b/compiler/rustc_mir_build/src/build/custom/mod.rs @@ -56,6 +56,7 @@ pub(super) fn build_custom_mir<'tcx>( var_debug_info: Vec::new(), span, required_consts: Vec::new(), + mentioned_items: Vec::new(), is_polymorphic: false, tainted_by_errors: None, injection_phase: None, diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index f6a0945c22297..aee2c99c929db 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -565,7 +565,8 @@ impl<'tcx> Inliner<'tcx> { mut callee_body: Body<'tcx>, ) { let terminator = caller_body[callsite.block].terminator.take().unwrap(); - let TerminatorKind::Call { args, destination, unwind, target, .. } = terminator.kind else { + let TerminatorKind::Call { func, args, destination, unwind, target, .. } = terminator.kind + else { bug!("unexpected terminator kind {:?}", terminator.kind); }; @@ -717,6 +718,29 @@ impl<'tcx> Inliner<'tcx> { Const::Val(..) | Const::Unevaluated(..) => true, }, )); + // Now that we incorporated the callee's `required_consts`, we can remove the callee from + // `mentioned_items` -- but we have to take their `mentioned_items` in return. + // This does some extra work here to save the monomorphization collector work later. + // FIXME: benchmark which option is better. + let callee_item = { + // We need to reconstruct the `required_item` for the callee so that we can find and + // remove it. + let func_ty = func.ty(caller_body, self.tcx); + match func_ty.kind() { + ty::FnDef(def_id, args) => MentionedItem::Fn(*def_id, args), + _ => bug!(), + } + }; + if let Some(idx) = + caller_body.mentioned_items.iter().position(|item| item.node == callee_item) + { + // We found the callee, so remove it and add its items instead. + caller_body.mentioned_items.remove(idx); + caller_body.mentioned_items.extend(callee_body.mentioned_items); + } else { + // If we can't find the callee, there's no point in adding its items. + // Probably it already got removed by being inlined elsewhere in the same function. + } } fn make_call_args( diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 4551380152217..65bc2af2ad7eb 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -89,6 +89,7 @@ mod lint; mod lower_intrinsics; mod lower_slice_len; mod match_branches; +mod mentioned_items; mod multiple_return_terminators; mod normalize_array_len; mod nrvo; @@ -566,6 +567,10 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { tcx, body, &[ + // Before doing anything, remember which items are being mentioned so that the set of items + // visited does not depend on the optimization level. + &mentioned_items::MentionedItems, + // Add some UB checks before any UB gets optimized away. &check_alignment::CheckAlignment, // Before inlining: trim down MIR with passes to reduce inlining work. diff --git a/compiler/rustc_mir_transform/src/mentioned_items.rs b/compiler/rustc_mir_transform/src/mentioned_items.rs new file mode 100644 index 0000000000000..b1b1ddbf665da --- /dev/null +++ b/compiler/rustc_mir_transform/src/mentioned_items.rs @@ -0,0 +1,56 @@ +use rustc_middle::mir::visit::Visitor; +use rustc_middle::mir::{self, ConstOperand, Location, MentionedItem, MirPass}; +use rustc_middle::ty::{self, TyCtxt}; +use rustc_session::Session; +use rustc_span::source_map::Spanned; + +pub struct MentionedItems; + +struct MentionedItemsVisitor<'a, 'tcx> { + tcx: TyCtxt<'tcx>, + body: &'a mir::Body<'tcx>, + mentioned_items: &'a mut Vec>>, +} + +impl<'tcx> MirPass<'tcx> for MentionedItems { + fn is_enabled(&self, _sess: &Session) -> bool { + // We need to do always do that as the collector will only check the 'mentioned' items of + // 'mentioned' items, so if some item X gets compiled without optimizations but later called + // from somewhere that has optimizations enabled, we need the `mentioned_items` of X to be + // filled. + true + } + + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) { + debug_assert!(body.mentioned_items.is_empty()); + let mut mentioned_items = Vec::new(); + MentionedItemsVisitor { tcx, body, mentioned_items: &mut mentioned_items }.visit_body(body); + body.mentioned_items = mentioned_items; + } +} + +impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> { + fn visit_constant(&mut self, constant: &ConstOperand<'tcx>, _: Location) { + let const_ = constant.const_; + // This is how function items get referenced: via constants of `FnDef` type. + if let ty::FnDef(def_id, args) = const_.ty().kind() { + debug!("adding to required_items: {def_id:?}"); + self.mentioned_items + .push(Spanned { node: MentionedItem::Fn(*def_id, args), span: constant.span }); + } + } + + fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) { + self.super_terminator(terminator, location); + match terminator.kind { + // We don't need to handle `Call` as we already handled all function type operands in + // `visit_constant`. But we do need to handle `Drop`. + mir::TerminatorKind::Drop { place, .. } => { + let ty = place.ty(self.body, self.tcx).ty; + let span = self.body.source_info(location).span; + self.mentioned_items.push(Spanned { node: MentionedItem::Drop(ty), span }); + } + _ => {} + } + } +} diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 733e2f93b2535..dd2b24ad6691d 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -17,7 +17,7 @@ use std::iter; use crate::{ abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, deref_separator, - pass_manager as pm, remove_noop_landing_pads, simplify, + mentioned_items, pass_manager as pm, remove_noop_landing_pads, simplify, }; use rustc_middle::mir::patch::MirPatch; use rustc_mir_dataflow::elaborate_drops::{self, DropElaborator, DropFlagMode, DropStyle}; @@ -147,6 +147,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' tcx, &mut body, &[ + &mentioned_items::MentionedItems, &abort_unwinding_calls::AbortUnwindingCalls, &add_call_guards::CriticalCallEdges, ], @@ -178,6 +179,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' tcx, &mut result, &[ + &mentioned_items::MentionedItems, &add_moves_for_packed_drops::AddMovesForPackedDrops, &deref_separator::Derefer, &remove_noop_landing_pads::RemoveNoopLandingPads, diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index cd9eb4916ce5d..2bdfa069f49e2 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -165,7 +165,7 @@ //! regardless of whether it is actually needed or not. use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::sync::{par_for_each_in, MTLock, MTLockRef}; +use rustc_data_structures::sync::{par_for_each_in, LRef, MTLock}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; @@ -173,7 +173,7 @@ use rustc_hir::lang_items::LangItem; use rustc_middle::mir::interpret::{AllocId, ErrorHandled, GlobalAlloc, Scalar}; use rustc_middle::mir::mono::{InstantiationMode, MonoItem}; use rustc_middle::mir::visit::Visitor as MirVisitor; -use rustc_middle::mir::{self, Location}; +use rustc_middle::mir::{self, Location, MentionedItem}; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCoercion}; use rustc_middle::ty::layout::ValidityRequirement; @@ -214,6 +214,17 @@ pub struct UsageMap<'tcx> { type MonoItems<'tcx> = Vec>>; +/// The state that is shared across the concurrent threads that are doing collection. +struct SharedState<'tcx> { + /// Items that have been or are currently being recursively collected. + visited: MTLock>>, + /// Items that have been or are currently being recursively treated as "mentioned", i.e., their + /// consts are evaluated but nothing is added to the collection. + mentioned: MTLock>>, + /// Which items are being used where, for better errors. + usage_map: MTLock>, +} + impl<'tcx> UsageMap<'tcx> { fn new() -> UsageMap<'tcx> { UsageMap { used_map: FxHashMap::default(), user_map: FxHashMap::default() } @@ -265,13 +276,15 @@ pub fn collect_crate_mono_items( debug!("building mono item graph, beginning at roots"); - let mut visited = MTLock::new(FxHashSet::default()); - let mut usage_map = MTLock::new(UsageMap::new()); + let mut state = SharedState { + visited: MTLock::new(FxHashSet::default()), + mentioned: MTLock::new(FxHashSet::default()), + usage_map: MTLock::new(UsageMap::new()), + }; let recursion_limit = tcx.recursion_limit(); { - let visited: MTLockRef<'_, _> = &mut visited; - let usage_map: MTLockRef<'_, _> = &mut usage_map; + let state: LRef<'_, _> = &mut state; tcx.sess.time("monomorphization_collector_graph_walk", || { par_for_each_in(roots, |root| { @@ -279,16 +292,15 @@ pub fn collect_crate_mono_items( collect_items_rec( tcx, dummy_spanned(root), - visited, + state, &mut recursion_depths, recursion_limit, - usage_map, ); }); }); } - (visited.into_inner(), usage_map.into_inner()) + (state.visited.into_inner(), state.usage_map.into_inner()) } // Find all non-generic items by walking the HIR. These items serve as roots to @@ -331,21 +343,21 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec( tcx: TyCtxt<'tcx>, starting_item: Spanned>, - visited: MTLockRef<'_, FxHashSet>>, + state: LRef<'_, SharedState<'tcx>>, recursion_depths: &mut DefIdMap, recursion_limit: Limit, - usage_map: MTLockRef<'_, UsageMap<'tcx>>, ) { - if !visited.lock_mut().insert(starting_item.node) { + if !state.visited.lock_mut().insert(starting_item.node) { // We've been here already, no need to search again. return; } - let mut used_items = Vec::new(); + let mut used_items = MonoItems::new(); + let mut mentioned_items = MonoItems::new(); let recursion_depth_reset; // Post-monomorphization errors MVP @@ -373,6 +385,9 @@ fn collect_items_rec<'tcx>( // 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(); + // 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 + // hide const-eval errors that those calls would otherwise have triggered. match starting_item.node { MonoItem::Static(def_id) => { let instance = Instance::mono(tcx, def_id); @@ -404,6 +419,10 @@ fn collect_items_rec<'tcx>( }), )); } + + // mentioned_items stays empty since there's no codegen for statics. statics don't get + // optimized, and if they did then the const-eval interpreter would have to worry about + // mentioned_items. } MonoItem::Fn(instance) => { // Sanity check whether this ended up being collected accidentally @@ -420,7 +439,12 @@ fn collect_items_rec<'tcx>( check_type_length_limit(tcx, instance); rustc_data_structures::stack::ensure_sufficient_stack(|| { - collect_used_items(tcx, instance, &mut used_items); + collect_used_and_mentioned_items( + tcx, + instance, + &mut used_items, + &mut mentioned_items, + ) }); } MonoItem::GlobalAsm(item_id) => { @@ -459,8 +483,10 @@ fn collect_items_rec<'tcx>( } else { span_bug!(item.span, "Mismatch between hir::Item type and MonoItem type") } + + // mention_items stays empty as nothing gets optimized here. } - } + }; // Check for PMEs and emit a diagnostic if one happened. To try to show relevant edges of the // mono item graph. @@ -474,10 +500,16 @@ fn collect_items_rec<'tcx>( formatted_item, }); } - usage_map.lock_mut().record_used(starting_item.node, &used_items); + state.usage_map.lock_mut().record_used(starting_item.node, &used_items); for used_item in used_items { - collect_items_rec(tcx, used_item, visited, recursion_depths, recursion_limit, usage_map); + collect_items_rec(tcx, used_item, state, recursion_depths, recursion_limit); + } + + // Walk over mentioned items *after* used items, so that if an item is both mentioned and used then + // the loop above has fully collected it, so this loop will skip it. + for mentioned_item in mentioned_items { + visit_mentioned_items_rec(tcx, mentioned_item, state, recursion_depths, recursion_limit); } if let Some((def_id, depth)) = recursion_depth_reset { @@ -485,6 +517,78 @@ fn collect_items_rec<'tcx>( } } +/// Visit all mentioned items reachable from the given one, and emit a note diagnostic if a +/// post-monomorphization error is encountered during a collection step. +/// +/// These items do *not* get collected, we just check that their constants all evaluated successfully. +#[instrument(skip(tcx, state, recursion_depths, recursion_limit), level = "debug")] +fn visit_mentioned_items_rec<'tcx>( + tcx: TyCtxt<'tcx>, + starting_item: Spanned>, + state: LRef<'_, SharedState<'tcx>>, + recursion_depths: &mut DefIdMap, + recursion_limit: Limit, +) { + if state.visited.lock().contains(&starting_item.node) { + // We've already done a *full* visit on this one, no need to do the "mention" visit. + return; + } + if !state.mentioned.lock_mut().insert(starting_item.node) { + // We've been here already, no need to search again. + return; + } + // There's some risk that we first do a 'mention' visit and then a full visit. But there's no + // harm in that, the mention visit will trigger all the queries and the results are cached. + + let mut mentioned_items = MonoItems::new(); + + match starting_item.node { + MonoItem::Fn(instance) => { + // Sanity check whether this ended up being collected accidentally + debug_assert!(should_codegen_locally(tcx, &instance)); + + let body = tcx.instance_mir(instance.def); + + // Need to evaluate all constants. + for const_op in &body.required_consts { + let const_ = instance.instantiate_mir_and_normalize_erasing_regions( + tcx, + ty::ParamEnv::reveal_all(), + ty::EarlyBinder::bind(const_op.const_), + ); + match const_.eval(tcx, ty::ParamEnv::reveal_all(), Some(const_op.span)) { + Ok(_) => {} + Err(ErrorHandled::TooGeneric(..)) => span_bug!( + const_op.span, + "collection encountered polymorphic constant: {:?}", + const_ + ), + Err(err @ ErrorHandled::Reported(..)) => { + err.emit_note(tcx); + } + } + } + + // And recurse into the mentioned items. + for item in &body.mentioned_items { + let item_mono = instance.instantiate_mir_and_normalize_erasing_regions( + tcx, + ty::ParamEnv::reveal_all(), + ty::EarlyBinder::bind(item.node), + ); + visit_mentioned_item(tcx, &item_mono, item.span, &mut mentioned_items); + } + } + other => { + bug!("only functions can be encountered during 'mention' collection, but got {other:?}") + } + } + + for mentioned_item in mentioned_items { + visit_mentioned_items_rec(tcx, mentioned_item, state, recursion_depths, recursion_limit); + } +} + /// Format instance name that is already known to be too long for rustc. /// Show only the first 2 types if it is longer than 32 characters to avoid blasting /// the user's terminal with thousands of lines of type-name. @@ -1493,26 +1597,55 @@ fn build_skip_move_check_fns(tcx: TyCtxt<'_>) -> Vec { } /// Scans the MIR in order to find function calls, closures, and drop-glue. -#[instrument(skip(tcx, output), level = "debug")] -fn collect_used_items<'tcx>( +/// +/// Anything that's found is added to `output`. Furthermore the "mentioned items" of the MIR are returned. +#[instrument(skip(tcx, used_items, mentioned_items), level = "debug")] +fn collect_used_and_mentioned_items<'tcx>( tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, - output: &mut MonoItems<'tcx>, + used_items: &mut MonoItems<'tcx>, + mentioned_items: &mut MonoItems<'tcx>, ) { let body = tcx.instance_mir(instance.def); // Here we rely on the visitor also visiting `required_consts`, so that we evaluate them // and abort compilation if any of them errors. - MirUsedCollector { + let mut collector = MirUsedCollector { tcx, body: body, - output, + output: used_items, instance, move_size_spans: vec![], visiting_call_terminator: false, skip_move_check_fns: None, + }; + collector.visit_body(body); + + for item in &body.mentioned_items { + visit_mentioned_item(tcx, &collector.monomorphize(item.node), item.span, mentioned_items); + } +} + +fn visit_mentioned_item<'tcx>( + tcx: TyCtxt<'tcx>, + item: &MentionedItem<'tcx>, + span: Span, + output: &mut MonoItems<'tcx>, +) { + match *item { + MentionedItem::Fn(def_id, args) => { + let instance = Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args); + // `visit_instance_use` was written for "used" item collection but works just as well + // for "mentioned" item collection. + // We can set `is_direct_call`; that just means we'll skip a bunch of shims that anyway + // can't have their own failing constants. + visit_instance_use(tcx, instance, /*is_direct_call*/ true, span, output); + } + MentionedItem::Drop(ty) => { + let instance = Instance::resolve_drop_in_place(tcx, ty); + visit_instance_use(tcx, instance, /*is_direct_call*/ true, span, output); + } } - .visit_body(body); } #[instrument(skip(tcx, output), level = "debug")] diff --git a/tests/ui/consts/required-consts/collect-in-dead-drop.noopt.stderr b/tests/ui/consts/required-consts/collect-in-dead-drop.noopt.stderr index 0bf231d09f174..73790f7517db1 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-drop.noopt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-drop.noopt.stderr @@ -1,13 +1,13 @@ error[E0080]: evaluation of `Fail::::C` failed - --> $DIR/collect-in-dead-drop.rs:12:19 + --> $DIR/collect-in-dead-drop.rs:9:19 | LL | const C: () = panic!(); - | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/collect-in-dead-drop.rs:12:19 + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/collect-in-dead-drop.rs:9:19 | = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered - --> $DIR/collect-in-dead-drop.rs:19:17 + --> $DIR/collect-in-dead-drop.rs:16:17 | LL | let _ = Fail::::C; | ^^^^^^^^^^^^ diff --git a/tests/ui/consts/required-consts/collect-in-dead-drop.opt.stderr b/tests/ui/consts/required-consts/collect-in-dead-drop.opt.stderr new file mode 100644 index 0000000000000..4ae13d6937f6e --- /dev/null +++ b/tests/ui/consts/required-consts/collect-in-dead-drop.opt.stderr @@ -0,0 +1,17 @@ +error[E0080]: evaluation of `Fail::::C` failed + --> $DIR/collect-in-dead-drop.rs:9:19 + | +LL | const C: () = panic!(); + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/collect-in-dead-drop.rs:9:19 + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant encountered + --> $DIR/collect-in-dead-drop.rs:16:17 + | +LL | let _ = Fail::::C; + | ^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. 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 c9ffcec690317..98e9d19189597 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-drop.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-drop.rs @@ -1,15 +1,12 @@ //@revisions: noopt opt -//@[noopt] build-fail +//@ build-fail //@[opt] compile-flags: -O -//FIXME: `opt` revision currently does not stop with an error due to -//. -//@[opt] build-pass //! 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) struct Fail(T); impl Fail { - const C: () = panic!(); //[noopt]~ERROR evaluation of `Fail::::C` failed + const C: () = panic!(); //~ERROR evaluation of `Fail::::C` failed } // This function is not actually called, but is mentioned implicitly as destructor in dead code in a diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn.noopt.stderr b/tests/ui/consts/required-consts/collect-in-dead-fn.noopt.stderr index 8bb99efe8e48d..52462076ff90b 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fn.noopt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-fn.noopt.stderr @@ -1,19 +1,19 @@ error[E0080]: evaluation of `Fail::::C` failed - --> $DIR/collect-in-dead-fn.rs:12:19 + --> $DIR/collect-in-dead-fn.rs:9:19 | LL | const C: () = panic!(); - | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/collect-in-dead-fn.rs:12:19 + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/collect-in-dead-fn.rs:9:19 | = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered - --> $DIR/collect-in-dead-fn.rs:22:17 + --> $DIR/collect-in-dead-fn.rs:19:17 | LL | let _ = Fail::::C; | ^^^^^^^^^^^^ note: the above error was encountered while instantiating `fn not_called::` - --> $DIR/collect-in-dead-fn.rs:29:9 + --> $DIR/collect-in-dead-fn.rs:26:9 | LL | not_called::(); | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn.opt.stderr b/tests/ui/consts/required-consts/collect-in-dead-fn.opt.stderr new file mode 100644 index 0000000000000..34035abebdacb --- /dev/null +++ b/tests/ui/consts/required-consts/collect-in-dead-fn.opt.stderr @@ -0,0 +1,17 @@ +error[E0080]: evaluation of `Fail::::C` failed + --> $DIR/collect-in-dead-fn.rs:9:19 + | +LL | const C: () = panic!(); + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/collect-in-dead-fn.rs:9:19 + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant encountered + --> $DIR/collect-in-dead-fn.rs:19:17 + | +LL | let _ = Fail::::C; + | ^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. 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 9e6b151915331..754fcf7b9874d 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fn.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-fn.rs @@ -1,15 +1,12 @@ //@revisions: noopt opt -//@[noopt] build-fail +//@ build-fail //@[opt] compile-flags: -O -//FIXME: `opt` revision currently does not stop with an error due to -//. -//@[opt] build-pass //! 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) struct Fail(T); impl Fail { - const C: () = panic!(); //[noopt]~ERROR evaluation of `Fail::::C` failed + const C: () = panic!(); //~ERROR evaluation of `Fail::::C` failed } // This function is not actually called, but it is mentioned in dead code in a function that is diff --git a/tests/ui/consts/required-consts/collect-in-dead-move.noopt.stderr b/tests/ui/consts/required-consts/collect-in-dead-move.noopt.stderr index 5b1df78b23265..2ab1f80e2d3b4 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-move.noopt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-move.noopt.stderr @@ -1,13 +1,13 @@ error[E0080]: evaluation of `Fail::::C` failed - --> $DIR/collect-in-dead-move.rs:12:19 + --> $DIR/collect-in-dead-move.rs:9:19 | LL | const C: () = panic!(); - | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/collect-in-dead-move.rs:12:19 + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/collect-in-dead-move.rs:9:19 | = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered - --> $DIR/collect-in-dead-move.rs:19:17 + --> $DIR/collect-in-dead-move.rs:16:17 | LL | let _ = Fail::::C; | ^^^^^^^^^^^^ diff --git a/tests/ui/consts/required-consts/collect-in-dead-move.opt.stderr b/tests/ui/consts/required-consts/collect-in-dead-move.opt.stderr new file mode 100644 index 0000000000000..51b9b993cb2ab --- /dev/null +++ b/tests/ui/consts/required-consts/collect-in-dead-move.opt.stderr @@ -0,0 +1,17 @@ +error[E0080]: evaluation of `Fail::::C` failed + --> $DIR/collect-in-dead-move.rs:9:19 + | +LL | const C: () = panic!(); + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/collect-in-dead-move.rs:9:19 + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant encountered + --> $DIR/collect-in-dead-move.rs:16:17 + | +LL | let _ = Fail::::C; + | ^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. 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 f3a6ba8a6577c..2fd6aea58de65 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-move.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-move.rs @@ -1,15 +1,12 @@ //@revisions: noopt opt -//@[noopt] build-fail +//@ build-fail //@[opt] compile-flags: -O -//FIXME: `opt` revision currently does not stop with an error due to -//. -//@[opt] build-pass //! 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) struct Fail(T); impl Fail { - const C: () = panic!(); //[noopt]~ERROR evaluation of `Fail::::C` failed + const C: () = panic!(); //~ERROR evaluation of `Fail::::C` failed } // This function is not actually called, but is mentioned implicitly as destructor in dead code in a