diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 956a024fa4dc3..2f807ba9b7188 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -43,7 +43,7 @@ pub(crate) fn codegen_fn<'tcx>( let symbol_name = tcx.symbol_name(instance).name.to_string(); let _timer = tcx.prof.generic_activity_with_arg("codegen fn", &*symbol_name); - let mir = tcx.instance_mir(instance.def); + let mir = tcx.codegen_mir(instance); let _mir_guard = crate::PrintOnPanic(|| { let mut buf = Vec::new(); with_no_trimmed_paths!({ @@ -305,19 +305,10 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { .generic_activity("codegen prelude") .run(|| crate::abi::codegen_fn_prelude(fx, start_block)); - let reachable_blocks = traversal::mono_reachable_as_bitset(fx.mir, fx.tcx, fx.instance); - for (bb, bb_data) in fx.mir.basic_blocks.iter_enumerated() { let block = fx.get_block(bb); fx.bcx.switch_to_block(block); - if !reachable_blocks.contains(bb) { - // We want to skip this block, because it's not reachable. But we still create - // the block so terminators in other blocks can reference it. - fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap()); - continue; - } - if bb_data.is_cleanup { // Unwinding after panicking is not supported continue; diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 544578b29f107..b8615cba477b2 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -417,7 +417,7 @@ pub(crate) fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( // release builds. info!("codegen_instance({})", instance); - mir::codegen_mir::(cx, instance); + mir::lower_mir::(cx, instance); } /// Creates the `main` function which will initialize the rust runtime and call diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index b0a1dedd646b0..7881df0ec3459 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1261,16 +1261,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } - pub(crate) fn codegen_block_as_unreachable(&mut self, bb: mir::BasicBlock) { - let llbb = match self.try_llbb(bb) { - Some(llbb) => llbb, - None => return, - }; - let bx = &mut Bx::build(self.cx, llbb); - debug!("codegen_block_as_unreachable({:?})", bb); - bx.unreachable(); - } - fn codegen_terminator( &mut self, bx: &mut Bx, diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 3a896071bc6b8..46d0ed052444e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -4,7 +4,7 @@ use rustc_index::IndexVec; use rustc_index::bit_set::DenseBitSet; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::{UnwindTerminateReason, traversal}; -use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, TyAndLayout}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_middle::{bug, mir, span_bug}; use rustc_target::callconv::{FnAbi, PassMode}; @@ -126,12 +126,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { where T: Copy + TypeFoldable>, { - debug!("monomorphize: self.instance={:?}", self.instance); - self.instance.instantiate_mir_and_normalize_erasing_regions( - self.cx.tcx(), - self.cx.typing_env(), - ty::EarlyBinder::bind(value), - ) + value } } @@ -164,7 +159,7 @@ impl<'tcx, V: CodegenObject> LocalRef<'tcx, V> { /////////////////////////////////////////////////////////////////////////// #[instrument(level = "debug", skip(cx))] -pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( +pub fn lower_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, instance: Instance<'tcx>, ) { @@ -172,7 +167,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let llfn = cx.get_fn(instance); - let mir = cx.tcx().instance_mir(instance.def); + let mir = cx.tcx().codegen_mir(instance); let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty()); debug!("fn_abi: {:?}", fn_abi); @@ -233,7 +228,8 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fx.compute_per_local_var_debug_info(&mut start_bx).unzip(); fx.per_local_var_debug_info = per_local_var_debug_info; - let traversal_order = traversal::mono_reachable_reverse_postorder(mir, cx.tcx(), instance); + let traversal_order: Vec<_> = + traversal::reverse_postorder(mir).map(|(block, _data)| block).collect(); let memory_locals = analyze::non_ssa_locals(&fx, &traversal_order); // Allocate variable and temp allocas @@ -293,20 +289,9 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // So drop the builder of `start_llbb` to avoid having two at the same time. drop(start_bx); - let mut unreached_blocks = DenseBitSet::new_filled(mir.basic_blocks.len()); // Codegen the body of each reachable block using our reverse postorder list. for bb in traversal_order { fx.codegen_block(bb); - unreached_blocks.remove(bb); - } - - // FIXME: These empty unreachable blocks are *mostly* a waste. They are occasionally - // targets for a SwitchInt terminator, but the reimplementation of the mono-reachable - // simplification in SwitchInt lowering sometimes misses cases that - // mono_reachable_reverse_postorder manages to figure out. - // The solution is to do something like post-mono GVN. But for now we have this hack. - for bb in unreached_blocks.iter() { - fx.codegen_block_as_unreachable(bb); } } diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs index 3eb563d7d6e57..f329dab1f39b9 100644 --- a/compiler/rustc_middle/src/mir/basic_blocks.rs +++ b/compiler/rustc_middle/src/mir/basic_blocks.rs @@ -64,7 +64,7 @@ impl<'tcx> BasicBlocks<'tcx> { #[inline] pub fn reverse_postorder(&self) -> &[BasicBlock] { self.cache.reverse_postorder.get_or_init(|| { - let mut rpo: Vec<_> = Postorder::new(&self.basic_blocks, START_BLOCK, ()).collect(); + let mut rpo: Vec<_> = Postorder::new(&self.basic_blocks, START_BLOCK).collect(); rpo.reverse(); rpo }) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index bbb8bdce4a0ca..0a7405e5dbadb 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -38,7 +38,7 @@ use crate::ty::fold::{FallibleTypeFolder, TypeFoldable}; use crate::ty::print::{FmtPrinter, Printer, pretty_print_const, with_no_trimmed_paths}; use crate::ty::visit::TypeVisitableExt; use crate::ty::{ - self, AdtDef, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt, TypingEnv, + self, AdtDef, GenericArg, GenericArgsRef, InstanceKind, List, Ty, TyCtxt, TypingEnv, UserTypeAnnotationIndex, }; @@ -618,74 +618,6 @@ impl<'tcx> Body<'tcx> { self.injection_phase.is_some() } - /// If this basic block ends with a [`TerminatorKind::SwitchInt`] for which we can evaluate the - /// discriminant in monomorphization, we return the discriminant bits and the - /// [`SwitchTargets`], just so the caller doesn't also have to match on the terminator. - fn try_const_mono_switchint<'a>( - tcx: TyCtxt<'tcx>, - instance: Instance<'tcx>, - block: &'a BasicBlockData<'tcx>, - ) -> Option<(u128, &'a SwitchTargets)> { - // There are two places here we need to evaluate a constant. - let eval_mono_const = |constant: &ConstOperand<'tcx>| { - // FIXME(#132279): what is this, why are we using an empty environment here. - let typing_env = ty::TypingEnv::fully_monomorphized(); - let mono_literal = instance.instantiate_mir_and_normalize_erasing_regions( - tcx, - typing_env, - crate::ty::EarlyBinder::bind(constant.const_), - ); - mono_literal.try_eval_bits(tcx, typing_env) - }; - - let TerminatorKind::SwitchInt { discr, targets } = &block.terminator().kind else { - return None; - }; - - // If this is a SwitchInt(const _), then we can just evaluate the constant and return. - let discr = match discr { - Operand::Constant(constant) => { - let bits = eval_mono_const(constant)?; - return Some((bits, targets)); - } - Operand::Move(place) | Operand::Copy(place) => place, - }; - - // MIR for `if false` actually looks like this: - // _1 = const _ - // SwitchInt(_1) - // - // And MIR for if intrinsics::ub_checks() looks like this: - // _1 = UbChecks() - // SwitchInt(_1) - // - // So we're going to try to recognize this pattern. - // - // If we have a SwitchInt on a non-const place, we find the most recent statement that - // isn't a storage marker. If that statement is an assignment of a const to our - // discriminant place, we evaluate and return the const, as if we've const-propagated it - // into the SwitchInt. - - let last_stmt = block.statements.iter().rev().find(|stmt| { - !matches!(stmt.kind, StatementKind::StorageDead(_) | StatementKind::StorageLive(_)) - })?; - - let (place, rvalue) = last_stmt.kind.as_assign()?; - - if discr != place { - return None; - } - - match rvalue { - Rvalue::NullaryOp(NullOp::UbChecks, _) => Some((tcx.sess.ub_checks() as u128, targets)), - Rvalue::Use(Operand::Constant(constant)) => { - let bits = eval_mono_const(constant)?; - Some((bits, targets)) - } - _ => None, - } - } - /// For a `Location` in this scope, determine what the "caller location" at that point is. This /// is interesting because of inlining: the `#[track_caller]` attribute of inlined functions /// must be honored. Falls back to the `tracked_caller` value for `#[track_caller]` functions, @@ -1435,19 +1367,6 @@ impl<'tcx> BasicBlockData<'tcx> { pub fn is_empty_unreachable(&self) -> bool { self.statements.is_empty() && matches!(self.terminator().kind, TerminatorKind::Unreachable) } - - /// Like [`Terminator::successors`] but tries to use information available from the [`Instance`] - /// to skip successors like the `false` side of an `if const {`. - /// - /// This is used to implement [`traversal::mono_reachable`] and - /// [`traversal::mono_reachable_reverse_postorder`]. - pub fn mono_successors(&self, tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Successors<'_> { - if let Some((bits, targets)) = Body::try_const_mono_switchint(tcx, instance, self) { - targets.successors_for_value(bits) - } else { - self.terminator().successors() - } - } } /////////////////////////////////////////////////////////////////////////// diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs index 0e7dcc24dafa6..2d4fd252a7a12 100644 --- a/compiler/rustc_middle/src/mir/traversal.rs +++ b/compiler/rustc_middle/src/mir/traversal.rs @@ -104,29 +104,23 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> { /// ``` /// /// A Postorder traversal of this graph is `D B C A` or `D C B A` -pub struct Postorder<'a, 'tcx, C> { +pub struct Postorder<'a, 'tcx> { basic_blocks: &'a IndexSlice>, visited: DenseBitSet, visit_stack: Vec<(BasicBlock, Successors<'a>)>, root_is_start_block: bool, - extra: C, } -impl<'a, 'tcx, C> Postorder<'a, 'tcx, C> -where - C: Customization<'tcx>, -{ +impl<'a, 'tcx> Postorder<'a, 'tcx> { pub fn new( basic_blocks: &'a IndexSlice>, root: BasicBlock, - extra: C, - ) -> Postorder<'a, 'tcx, C> { + ) -> Postorder<'a, 'tcx> { let mut po = Postorder { basic_blocks, visited: DenseBitSet::new_empty(basic_blocks.len()), visit_stack: Vec::new(), root_is_start_block: root == START_BLOCK, - extra, }; po.visit(root); @@ -140,7 +134,7 @@ where return; } let data = &self.basic_blocks[bb]; - let successors = C::successors(data, self.extra); + let successors = data.terminator().successors(); self.visit_stack.push((bb, successors)); } @@ -198,10 +192,7 @@ where } } -impl<'tcx, C> Iterator for Postorder<'_, 'tcx, C> -where - C: Customization<'tcx>, -{ +impl<'tcx> Iterator for Postorder<'_, 'tcx> { type Item = BasicBlock; fn next(&mut self) -> Option { @@ -252,29 +243,6 @@ impl<'tcx> Customization<'tcx> for () { } } -impl<'tcx> Customization<'tcx> for (TyCtxt<'tcx>, Instance<'tcx>) { - fn successors<'a>( - data: &'a BasicBlockData<'tcx>, - (tcx, instance): (TyCtxt<'tcx>, Instance<'tcx>), - ) -> Successors<'a> { - data.mono_successors(tcx, instance) - } -} - -pub fn mono_reachable_reverse_postorder<'a, 'tcx>( - body: &'a Body<'tcx>, - tcx: TyCtxt<'tcx>, - instance: Instance<'tcx>, -) -> Vec { - let mut iter = Postorder::new(&body.basic_blocks, START_BLOCK, (tcx, instance)); - let mut items = Vec::with_capacity(body.basic_blocks.len()); - while let Some(block) = iter.next() { - items.push(block); - } - items.reverse(); - items -} - /// Returns an iterator over all basic blocks reachable from the `START_BLOCK` in no particular /// order. /// @@ -322,91 +290,3 @@ pub fn reverse_postorder<'a, 'tcx>( { body.basic_blocks.reverse_postorder().iter().map(|&bb| (bb, &body.basic_blocks[bb])) } - -/// Traversal of a [`Body`] that tries to avoid unreachable blocks in a monomorphized [`Instance`]. -/// -/// This is allowed to have false positives; blocks may be visited even if they are not actually -/// reachable. -/// -/// Such a traversal is mostly useful because it lets us skip lowering the `false` side -/// of `if ::CONST`, as well as [`NullOp::UbChecks`]. -/// -/// [`NullOp::UbChecks`]: rustc_middle::mir::NullOp::UbChecks -pub fn mono_reachable<'a, 'tcx>( - body: &'a Body<'tcx>, - tcx: TyCtxt<'tcx>, - instance: Instance<'tcx>, -) -> MonoReachable<'a, 'tcx> { - MonoReachable::new(body, tcx, instance) -} - -/// [`MonoReachable`] internally accumulates a [`DenseBitSet`] of visited blocks. This is just a -/// convenience function to run that traversal then extract its set of reached blocks. -pub fn mono_reachable_as_bitset<'a, 'tcx>( - body: &'a Body<'tcx>, - tcx: TyCtxt<'tcx>, - instance: Instance<'tcx>, -) -> DenseBitSet { - let mut iter = mono_reachable(body, tcx, instance); - while let Some(_) = iter.next() {} - iter.visited -} - -pub struct MonoReachable<'a, 'tcx> { - body: &'a Body<'tcx>, - tcx: TyCtxt<'tcx>, - instance: Instance<'tcx>, - visited: DenseBitSet, - // Other traversers track their worklist in a Vec. But we don't care about order, so we can - // store ours in a DenseBitSet and thus save allocations because DenseBitSet has a small size - // optimization. - worklist: DenseBitSet, -} - -impl<'a, 'tcx> MonoReachable<'a, 'tcx> { - pub fn new( - body: &'a Body<'tcx>, - tcx: TyCtxt<'tcx>, - instance: Instance<'tcx>, - ) -> MonoReachable<'a, 'tcx> { - let mut worklist = DenseBitSet::new_empty(body.basic_blocks.len()); - worklist.insert(START_BLOCK); - MonoReachable { - body, - tcx, - instance, - visited: DenseBitSet::new_empty(body.basic_blocks.len()), - worklist, - } - } - - fn add_work(&mut self, blocks: impl IntoIterator) { - for block in blocks.into_iter() { - if !self.visited.contains(block) { - self.worklist.insert(block); - } - } - } -} - -impl<'a, 'tcx> Iterator for MonoReachable<'a, 'tcx> { - type Item = (BasicBlock, &'a BasicBlockData<'tcx>); - - fn next(&mut self) -> Option<(BasicBlock, &'a BasicBlockData<'tcx>)> { - while let Some(idx) = self.worklist.iter().next() { - self.worklist.remove(idx); - if !self.visited.insert(idx) { - continue; - } - - let data = &self.body[idx]; - - let targets = data.mono_successors(self.tcx, self.instance); - self.add_work(targets); - - return Some((idx, data)); - } - - None - } -} diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 7d334847d44b1..44b649b4a8194 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -597,14 +597,21 @@ rustc_queries! { desc { |tcx| "verify auto trait bounds for coroutine interior type `{}`", tcx.def_path_str(key) } } - /// MIR after our optimization passes have run. This is MIR that is ready - /// for codegen. This is also the only query that can fetch non-local MIR, at present. + /// Polymorphic MIR after our pre-mono optimization passes have run. This is the MIR that + /// crates export. query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> { desc { |tcx| "optimizing MIR for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern } + /// MIR for a specific Instance ready for codegen. This is `optimized_mir` but monomorphized + /// and with extra transforms applied. + query build_codegen_mir(key: ty::Instance<'tcx>) -> &'tcx mir::Body<'tcx> { + desc { |tcx| "finalizing codegen MIR for `{}`", tcx.def_path_str_with_args(key.def_id(), key.args) } + arena_cache + } + /// Checks for the nearest `#[coverage(off)]` or `#[coverage(on)]` on /// this def and any enclosing defs, up to the crate root. /// diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 2d69386176b80..d4dee87dd0893 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1709,6 +1709,10 @@ impl<'tcx> TyCtxt<'tcx> { } } + pub fn codegen_mir(self, instance: ty::Instance<'tcx>) -> &'tcx Body<'tcx> { + self.build_codegen_mir(instance) + } + /// Returns the possibly-auto-generated MIR of a [`ty::InstanceKind`]. #[instrument(skip(self), level = "debug")] pub fn instance_mir(self, instance: ty::InstanceKind<'tcx>) -> &'tcx Body<'tcx> { diff --git a/compiler/rustc_mir_transform/messages.ftl b/compiler/rustc_mir_transform/messages.ftl index b0c023cca8242..2596e3834d52f 100644 --- a/compiler/rustc_mir_transform/messages.ftl +++ b/compiler/rustc_mir_transform/messages.ftl @@ -1,6 +1,23 @@ +mir_transform_abi_error_disabled_vector_type_call = + this function call uses a SIMD vector type that (with the chosen ABI) requires the `{$required_feature}` target feature, which is not enabled in the caller + .label = function called here + .help = consider enabling it globally (`-C target-feature=+{$required_feature}`) or locally (`#[target_feature(enable="{$required_feature}")]`) +mir_transform_abi_error_disabled_vector_type_def = + this function definition uses a SIMD vector type that (with the chosen ABI) requires the `{$required_feature}` target feature, which is not enabled + .label = function defined here + .help = consider enabling it globally (`-C target-feature=+{$required_feature}`) or locally (`#[target_feature(enable="{$required_feature}")]`) + +mir_transform_abi_error_unsupported_vector_type_call = + this function call uses a SIMD vector type that is not currently supported with the chosen ABI + .label = function called here +mir_transform_abi_error_unsupported_vector_type_def = + this function definition uses a SIMD vector type that is not currently supported with the chosen ABI + .label = function defined here + mir_transform_arithmetic_overflow = this arithmetic operation will overflow mir_transform_const_defined_here = `const` item defined here + mir_transform_const_modify = attempting to modify a `const` item .note = each usage of a `const` item creates a new temporary; the original `const` item will not be modified @@ -30,6 +47,11 @@ mir_transform_force_inline = mir_transform_force_inline_justification = `{$callee}` is required to be inlined to: {$sym} +mir_transform_large_assignments = + moving {$size} bytes + .label = value moved from here + .note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` + mir_transform_must_not_suspend = {$pre}`{$def_path}`{$post} held across a suspend point, but should not be .label = the value is held across this suspend point .note = {$reason} diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 015633d145f15..44f1dc05291b7 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -95,6 +95,16 @@ pub(crate) struct FnItemRef { pub ident: String, } +#[derive(LintDiagnostic)] +#[diag(mir_transform_large_assignments)] +#[note] +pub(crate) struct LargeAssignmentsLint { + #[label] + pub span: Span, + pub size: u64, + pub limit: u64, +} + #[derive(Diagnostic)] #[diag(mir_transform_exceeds_mcdc_test_vector_limit)] pub(crate) struct MCDCExceedsTestVectorLimit { @@ -168,3 +178,35 @@ pub(crate) struct ForceInlineFailure { pub(crate) struct ForceInlineJustification { pub sym: Symbol, } + +#[derive(LintDiagnostic)] +#[diag(mir_transform_abi_error_disabled_vector_type_def)] +#[help] +pub(crate) struct AbiErrorDisabledVectorTypeDef<'a> { + #[label] + pub span: Span, + pub required_feature: &'a str, +} + +#[derive(LintDiagnostic)] +#[diag(mir_transform_abi_error_disabled_vector_type_call)] +#[help] +pub(crate) struct AbiErrorDisabledVectorTypeCall<'a> { + #[label] + pub span: Span, + pub required_feature: &'a str, +} + +#[derive(LintDiagnostic)] +#[diag(mir_transform_abi_error_unsupported_vector_type_def)] +pub(crate) struct AbiErrorUnsupportedVectorTypeDef { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(mir_transform_abi_error_unsupported_vector_type_call)] +pub(crate) struct AbiErrorUnsupportedVectorTypeCall { + #[label] + pub span: Span, +} diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index affc4cf0afc31..6ff311401c1d9 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -86,6 +86,7 @@ use std::borrow::Cow; use either::Either; use rustc_abi::{self as abi, BackendRepr, FIRST_VARIANT, FieldIdx, Primitive, Size, VariantIdx}; +use rustc_ast::attr; use rustc_const_eval::const_eval::DummyMachine; use rustc_const_eval::interpret::{ ImmTy, Immediate, InterpCx, MemPlaceMeta, MemoryKind, OpTy, Projectable, Scalar, @@ -102,30 +103,62 @@ use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::DUMMY_SP; use rustc_span::def_id::DefId; +use rustc_span::{DUMMY_SP, sym}; use smallvec::SmallVec; use tracing::{debug, instrument, trace}; use crate::ssa::{AssignedValue, SsaLocals}; -pub(super) struct GVN; +pub(super) enum GVN { + Polymorphic, + PostMono, +} impl<'tcx> crate::MirPass<'tcx> for GVN { + fn name(&self) -> &'static str { + match self { + GVN::Polymorphic => "GVN", + GVN::PostMono => "GVN-post-mono", + } + } + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() >= 2 + let threshold = match self { + GVN::Polymorphic => 2, + GVN::PostMono => 1, + }; + sess.mir_opt_level() >= threshold } #[instrument(level = "trace", skip(self, tcx, body))] fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!(def_id = ?body.source.def_id()); - let typing_env = body.typing_env(tcx); + let typing_env = match self { + GVN::Polymorphic => body.typing_env(tcx), + GVN::PostMono => ty::TypingEnv::fully_monomorphized(), + }; let ssa = SsaLocals::new(tcx, body, typing_env); // Clone dominators because we need them while mutating the body. let dominators = body.basic_blocks.dominators().clone(); - let mut state = VnState::new(tcx, body, typing_env, &ssa, dominators, &body.local_decls); + let preserve_ub_checks = match self { + GVN::Polymorphic => { + attr::contains_name(tcx.hir().krate_attrs(), sym::rustc_preserve_ub_checks) + } + GVN::PostMono => false, + }; + + let mut state = VnState::new( + tcx, + body, + typing_env, + &ssa, + dominators, + &body.local_decls, + preserve_ub_checks, + ); ssa.for_each_assignment_mut( body.basic_blocks.as_mut_preserves_cfg(), |local, value, location| { @@ -257,6 +290,7 @@ struct VnState<'body, 'tcx> { ssa: &'body SsaLocals, dominators: Dominators, reused_locals: DenseBitSet, + preserve_ub_checks: bool, } impl<'body, 'tcx> VnState<'body, 'tcx> { @@ -267,6 +301,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { ssa: &'body SsaLocals, dominators: Dominators, local_decls: &'body LocalDecls<'tcx>, + preserve_ub_checks: bool, ) -> Self { // Compute a rough estimate of the number of values in the body from the number of // statements. This is meant to reduce the number of allocations, but it's all right if @@ -288,6 +323,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { ssa, dominators, reused_locals: DenseBitSet::new_empty(local_decls.len()), + preserve_ub_checks, } } @@ -526,7 +562,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { .tcx .offset_of_subfield(self.typing_env(), layout, fields.iter()) .bytes(), - NullOp::UbChecks => return None, + NullOp::UbChecks => { + if self.preserve_ub_checks { + return None; + } else { + let val = ImmTy::from_bool(self.tcx.sess.ub_checks(), self.tcx); + return Some(val.into()); + } + } }; let usize_layout = self.ecx.layout_of(self.tcx.types.usize).unwrap(); let imm = ImmTy::from_uint(val, usize_layout); diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 20e2e3e8ba2c1..8001df3157116 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -15,6 +15,7 @@ use crate::take_array; pub(super) enum InstSimplify { BeforeInline, AfterSimplifyCfg, + PostMono, } impl<'tcx> crate::MirPass<'tcx> for InstSimplify { @@ -22,6 +23,7 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { match self { InstSimplify::BeforeInline => "InstSimplify-before-inline", InstSimplify::AfterSimplifyCfg => "InstSimplify-after-simplifycfg", + InstSimplify::PostMono => "InstSimplify-post-mono", } } @@ -30,13 +32,18 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let ctx = InstSimplifyContext { - tcx, - local_decls: &body.local_decls, - typing_env: body.typing_env(tcx), + let typing_env = if matches!(*self, InstSimplify::PostMono) { + ty::TypingEnv::fully_monomorphized() + } else { + body.typing_env(tcx) + }; + let ctx = InstSimplifyContext { tcx, local_decls: &body.local_decls, typing_env }; + let preserve_ub_checks = match self { + InstSimplify::PostMono => false, + InstSimplify::BeforeInline | InstSimplify::AfterSimplifyCfg => { + attr::contains_name(tcx.hir().krate_attrs(), sym::rustc_preserve_ub_checks) + } }; - let preserve_ub_checks = - attr::contains_name(tcx.hir().krate_attrs(), sym::rustc_preserve_ub_checks); for block in body.basic_blocks.as_mut() { for statement in block.statements.iter_mut() { match statement.kind { @@ -51,6 +58,29 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { ctx.simplify_repeated_aggregate(rvalue); ctx.simplify_repeat_once(rvalue); } + StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(ref op)) => { + // UnreachablePropagation likes to generate this MIR: + // + // _1 = UbChecks(); + // assume(copy _1); + // _2 = unreachable_unchecked::precondition_check() -> [return: bb2, unwind unreachable]; + // + // Which is mind-bending but correct. When UbChecks is false, we + // assume(false) which is unreachable, and we never hit the precondition + // check. When UbChecks is true, we assume(true) and fall through to the + // precondition check. + // + // So the branch on UbChecks is implicit, which is both clever and makes + // the rest of MIR optimizations unable to delete this precondition check + // call when UB checks are off. + if let Some(ConstOperand { const_, .. }) = op.constant() { + if let Some(false) = const_.try_to_bool() { + block.statements.clear(); + block.terminator_mut().kind = TerminatorKind::Unreachable; + break; + } + } + } _ => {} } } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 350929ffaa508..932ecaf366a03 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -29,7 +29,7 @@ use rustc_middle::mir::{ MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, START_BLOCK, SourceInfo, Statement, StatementKind, TerminatorKind, }; -use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitableExt}; use rustc_middle::util::Providers; use rustc_middle::{bug, query, span_bug}; use rustc_span::source_map::Spanned; @@ -51,6 +51,7 @@ mod errors; mod ffi_unwind_calls; mod lint; mod lint_tail_expr_drop_order; +mod mono_checks; mod shim; mod ssa; @@ -138,11 +139,14 @@ declare_passes! { mod elaborate_box_derefs : ElaborateBoxDerefs; mod elaborate_drops : ElaborateDrops; mod function_item_references : FunctionItemReferences; - mod gvn : GVN; + mod gvn : GVN { + Polymorphic, + PostMono + }; // Made public so that `mir_drops_elaborated_and_const_checked` can be overridden // by custom rustc drivers, running all the steps by themselves. See #114628. pub mod inline : Inline, ForceInline; - mod instsimplify : InstSimplify { BeforeInline, AfterSimplifyCfg }; + mod instsimplify : InstSimplify { BeforeInline, AfterSimplifyCfg, PostMono }; mod jump_threading : JumpThreading; mod known_panics_lint : KnownPanicsLint; mod large_enums : EnumSizeOpt; @@ -175,7 +179,8 @@ declare_passes! { PreOptimizations, Final, MakeShim, - AfterUnreachableEnumBranching + AfterUnreachableEnumBranching, + PostMono }, SimplifyLocals { BeforeConstProp, @@ -184,7 +189,8 @@ declare_passes! { }; mod simplify_branches : SimplifyConstCondition { AfterConstProp, - Final + Final, + PostMono }; mod simplify_comparison_integral : SimplifyComparisonIntegral; mod single_use_consts : SingleUseConsts; @@ -202,6 +208,7 @@ pub fn provide(providers: &mut Providers) { ffi_unwind_calls::provide(providers); shim::provide(providers); cross_crate_inline::provide(providers); + mono_checks::provide(providers); providers.queries = query::Providers { mir_keys, mir_built, @@ -218,6 +225,7 @@ pub fn provide(providers: &mut Providers) { promoted_mir, deduced_param_attrs: deduce_param_attrs::deduced_param_attrs, coroutine_by_move_body_def_id: coroutine::coroutine_by_move_body_def_id, + build_codegen_mir, ..providers.queries }; } @@ -646,11 +654,11 @@ fn run_runtime_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { } } -fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - fn o1(x: T) -> WithMinOptLevel { - WithMinOptLevel(1, x) - } +fn o1(x: T) -> WithMinOptLevel { + WithMinOptLevel(1, x) +} +fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // The main optimizations that we do on MIR. pm::run_passes( tcx, @@ -693,7 +701,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &instsimplify::InstSimplify::AfterSimplifyCfg, &simplify::SimplifyLocals::BeforeConstProp, &dead_store_elimination::DeadStoreElimination::Initial, - &gvn::GVN, + &gvn::GVN::Polymorphic, &simplify::SimplifyLocals::AfterGVN, &dataflow_const_prop::DataflowConstProp, &single_use_consts::SingleUseConsts, @@ -714,12 +722,9 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &multiple_return_terminators::MultipleReturnTerminators, &deduplicate_blocks::DeduplicateBlocks, &large_enums::EnumSizeOpt { discrepancy: 128 }, - // Some cleanup necessary at least for LLVM and potentially other codegen backends. - &add_call_guards::CriticalCallEdges, // Cleanup for human readability, off by default. &prettify::ReorderBasicBlocks, &prettify::ReorderLocals, - // Dump the end result for testing and debugging purposes. &dump_mir::Marker("PreCodegen"), ], Some(MirPhase::Runtime(RuntimePhase::Optimized)), @@ -775,6 +780,36 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> { body } +pub fn build_codegen_mir<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Body<'tcx> { + let body = tcx.instance_mir(instance.def); + let mut body = instance.instantiate_mir_and_normalize_erasing_regions( + tcx, + ty::TypingEnv::fully_monomorphized(), + ty::EarlyBinder::bind(body.clone()), + ); + + pm::run_passes_no_validate( + tcx, + &mut body, + &[ + &gvn::GVN::PostMono, + // FIXME: Enabling this InstSimplify is required to fix the MIR from the + // unreachable_unchecked precondition check that UnreachablePropagation creates, but + // also enabling it breaks tests/codegen/issues/issue-122600-ptr-discriminant-update.rs + // LLVM appears to handle switches on i64 better than it handles icmp eq + br. + &instsimplify::InstSimplify::PostMono, + &o1(simplify_branches::SimplifyConstCondition::PostMono), + &o1(simplify::SimplifyCfg::PostMono), + &add_call_guards::CriticalCallEdges, + ], + None, + ); + + mono_checks::check_mono_item(tcx, instance, &body); + + body +} + /// Fetch all the promoteds of an item and prepare their MIR bodies to be ready for /// constant evaluation once all generic parameters become known. fn promoted_mir(tcx: TyCtxt<'_>, def: LocalDefId) -> &IndexVec> { diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_mir_transform/src/mono_checks/abi_check.rs similarity index 97% rename from compiler/rustc_monomorphize/src/mono_checks/abi_check.rs rename to compiler/rustc_mir_transform/src/mono_checks/abi_check.rs index 30e634d825276..d7e57f97e3e04 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs +++ b/compiler/rustc_mir_transform/src/mono_checks/abi_check.rs @@ -1,7 +1,7 @@ //! This module ensures that if a function's ABI requires a particular target feature, //! that target feature is enabled both on the callee and all callers. use rustc_hir::CRATE_HIR_ID; -use rustc_middle::mir::{self, traversal}; +use rustc_middle::mir::{self}; use rustc_middle::ty::inherent::*; use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt}; use rustc_session::lint::builtin::ABI_UNSUPPORTED_VECTOR_TYPES; @@ -144,7 +144,7 @@ fn check_call_site_abi<'tcx>( fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &mir::Body<'tcx>) { // Check all function call terminators. - for (bb, _data) in traversal::mono_reachable(body, tcx, instance) { + for (bb, _data) in body.basic_blocks.iter_enumerated() { let terminator = body.basic_blocks[bb].terminator(); match terminator.kind { mir::TerminatorKind::Call { ref func, ref fn_span, .. } @@ -165,7 +165,7 @@ fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &m pub(crate) fn check_feature_dependent_abi<'tcx>( tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, - body: &'tcx mir::Body<'tcx>, + body: &mir::Body<'tcx>, ) { check_instance_abi(tcx, instance); check_callees_abi(tcx, instance, body); diff --git a/compiler/rustc_monomorphize/src/mono_checks/mod.rs b/compiler/rustc_mir_transform/src/mono_checks/mod.rs similarity index 66% rename from compiler/rustc_monomorphize/src/mono_checks/mod.rs rename to compiler/rustc_mir_transform/src/mono_checks/mod.rs index 1ecda824fb8c2..9dedee9900c94 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/mod.rs +++ b/compiler/rustc_mir_transform/src/mono_checks/mod.rs @@ -2,22 +2,22 @@ //! monomorphization of all functions. This lets us implement monomorphization-time //! checks in a way that is friendly to incremental compilation. +use rustc_middle::mir::Body; use rustc_middle::query::Providers; use rustc_middle::ty::{Instance, TyCtxt}; mod abi_check; mod move_check; -fn check_mono_item<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { - let body = tcx.instance_mir(instance.def); +pub(crate) fn check_mono_item<'tcx>( + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, + body: &Body<'tcx>, +) { abi_check::check_feature_dependent_abi(tcx, instance, body); move_check::check_moves(tcx, instance, body); } pub(super) fn provide(providers: &mut Providers) { - *providers = Providers { - check_mono_item, - skip_move_check_fns: move_check::skip_move_check_fns, - ..*providers - } + *providers = Providers { skip_move_check_fns: move_check::skip_move_check_fns, ..*providers } } diff --git a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs b/compiler/rustc_mir_transform/src/mono_checks/move_check.rs similarity index 95% rename from compiler/rustc_monomorphize/src/mono_checks/move_check.rs rename to compiler/rustc_mir_transform/src/mono_checks/move_check.rs index 02b9397f9a995..43e32d40d671d 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs +++ b/compiler/rustc_mir_transform/src/mono_checks/move_check.rs @@ -2,7 +2,7 @@ use rustc_abi::Size; use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def_id::DefId; use rustc_middle::mir::visit::Visitor as MirVisitor; -use rustc_middle::mir::{self, Location, traversal}; +use rustc_middle::mir::{self, Location}; use rustc_middle::ty::{self, AssocKind, Instance, Ty, TyCtxt, TypeFoldable}; use rustc_session::Limit; use rustc_session::lint::builtin::LARGE_ASSIGNMENTS; @@ -12,10 +12,10 @@ use tracing::{debug, trace}; use crate::errors::LargeAssignmentsLint; -struct MoveCheckVisitor<'tcx> { +struct MoveCheckVisitor<'body, 'tcx> { tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, - body: &'tcx mir::Body<'tcx>, + body: &'body mir::Body<'tcx>, /// Spans for move size lints already emitted. Helps avoid duplicate lints. move_size_spans: Vec, } @@ -23,15 +23,15 @@ struct MoveCheckVisitor<'tcx> { pub(crate) fn check_moves<'tcx>( tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, - body: &'tcx mir::Body<'tcx>, + body: &mir::Body<'tcx>, ) { let mut visitor = MoveCheckVisitor { tcx, instance, body, move_size_spans: vec![] }; - for (bb, data) in traversal::mono_reachable(body, tcx, instance) { + for (bb, data) in body.basic_blocks.iter_enumerated() { visitor.visit_basic_block_data(bb, data) } } -impl<'tcx> MirVisitor<'tcx> for MoveCheckVisitor<'tcx> { +impl<'body, 'tcx> MirVisitor<'tcx> for MoveCheckVisitor<'body, 'tcx> { fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) { match terminator.kind { mir::TerminatorKind::Call { ref func, ref args, ref fn_span, .. } @@ -52,7 +52,7 @@ impl<'tcx> MirVisitor<'tcx> for MoveCheckVisitor<'tcx> { } } -impl<'tcx> MoveCheckVisitor<'tcx> { +impl<'body, 'tcx> MoveCheckVisitor<'body, 'tcx> { fn monomorphize(&self, value: T) -> T where T: TypeFoldable>, diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index c3f0a989ce105..8c436ec7483ee 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -288,7 +288,7 @@ fn run_passes_inner<'tcx>( let validate = (validate_each & tcx.sess.opts.unstable_opts.validate_mir & !body.should_skip()) - || new_phase == MirPhase::Runtime(RuntimePhase::Optimized); + || matches!(new_phase, MirPhase::Runtime(RuntimePhase::Optimized)); let lint = tcx.sess.opts.unstable_opts.lint_mir & !body.should_skip(); if validate { validate_body(tcx, body, format!("after phase change to {}", new_phase.name())); diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 4f312ed2aaabc..2d444d7128d32 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -47,6 +47,7 @@ pub(super) enum SimplifyCfg { Final, MakeShim, AfterUnreachableEnumBranching, + PostMono, } impl SimplifyCfg { @@ -62,6 +63,7 @@ impl SimplifyCfg { SimplifyCfg::AfterUnreachableEnumBranching => { "SimplifyCfg-after-unreachable-enum-branching" } + SimplifyCfg::PostMono => "SimplifyCfg-post-mono", } } } @@ -79,7 +81,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyCfg { self.name() } - fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!("SimplifyCfg({:?}) - simplifying {:?}", self.name(), body.source); simplify_cfg(body); } diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs index bea3d0d8557a7..3d324d783edb9 100644 --- a/compiler/rustc_mir_transform/src/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -1,10 +1,11 @@ use rustc_middle::mir::*; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{self, TyCtxt}; use tracing::trace; pub(super) enum SimplifyConstCondition { AfterConstProp, Final, + PostMono, } /// A pass that replaces a branch with a goto when its condition is known. @@ -13,12 +14,17 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition { match self { SimplifyConstCondition::AfterConstProp => "SimplifyConstCondition-after-const-prop", SimplifyConstCondition::Final => "SimplifyConstCondition-final", + SimplifyConstCondition::PostMono => "SimplifyConstCondition-post-mono", } } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("Running SimplifyConstCondition on {:?}", body.source); - let typing_env = body.typing_env(tcx); + let typing_env = if matches!(*self, SimplifyConstCondition::PostMono) { + ty::TypingEnv::fully_monomorphized() + } else { + body.typing_env(tcx) + }; 'blocks: for block in body.basic_blocks_mut() { for stmt in block.statements.iter_mut() { // Simplify `assume` of a known value: either a NOP or unreachable. diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 414477d900402..f77892f8ade89 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -262,12 +262,6 @@ impl<'a, 'tcx> CfgChecker<'a, 'tcx> { UnwindAction::Unreachable | UnwindAction::Terminate(UnwindTerminateReason::Abi) => (), } } - - fn is_critical_call_edge(&self, target: Option, unwind: UnwindAction) -> bool { - let Some(target) = target else { return false }; - matches!(unwind, UnwindAction::Cleanup(_) | UnwindAction::Terminate(_)) - && self.body.basic_blocks.predecessors()[target].len() > 1 - } } impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { @@ -376,23 +370,6 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { } self.check_unwind_edge(location, unwind); - // The code generation assumes that there are no critical call edges. The - // assumption is used to simplify inserting code that should be executed along - // the return edge from the call. FIXME(tmiasko): Since this is a strictly code - // generation concern, the code generation should be responsible for handling - // it. - if self.body.phase >= MirPhase::Runtime(RuntimePhase::Optimized) - && self.is_critical_call_edge(target, unwind) - { - self.fail( - location, - format!( - "encountered critical edge in `Call` terminator {:?}", - terminator.kind, - ), - ); - } - // The call destination place and Operand::Move place used as an argument might // be passed by a reference to the callee. Consequently they cannot be packed. if is_within_packed(self.tcx, &self.body.local_decls, destination).is_some() { diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl index 540ce7cc4ce30..e581d12fc1431 100644 --- a/compiler/rustc_monomorphize/messages.ftl +++ b/compiler/rustc_monomorphize/messages.ftl @@ -1,30 +1,9 @@ -monomorphize_abi_error_disabled_vector_type_call = - this function call uses a SIMD vector type that (with the chosen ABI) requires the `{$required_feature}` target feature, which is not enabled in the caller - .label = function called here - .help = consider enabling it globally (`-C target-feature=+{$required_feature}`) or locally (`#[target_feature(enable="{$required_feature}")]`) -monomorphize_abi_error_disabled_vector_type_def = - this function definition uses a SIMD vector type that (with the chosen ABI) requires the `{$required_feature}` target feature, which is not enabled - .label = function defined here - .help = consider enabling it globally (`-C target-feature=+{$required_feature}`) or locally (`#[target_feature(enable="{$required_feature}")]`) - -monomorphize_abi_error_unsupported_vector_type_call = - this function call uses a SIMD vector type that is not currently supported with the chosen ABI - .label = function called here -monomorphize_abi_error_unsupported_vector_type_def = - this function definition uses a SIMD vector type that is not currently supported with the chosen ABI - .label = function defined here - monomorphize_couldnt_dump_mono_stats = unexpected error occurred while dumping monomorphization stats: {$error} monomorphize_encountered_error_while_instantiating = the above error was encountered while instantiating `{$formatted_item}` -monomorphize_large_assignments = - moving {$size} bytes - .label = value moved from here - .note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` - monomorphize_no_optimized_mir = missing optimized MIR for an item in the crate `{$crate_name}` .note = missing optimized MIR for this item (was the crate `{$crate_name}` compiled with `--emit=metadata`?) diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index c2e9498908cda..cc937b38654c8 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -219,14 +219,14 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::interpret::{AllocId, ErrorHandled, GlobalAlloc, Scalar}; use rustc_middle::mir::mono::{CollectionMode, InstantiationMode, MonoItem}; use rustc_middle::mir::visit::Visitor as MirVisitor; -use rustc_middle::mir::{self, Location, MentionedItem, traversal}; +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; use rustc_middle::ty::print::{shrunk_instance_name, with_no_trimmed_paths}; use rustc_middle::ty::{ self, GenericArgs, GenericParamDefKind, Instance, InstanceKind, Interner, Ty, TyCtxt, - TypeFoldable, TypeVisitableExt, VtblEntry, + TypeVisitableExt, VtblEntry, }; use rustc_middle::util::Providers; use rustc_middle::{bug, span_bug}; @@ -625,38 +625,24 @@ struct MirUsedCollector<'a, 'tcx> { /// See the comment in `collect_items_of_instance` for the purpose of this set. /// Note that this contains *not-monomorphized* items! used_mentioned_items: &'a mut UnordSet>, - instance: Instance<'tcx>, } impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> { - fn monomorphize(&self, value: T) -> T - where - T: TypeFoldable>, - { - trace!("monomorphize: self.instance={:?}", self.instance); - self.instance.instantiate_mir_and_normalize_erasing_regions( - self.tcx, - ty::TypingEnv::fully_monomorphized(), - ty::EarlyBinder::bind(value), - ) - } - - /// Evaluates a *not yet monomorphized* constant. + /// Evaluates a monomorphized constant. fn eval_constant( &mut self, constant: &mir::ConstOperand<'tcx>, ) -> Option> { - let const_ = self.monomorphize(constant.const_); // Evaluate the constant. This makes const eval failure a collection-time error (rather than // a codegen-time error). rustc stops after collection if there was an error, so this // ensures codegen never has to worry about failing consts. // (codegen relies on this and ICEs will happen if this is violated.) - match const_.eval(self.tcx, ty::TypingEnv::fully_monomorphized(), constant.span) { + match constant.const_.eval(self.tcx, ty::TypingEnv::fully_monomorphized(), constant.span) { Ok(v) => Some(v), Err(ErrorHandled::TooGeneric(..)) => span_bug!( constant.span, "collection encountered polymorphic constant: {:?}", - const_ + constant.const_ ), Err(err @ ErrorHandled::Reported(..)) => { err.emit_note(self.tcx); @@ -686,8 +672,6 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { // *Before* monomorphizing, record that we already handled this mention. self.used_mentioned_items .insert(MentionedItem::UnsizeCast { source_ty, target_ty }); - let target_ty = self.monomorphize(target_ty); - let source_ty = self.monomorphize(source_ty); let (source_ty, target_ty) = find_vtable_types_for_unsizing(self.tcx.at(span), source_ty, target_ty); // This could also be a different Unsize instruction, like @@ -713,7 +697,6 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { let fn_ty = operand.ty(self.body, self.tcx); // *Before* monomorphizing, record that we already handled this mention. self.used_mentioned_items.insert(MentionedItem::Fn(fn_ty)); - let fn_ty = self.monomorphize(fn_ty); visit_fn_use(self.tcx, fn_ty, false, span, self.used_items); } mir::Rvalue::Cast( @@ -724,7 +707,6 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { let source_ty = operand.ty(self.body, self.tcx); // *Before* monomorphizing, record that we already handled this mention. self.used_mentioned_items.insert(MentionedItem::Closure(source_ty)); - let source_ty = self.monomorphize(source_ty); if let ty::Closure(def_id, args) = *source_ty.kind() { let instance = Instance::resolve_closure(self.tcx, def_id, args, ty::ClosureKind::FnOnce); @@ -776,14 +758,12 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { let callee_ty = func.ty(self.body, tcx); // *Before* monomorphizing, record that we already handled this mention. self.used_mentioned_items.insert(MentionedItem::Fn(callee_ty)); - let callee_ty = self.monomorphize(callee_ty); visit_fn_use(self.tcx, callee_ty, true, source, &mut self.used_items) } mir::TerminatorKind::Drop { ref place, .. } => { let ty = place.ty(self.body, self.tcx).ty; // *Before* monomorphizing, record that we already handled this mention. self.used_mentioned_items.insert(MentionedItem::Drop(ty)); - let ty = self.monomorphize(ty); visit_drop_use(self.tcx, ty, true, source, self.used_items); } mir::TerminatorKind::InlineAsm { ref operands, .. } => { @@ -793,7 +773,6 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { let fn_ty = value.const_.ty(); // *Before* monomorphizing, record that we already handled this mention. self.used_mentioned_items.insert(MentionedItem::Fn(fn_ty)); - let fn_ty = self.monomorphize(fn_ty); visit_fn_use(self.tcx, fn_ty, false, source, self.used_items); } mir::InlineAsmOperand::SymStatic { def_id } => { @@ -1212,10 +1191,7 @@ fn collect_items_of_instance<'tcx>( instance: Instance<'tcx>, mode: CollectionMode, ) -> (MonoItems<'tcx>, MonoItems<'tcx>) { - // This item is getting monomorphized, do mono-time checks. - tcx.ensure().check_mono_item(instance); - - let body = tcx.instance_mir(instance.def); + let body = tcx.codegen_mir(instance); // 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 // visited, but at that point each mentioned item has been monomorphized, added to the @@ -1234,11 +1210,10 @@ fn collect_items_of_instance<'tcx>( body, used_items: &mut used_items, used_mentioned_items: &mut used_mentioned_items, - instance, }; if mode == CollectionMode::UsedItems { - for (bb, data) in traversal::mono_reachable(body, tcx, instance) { + for (bb, data) in body.basic_blocks.iter_enumerated() { collector.visit_basic_block_data(bb, data) } } @@ -1255,8 +1230,7 @@ fn collect_items_of_instance<'tcx>( // `used_items` above. for item in body.mentioned_items() { if !collector.used_mentioned_items.contains(&item.node) { - let item_mono = collector.monomorphize(item.node); - visit_mentioned_item(tcx, &item_mono, item.span, &mut mentioned_items); + visit_mentioned_item(tcx, &item.node, item.span, &mut mentioned_items); } } diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index fc8d63b588818..2cd47be56133f 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -1,6 +1,6 @@ use std::path::PathBuf; -use rustc_macros::{Diagnostic, LintDiagnostic}; +use rustc_macros::Diagnostic; use rustc_span::{Span, Symbol}; #[derive(Diagnostic)] @@ -25,16 +25,6 @@ pub(crate) struct NoOptimizedMir { pub crate_name: Symbol, } -#[derive(LintDiagnostic)] -#[diag(monomorphize_large_assignments)] -#[note] -pub(crate) struct LargeAssignmentsLint { - #[label] - pub span: Span, - pub size: u64, - pub limit: u64, -} - #[derive(Diagnostic)] #[diag(monomorphize_symbol_already_defined)] pub(crate) struct SymbolAlreadyDefined { @@ -67,35 +57,3 @@ pub(crate) struct StartNotFound; pub(crate) struct UnknownCguCollectionMode<'a> { pub mode: &'a str, } - -#[derive(LintDiagnostic)] -#[diag(monomorphize_abi_error_disabled_vector_type_def)] -#[help] -pub(crate) struct AbiErrorDisabledVectorTypeDef<'a> { - #[label] - pub span: Span, - pub required_feature: &'a str, -} - -#[derive(LintDiagnostic)] -#[diag(monomorphize_abi_error_disabled_vector_type_call)] -#[help] -pub(crate) struct AbiErrorDisabledVectorTypeCall<'a> { - #[label] - pub span: Span, - pub required_feature: &'a str, -} - -#[derive(LintDiagnostic)] -#[diag(monomorphize_abi_error_unsupported_vector_type_def)] -pub(crate) struct AbiErrorUnsupportedVectorTypeDef { - #[label] - pub span: Span, -} - -#[derive(LintDiagnostic)] -#[diag(monomorphize_abi_error_unsupported_vector_type_call)] -pub(crate) struct AbiErrorUnsupportedVectorTypeCall { - #[label] - pub span: Span, -} diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index 714b64b3a231c..abe7eeef70ced 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -17,7 +17,6 @@ use rustc_span::ErrorGuaranteed; mod collector; mod errors; -mod mono_checks; mod partitioning; mod util; @@ -52,5 +51,4 @@ fn custom_coerce_unsize_info<'tcx>( pub fn provide(providers: &mut Providers) { partitioning::provide(providers); - mono_checks::provide(providers); } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index ab606478c5136..53731dd2ca791 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -599,6 +599,13 @@ fn layout_of_uncached<'tcx>( let maybe_unsized = def.is_struct() && def.non_enum_variant().tail_opt().is_some_and(|last_field| { + /* + let typing_env = if cx.typing_env == ty::TypingEnv::fully_monomorphized() { + cx.typing_env + } else { + ty::TypingEnv::post_analysis(tcx, def.did()) + }; + */ let typing_env = ty::TypingEnv::post_analysis(tcx, def.did()); !tcx.type_of(last_field.did).instantiate_identity().is_sized(tcx, typing_env) }); diff --git a/src/tools/clippy/clippy_utils/src/mir/mod.rs b/src/tools/clippy/clippy_utils/src/mir/mod.rs index ccbbccd0dbffc..3ead5919a41d3 100644 --- a/src/tools/clippy/clippy_utils/src/mir/mod.rs +++ b/src/tools/clippy/clippy_utils/src/mir/mod.rs @@ -30,7 +30,7 @@ pub fn visit_local_usage(locals: &[Local], mir: &Body<'_>, location: Location) - locals.len() ]; - traversal::Postorder::new(&mir.basic_blocks, location.block, ()) + traversal::Postorder::new(&mir.basic_blocks, location.block) .collect::>() .into_iter() .rev() diff --git a/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs b/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs index 4b520a6206951..5c4c36d306a05 100644 --- a/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs +++ b/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -O +//@ compile-flags: -O -Zmir-enable-passes=-InstSimplify-post-mono //@ min-llvm-version: 19 #![crate_type = "lib"] diff --git a/tests/codegen/precondition-checks.rs b/tests/codegen/precondition-checks.rs index 16812ca17207c..95866666cf5a6 100644 --- a/tests/codegen/precondition-checks.rs +++ b/tests/codegen/precondition-checks.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Cno-prepopulate-passes -Copt-level=0 -Cdebug-assertions=no +//@ compile-flags: -Copt-level=0 -Cdebug-assertions=no // This test ensures that in a debug build which turns off debug assertions, we do not monomorphize // any of the standard library's unsafe precondition checks. diff --git a/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs index 5ab55a467268b..5f9ef5bfc4ae3 100644 --- a/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs +++ b/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs @@ -156,7 +156,7 @@ pub fn foo5(a: &dyn Trait5) { let b = &[Type5; 32]; a.quux(&b); // CHECK-LABEL: define{{.*}}4foo5{{.*}}!{{|kcfi_type}} !{{[0-9]+}} - // CHECK: call void %{{[0-9]}}(ptr align 1 {{%[a-z](\.0)*|%_[0-9]+]}}, ptr align 1 {{%[a-z](\.0)*|%_[0-9]+}}){{.*}}[ "kcfi"(i32 [[TYPE5:[[:print:]]+]]) ] + // CHECK: call void %{{[0-9]}}(ptr align 1 %a.0, ptr align 1 %_5){{.*}}[ "kcfi"(i32 [[TYPE5:[[:print:]]+]]) ] } pub fn bar5() { @@ -165,7 +165,7 @@ pub fn bar5() { let b = &a as &dyn Trait5; b.quux(&a); // CHECK-LABEL: define{{.*}}4bar5{{.*}}!{{|kcfi_type}} !{{[0-9]+}} - // CHECK: call void %{{[0-9]}}(ptr align 1 {{%[a-z](\.0)*|%_[0-9]+]}}, ptr align 1 {{%[a-z](\.0)*|%_[0-9]+}}){{.*}}[ "kcfi"(i32 [[TYPE5:[[:print:]]+]]) ] + // CHECK: call void %{{[0-9]}}(ptr align 1 %a, ptr align 1 %_9){{.*}}[ "kcfi"(i32 [[TYPE5:[[:print:]]+]]) ] } // CHECK: !{{[0-9]+}} = !{i32 [[TYPE1]]} diff --git a/tests/codegen/skip-mono-inside-if-false.rs b/tests/codegen/skip-mono-inside-if-false.rs deleted file mode 100644 index 8b95de99dd3bd..0000000000000 --- a/tests/codegen/skip-mono-inside-if-false.rs +++ /dev/null @@ -1,41 +0,0 @@ -//@ compile-flags: -Cno-prepopulate-passes -Copt-level=0 - -#![crate_type = "lib"] - -#[no_mangle] -pub fn demo_for_i32() { - generic_impl::(); -} - -// Two important things here: -// - We replace the "then" block with `unreachable` to avoid linking problems -// - We neither declare nor define the `big_impl` that said block "calls". - -// CHECK-LABEL: ; skip_mono_inside_if_false::generic_impl -// CHECK: start: -// CHECK-NEXT: br label %[[ELSE_BRANCH:bb[0-9]+]] -// CHECK: [[ELSE_BRANCH]]: -// CHECK-NEXT: call skip_mono_inside_if_false::small_impl -// CHECK: bb{{[0-9]+}}: -// CHECK-NEXT: ret void -// CHECK: bb{{[0-9+]}}: -// CHECK-NEXT: unreachable - -fn generic_impl() { - trait MagicTrait { - const IS_BIG: bool; - } - impl MagicTrait for T { - const IS_BIG: bool = std::mem::size_of::() > 10; - } - if T::IS_BIG { - big_impl::(); - } else { - small_impl::(); - } -} - -#[inline(never)] -fn small_impl() {} -#[inline(never)] -fn big_impl() {} diff --git a/tests/crashes/129372.rs b/tests/crashes/129372.rs deleted file mode 100644 index 43be01b35df29..0000000000000 --- a/tests/crashes/129372.rs +++ /dev/null @@ -1,52 +0,0 @@ -//@ known-bug: #129372 -//@ compile-flags: -Cdebuginfo=2 -Copt-level=0 - -pub struct Wrapper(T); -struct Struct; - -pub trait TraitA { - type AssocA<'t>; -} -pub trait TraitB { - type AssocB; -} - -pub fn helper(v: impl MethodTrait) { - let _local_that_causes_ice = v.method(); -} - -pub fn main() { - helper(Wrapper(Struct)); -} - -pub trait MethodTrait { - type Assoc<'a>; - - fn method(self) -> impl for<'a> FnMut(&'a ()) -> Self::Assoc<'a>; -} - -impl MethodTrait for T -where - ::AssocB: TraitA, -{ - type Assoc<'a> = ::AssocA<'a>; - - fn method(self) -> impl for<'a> FnMut(&'a ()) -> Self::Assoc<'a> { - move |_| loop {} - } -} - -impl TraitB for Wrapper -where - B: TraitB, -{ - type AssocB = T; -} - -impl TraitB for Struct { - type AssocB = Struct; -} - -impl TraitA for Struct { - type AssocA<'t> = Self; -} diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff index 5ea9902b26251..2d1d2391870cd 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff @@ -53,8 +53,8 @@ _6 = const {0x1 as *mut [bool; 0]}; StorageLive(_11); StorageLive(_8); - _8 = UbChecks(); - switchInt(move _8) -> [0: bb4, otherwise: bb2]; + _8 = const false; + switchInt(const false) -> [0: bb4, otherwise: bb2]; } bb1: { diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff index cc5a41a7f63b1..9ac870b235eff 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff @@ -53,8 +53,8 @@ _6 = const {0x1 as *mut [bool; 0]}; StorageLive(_11); StorageLive(_8); - _8 = UbChecks(); - switchInt(move _8) -> [0: bb5, otherwise: bb3]; + _8 = const false; + switchInt(const false) -> [0: bb5, otherwise: bb3]; } bb1: { diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff index 3d398fbea7935..2d76c14f90440 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff @@ -53,8 +53,8 @@ _6 = const {0x1 as *mut [bool; 0]}; StorageLive(_11); StorageLive(_8); - _8 = UbChecks(); - switchInt(move _8) -> [0: bb4, otherwise: bb2]; + _8 = const false; + switchInt(const false) -> [0: bb4, otherwise: bb2]; } bb1: { diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff index dc99c3f7a8c9b..51056e7efda3f 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff @@ -53,8 +53,8 @@ _6 = const {0x1 as *mut [bool; 0]}; StorageLive(_11); StorageLive(_8); - _8 = UbChecks(); - switchInt(move _8) -> [0: bb5, otherwise: bb3]; + _8 = const false; + switchInt(const false) -> [0: bb5, otherwise: bb3]; } bb1: { diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff index 6a3ec54306994..3fb3a3687c693 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff @@ -55,8 +55,10 @@ + _6 = const {0x1 as *mut [bool; 0]}; StorageLive(_11); StorageLive(_8); - _8 = UbChecks(); - switchInt(move _8) -> [0: bb4, otherwise: bb2]; +- _8 = UbChecks(); +- switchInt(move _8) -> [0: bb4, otherwise: bb2]; ++ _8 = const false; ++ switchInt(const false) -> [0: bb4, otherwise: bb2]; } bb1: { diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff index 9471ad47cd9df..1980e047d469e 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff @@ -55,8 +55,10 @@ + _6 = const {0x1 as *mut [bool; 0]}; StorageLive(_11); StorageLive(_8); - _8 = UbChecks(); - switchInt(move _8) -> [0: bb5, otherwise: bb3]; +- _8 = UbChecks(); +- switchInt(move _8) -> [0: bb5, otherwise: bb3]; ++ _8 = const false; ++ switchInt(const false) -> [0: bb5, otherwise: bb3]; } bb1: { diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff index 187927b8ecab7..09cabb40d6b6f 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff @@ -55,8 +55,10 @@ + _6 = const {0x1 as *mut [bool; 0]}; StorageLive(_11); StorageLive(_8); - _8 = UbChecks(); - switchInt(move _8) -> [0: bb4, otherwise: bb2]; +- _8 = UbChecks(); +- switchInt(move _8) -> [0: bb4, otherwise: bb2]; ++ _8 = const false; ++ switchInt(const false) -> [0: bb4, otherwise: bb2]; } bb1: { diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff index 031c021ba5abf..eefbfe7c09f3d 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff @@ -55,8 +55,10 @@ + _6 = const {0x1 as *mut [bool; 0]}; StorageLive(_11); StorageLive(_8); - _8 = UbChecks(); - switchInt(move _8) -> [0: bb5, otherwise: bb3]; +- _8 = UbChecks(); +- switchInt(move _8) -> [0: bb5, otherwise: bb3]; ++ _8 = const false; ++ switchInt(const false) -> [0: bb5, otherwise: bb3]; } bb1: { diff --git a/tests/ui/consts/const-eval/issue-50814-2.mir-opt.stderr b/tests/ui/consts/const-eval/issue-50814-2.mir-opt.stderr index 2de68d3fee9e0..8bf73468643b3 100644 --- a/tests/ui/consts/const-eval/issue-50814-2.mir-opt.stderr +++ b/tests/ui/consts/const-eval/issue-50814-2.mir-opt.stderr @@ -1,61 +1,21 @@ error[E0080]: evaluation of ` as Foo<()>>::BAR` failed - --> $DIR/issue-50814-2.rs:16:24 + --> $DIR/issue-50814-2.rs:17:24 | LL | const BAR: usize = [5, 6, 7][T::BOO]; | ^^^^^^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 42 note: erroneous constant encountered - --> $DIR/issue-50814-2.rs:20:6 + --> $DIR/issue-50814-2.rs:21:6 | LL | & as Foo>::BAR | ^^^^^^^^^^^^^^^^^^^^^ note: erroneous constant encountered - --> $DIR/issue-50814-2.rs:20:5 + --> $DIR/issue-50814-2.rs:21:5 | LL | & as Foo>::BAR | ^^^^^^^^^^^^^^^^^^^^^^ -note: erroneous constant encountered - --> $DIR/issue-50814-2.rs:20:5 - | -LL | & as Foo>::BAR - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -note: erroneous constant encountered - --> $DIR/issue-50814-2.rs:20:5 - | -LL | & as Foo>::BAR - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -note: erroneous constant encountered - --> $DIR/issue-50814-2.rs:20:5 - | -LL | & as Foo>::BAR - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -note: erroneous constant encountered - --> $DIR/issue-50814-2.rs:20:6 - | -LL | & as Foo>::BAR - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -note: erroneous constant encountered - --> $DIR/issue-50814-2.rs:20:6 - | -LL | & as Foo>::BAR - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/issue-50814-2.normal.stderr b/tests/ui/consts/const-eval/issue-50814-2.normal.stderr index 4a7dfb1930443..6272a7cb10fdf 100644 --- a/tests/ui/consts/const-eval/issue-50814-2.normal.stderr +++ b/tests/ui/consts/const-eval/issue-50814-2.normal.stderr @@ -1,31 +1,23 @@ error[E0080]: evaluation of ` as Foo<()>>::BAR` failed - --> $DIR/issue-50814-2.rs:16:24 + --> $DIR/issue-50814-2.rs:17:24 | LL | const BAR: usize = [5, 6, 7][T::BOO]; | ^^^^^^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 42 note: erroneous constant encountered - --> $DIR/issue-50814-2.rs:20:6 + --> $DIR/issue-50814-2.rs:21:6 | LL | & as Foo>::BAR | ^^^^^^^^^^^^^^^^^^^^^ note: erroneous constant encountered - --> $DIR/issue-50814-2.rs:20:5 + --> $DIR/issue-50814-2.rs:21:5 | LL | & as Foo>::BAR | ^^^^^^^^^^^^^^^^^^^^^^ -note: erroneous constant encountered - --> $DIR/issue-50814-2.rs:20:6 - | -LL | & as Foo>::BAR - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - note: the above error was encountered while instantiating `fn foo::<()>` - --> $DIR/issue-50814-2.rs:32:22 + --> $DIR/issue-50814-2.rs:33:22 | LL | println!("{:x}", foo::<()>() as *const usize as usize); | ^^^^^^^^^^^ diff --git a/tests/ui/consts/const-eval/issue-50814-2.rs b/tests/ui/consts/const-eval/issue-50814-2.rs index c2e2de67a6517..cc5464df10cbd 100644 --- a/tests/ui/consts/const-eval/issue-50814-2.rs +++ b/tests/ui/consts/const-eval/issue-50814-2.rs @@ -1,6 +1,7 @@ //@ build-fail //@ revisions: normal mir-opt //@ [mir-opt]compile-flags: -Zmir-opt-level=4 +//@ compile-flags: -Zdeduplicate-diagnostics=yes trait C { const BOO: usize; diff --git a/tests/ui/consts/mono-reachable-invalid-const.rs b/tests/ui/consts/mono-reachable-invalid-const.rs index aabdb071bc9fb..4e0bd6b4ddbee 100644 --- a/tests/ui/consts/mono-reachable-invalid-const.rs +++ b/tests/ui/consts/mono-reachable-invalid-const.rs @@ -1,4 +1,5 @@ //@ build-fail +//@ compile-flags: -Zdeduplicate-diagnostics=yes struct Bar; diff --git a/tests/ui/consts/mono-reachable-invalid-const.stderr b/tests/ui/consts/mono-reachable-invalid-const.stderr index 6b7b25b59b821..72abf5a482832 100644 --- a/tests/ui/consts/mono-reachable-invalid-const.stderr +++ b/tests/ui/consts/mono-reachable-invalid-const.stderr @@ -1,25 +1,23 @@ error[E0080]: evaluation of `Bar::<0>::ASSERT` failed - --> $DIR/mono-reachable-invalid-const.rs:8:9 + --> $DIR/mono-reachable-invalid-const.rs:9:9 | LL | ["oops"][b]; | ^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 1 note: erroneous constant encountered - --> $DIR/mono-reachable-invalid-const.rs:13:19 + --> $DIR/mono-reachable-invalid-const.rs:9:9 | -LL | let val = Self::ASSERT; - | ^^^^^^^^^^^^ +LL | ["oops"][b]; + | ^^^^^^^^^^^ note: erroneous constant encountered - --> $DIR/mono-reachable-invalid-const.rs:13:19 + --> $DIR/mono-reachable-invalid-const.rs:14:19 | LL | let val = Self::ASSERT; | ^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` note: the above error was encountered while instantiating `fn Bar::<0>::assert` - --> $DIR/mono-reachable-invalid-const.rs:22:5 + --> $DIR/mono-reachable-invalid-const.rs:23:5 | LL | Bar::<0>::assert(); | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/inline-const/const-expr-generic-err.rs b/tests/ui/inline-const/const-expr-generic-err.rs index 3249e826a96be..c38e8a13291cb 100644 --- a/tests/ui/inline-const/const-expr-generic-err.rs +++ b/tests/ui/inline-const/const-expr-generic-err.rs @@ -1,4 +1,5 @@ //@ build-fail +//@ compile-flags: -Zdeduplicate-diagnostics=yes fn foo() { const { assert!(std::mem::size_of::() == 0); } //~ ERROR E0080 diff --git a/tests/ui/inline-const/const-expr-generic-err.stderr b/tests/ui/inline-const/const-expr-generic-err.stderr index dcd6b62bbfc1d..385f92ac57d71 100644 --- a/tests/ui/inline-const/const-expr-generic-err.stderr +++ b/tests/ui/inline-const/const-expr-generic-err.stderr @@ -1,45 +1,43 @@ error[E0080]: evaluation of `foo::::{constant#0}` failed - --> $DIR/const-expr-generic-err.rs:4:13 + --> $DIR/const-expr-generic-err.rs:5:13 | LL | const { assert!(std::mem::size_of::() == 0); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: std::mem::size_of::() == 0', $DIR/const-expr-generic-err.rs:4:13 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: std::mem::size_of::() == 0', $DIR/const-expr-generic-err.rs:5:13 | = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered - --> $DIR/const-expr-generic-err.rs:4:5 + --> $DIR/const-expr-generic-err.rs:5:5 | LL | const { assert!(std::mem::size_of::() == 0); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: the above error was encountered while instantiating `fn foo::` - --> $DIR/const-expr-generic-err.rs:12:5 + --> $DIR/const-expr-generic-err.rs:13:5 | LL | foo::(); | ^^^^^^^^^^^^ error[E0080]: evaluation of `bar::<0>::{constant#0}` failed - --> $DIR/const-expr-generic-err.rs:8:13 + --> $DIR/const-expr-generic-err.rs:9:13 | LL | const { N - 1 } | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow note: erroneous constant encountered - --> $DIR/const-expr-generic-err.rs:8:5 + --> $DIR/const-expr-generic-err.rs:9:13 | LL | const { N - 1 } - | ^^^^^^^^^^^^^^^ + | ^^^^^ note: erroneous constant encountered - --> $DIR/const-expr-generic-err.rs:8:5 + --> $DIR/const-expr-generic-err.rs:9:5 | LL | const { N - 1 } | ^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` note: the above error was encountered while instantiating `fn bar::<0>` - --> $DIR/const-expr-generic-err.rs:13:5 + --> $DIR/const-expr-generic-err.rs:14:5 | LL | bar::<0>(); | ^^^^^^^^^^ diff --git a/tests/ui/layout/layout-cycle.rs b/tests/ui/layout/layout-cycle.rs index 3c930def43b2b..846ce0882cad1 100644 --- a/tests/ui/layout/layout-cycle.rs +++ b/tests/ui/layout/layout-cycle.rs @@ -1,6 +1,5 @@ //@ build-fail -//~^ ERROR: a cycle occurred during layout computation -//~| ERROR: cycle detected when computing layout of +//~^ ERROR: cycle detected when computing layout of // Issue #111176 -- ensure that we do not emit ICE on layout cycles diff --git a/tests/ui/layout/layout-cycle.stderr b/tests/ui/layout/layout-cycle.stderr index a3cdb7edcc232..148adf3361a64 100644 --- a/tests/ui/layout/layout-cycle.stderr +++ b/tests/ui/layout/layout-cycle.stderr @@ -2,10 +2,16 @@ error[E0391]: cycle detected when computing layout of `S>` | = note: ...which requires computing layout of ` as Tr>::I`... = note: ...which again requires computing layout of `S>`, completing the cycle +note: cycle used when finalizing codegen MIR for `core::mem::size_of::>>` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: failed to get layout for S>: a cycle occurred during layout computation +note: the above error was encountered while instantiating `fn std::mem::size_of::>>` + --> $DIR/layout-cycle.rs:25:5 + | +LL | mem::size_of::>() + | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/layout/post-mono-layout-cycle.rs b/tests/ui/layout/post-mono-layout-cycle.rs index 6753c01267ecd..a96c06cbfe4dd 100644 --- a/tests/ui/layout/post-mono-layout-cycle.rs +++ b/tests/ui/layout/post-mono-layout-cycle.rs @@ -1,5 +1,5 @@ //@ build-fail -//~^ cycle detected when computing layout of `Wrapper<()>` +//~^ ERROR: cycle detected when computing layout of trait Trait { type Assoc; diff --git a/tests/ui/layout/post-mono-layout-cycle.stderr b/tests/ui/layout/post-mono-layout-cycle.stderr index 7f246b3d409ad..e2f6ac595d006 100644 --- a/tests/ui/layout/post-mono-layout-cycle.stderr +++ b/tests/ui/layout/post-mono-layout-cycle.stderr @@ -5,11 +5,11 @@ error[E0391]: cycle detected when computing layout of `Wrapper<()>` = note: cycle used when computing layout of `core::option::Option>` = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -note: the above error was encountered while instantiating `fn abi::<()>` - --> $DIR/post-mono-layout-cycle.rs:19:5 +note: the above error was encountered while instantiating `fn indirect::<()>` + --> $DIR/post-mono-layout-cycle.rs:23:5 | -LL | abi::(None); - | ^^^^^^^^^^^^^^ +LL | indirect::<()>(); + | ^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/lint/large_assignments/copy_into_fn.stderr b/tests/ui/lint/large_assignments/copy_into_fn.stderr index f05fc33e17e14..2cc5eb97a4bdf 100644 --- a/tests/ui/lint/large_assignments/copy_into_fn.stderr +++ b/tests/ui/lint/large_assignments/copy_into_fn.stderr @@ -12,18 +12,18 @@ LL | #![deny(large_assignments)] | ^^^^^^^^^^^^^^^^^ error: moving 9999 bytes - --> $DIR/copy_into_fn.rs:17:15 + --> $DIR/copy_into_fn.rs:17:20 | LL | many_args(Data([0; 9999]), true, Data([0; 9999])); - | ^^^^^^^^^^^^^^^ value moved from here + | ^^^^^^^^^ 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 = "..."]` error: moving 9999 bytes - --> $DIR/copy_into_fn.rs:17:38 + --> $DIR/copy_into_fn.rs:17:43 | LL | many_args(Data([0; 9999]), true, Data([0; 9999])); - | ^^^^^^^^^^^^^^^ value moved from here + | ^^^^^^^^^ 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 = "..."]` diff --git a/tests/ui/mir/validate/critical-edge.rs b/tests/ui/mir/validate/critical-edge.rs deleted file mode 100644 index 9048d08a22a73..0000000000000 --- a/tests/ui/mir/validate/critical-edge.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Optimized MIR shouldn't have critical call edges -// -//@ build-fail -//@ edition: 2021 -//@ compile-flags: --crate-type=lib -//@ failure-status: 101 -//@ dont-check-compiler-stderr -//@ error-pattern: encountered critical edge in `Call` terminator -#![feature(custom_mir, core_intrinsics)] -use core::intrinsics::mir::*; - -#[custom_mir(dialect = "runtime", phase = "optimized")] -#[inline(always)] -pub fn f(a: u32) -> u32 { - mir! { - { - match a { - 0 => bb1, - _ => bb2, - } - } - bb1 = { - Call(RET = f(1), ReturnTo(bb2), UnwindTerminate(ReasonAbi)) - } - - bb2 = { - RET = 2; - Return() - } - } -} diff --git a/tests/ui/recursion_limit/zero-overflow.rs b/tests/ui/recursion_limit/zero-overflow.rs index 3887972a51623..5f5f59578a5a6 100644 --- a/tests/ui/recursion_limit/zero-overflow.rs +++ b/tests/ui/recursion_limit/zero-overflow.rs @@ -1,4 +1,4 @@ -//~ ERROR overflow evaluating the requirement `&mut Self: DispatchFromDyn<&mut RustaceansAreAwesome> +//~ ERROR overflow evaluating the requirement //~| HELP consider increasing the recursion limit //@ build-fail diff --git a/tests/ui/recursion_limit/zero-overflow.stderr b/tests/ui/recursion_limit/zero-overflow.stderr index fc03cc5b604b7..c7dfb01664f0b 100644 --- a/tests/ui/recursion_limit/zero-overflow.stderr +++ b/tests/ui/recursion_limit/zero-overflow.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow evaluating the requirement `&mut Self: DispatchFromDyn<&mut RustaceansAreAwesome>` +error[E0275]: overflow evaluating the requirement `{closure@rt::lang_start<()>::{closure#0}}: Freeze` | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "2"]` attribute to your crate (`zero_overflow`)