diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 8c4885770ad..2821677c537 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -393,6 +393,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { | mir::StatementKind::AscribeUserType(..) | mir::StatementKind::Coverage(..) | mir::StatementKind::Intrinsic(..) + | mir::StatementKind::ConstEvalCounter | mir::StatementKind::Nop => {} } } diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index 6fd9290058c..6217676d5c1 100644 --- a/compiler/rustc_borrowck/src/invalidation.rs +++ b/compiler/rustc_borrowck/src/invalidation.rs @@ -91,7 +91,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { LocalMutationIsAllowed::Yes, ); } - StatementKind::Nop + StatementKind::ConstEvalCounter + | StatementKind::Nop | StatementKind::Retag { .. } | StatementKind::Deinit(..) | StatementKind::SetDiscriminant { .. } => { diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 73ea7314b75..8f8fae2c630 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -620,7 +620,8 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx flow_state, ); } - StatementKind::Nop + StatementKind::ConstEvalCounter + | StatementKind::Nop | StatementKind::Retag { .. } | StatementKind::Deinit(..) | StatementKind::SetDiscriminant { .. } => { diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 81bd4c2a783..06087b0c579 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1258,6 +1258,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { | StatementKind::StorageDead(..) | StatementKind::Retag { .. } | StatementKind::Coverage(..) + | StatementKind::ConstEvalCounter | StatementKind::Nop => {} StatementKind::Deinit(..) | StatementKind::SetDiscriminant { .. } => { bug!("Statement not allowed in this MIR phase") diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index 19452c8cdc8..60fbceb344d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -91,6 +91,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::StatementKind::FakeRead(..) | mir::StatementKind::Retag { .. } | mir::StatementKind::AscribeUserType(..) + | mir::StatementKind::ConstEvalCounter | mir::StatementKind::Nop => {} } } diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 18e01567ca3..041e9d41357 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -22,6 +22,8 @@ use crate::interpret::{ RefTracking, StackPopCleanup, }; +use tracing::info; + const NOTE_ON_UNDEFINED_BEHAVIOR_ERROR: &str = "The rules on what exactly is undefined behavior aren't clear, \ so this check might be overzealous. Please open an issue on the rustc \ repository if you believe it should not be considered undefined behavior."; @@ -33,6 +35,7 @@ fn eval_body_using_ecx<'mir, 'tcx>( body: &'mir mir::Body<'tcx>, ) -> InterpResult<'tcx, MPlaceTy<'tcx>> { debug!("eval_body_using_ecx: {:?}, {:?}", cid, ecx.param_env); + info!("HERE body is {:#?}", body); let tcx = *ecx.tcx; assert!( cid.promoted.is_some() diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 4709514c82e..befc71ce6a0 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -369,6 +369,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } } + #[instrument(skip(ecx), ret)] fn load_mir( ecx: &InterpCx<'mir, 'tcx, Self>, instance: ty::InstanceDef<'tcx>, diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index d13fed7a9c2..cc97564e8fc 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -46,6 +46,9 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> { /// The recursion limit (cached from `tcx.recursion_limit(())`) pub recursion_limit: Limit, + + pub const_eval_limit: u32, + pub const_eval_counter: u32, } // The Phantomdata exists to prevent this type from being `Send`. If it were sent across a thread @@ -408,6 +411,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { param_env, memory: Memory::new(), recursion_limit: tcx.recursion_limit(), + const_eval_limit: 20, + const_eval_counter: 0, } } diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 274af61ee7c..271a3a74fe3 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -293,6 +293,17 @@ where Prov: Provenance + 'static, M: Machine<'mir, 'tcx, Provenance = Prov>, { + pub fn increment_const_eval_counter(&mut self) { + self.const_eval_counter = self.const_eval_counter + 1; + if self.const_eval_counter == self.const_eval_limit { + let mut warn = self.tcx.sess.struct_warn(format!( + "Const eval counter limit ({}) has been crossed", + self.const_eval_limit + )); + warn.emit(); + } + } + /// Take a value, which represents a (thin or wide) reference, and make it a place. /// Alignment is just based on the type. This is the inverse of `MemPlace::to_ref()`. /// diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index fad4cb06cd6..0f0eb5aadd7 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -129,6 +129,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // FIXME(#73156): Handle source code coverage in const eval Coverage(..) => {} + // FIXME(bryangarza): Update this to do some logic!!! + ConstEvalCounter => { + self.increment_const_eval_counter(); + } + // Defined to do nothing. These are added by optimization passes, to avoid changing the // size of MIR constantly. Nop => {} diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 79f1737e32b..16b504dd9d4 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -693,6 +693,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { | StatementKind::AscribeUserType(..) | StatementKind::Coverage(..) | StatementKind::Intrinsic(..) + | StatementKind::ConstEvalCounter | StatementKind::Nop => {} } } diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index dd168a9ac3c..4ad699c0395 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -766,6 +766,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { StatementKind::StorageLive(..) | StatementKind::StorageDead(..) | StatementKind::Coverage(_) + | StatementKind::ConstEvalCounter | StatementKind::Nop => {} } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 4da893e4c07..dae7e84e415 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1461,6 +1461,7 @@ impl Debug for Statement<'_> { } Coverage(box ref coverage) => write!(fmt, "Coverage::{:?}", coverage.kind), Intrinsic(box ref intrinsic) => write!(fmt, "{intrinsic}"), + ConstEvalCounter => write!(fmt, "ConstEvalCounter"), Nop => write!(fmt, "nop"), } } diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index a8a4532223c..c281fe00591 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -441,10 +441,14 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mir_for_ctfe_opt_const_arg(self, def: ty::WithOptConstParam) -> &'tcx Body<'tcx> { - if let Some((did, param_did)) = def.as_const_arg() { + let res = if let Some((did, param_did)) = def.as_const_arg() { + info!("calling mir_for_ctfe_of_const_arg for DedId {did:?}"); self.mir_for_ctfe_of_const_arg((did, param_did)) } else { + info!("calling mir_for_ctfe for DefId {:?}", def.did); self.mir_for_ctfe(def.did) - } + }; + //info!("RES OF CALLING MIR_FOR_CTFE_OPT_CONST_ARG: {:#?}", res); + res } } diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs index 887ee571575..7efe1fde093 100644 --- a/compiler/rustc_middle/src/mir/spanview.rs +++ b/compiler/rustc_middle/src/mir/spanview.rs @@ -250,6 +250,7 @@ pub fn statement_kind_name(statement: &Statement<'_>) -> &'static str { AscribeUserType(..) => "AscribeUserType", Coverage(..) => "Coverage", Intrinsic(..) => "Intrinsic", + ConstEvalCounter => "ConstEvalCounter", Nop => "Nop", } } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 52c2b10cbbe..faf903a5949 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -286,7 +286,10 @@ pub enum StatementKind<'tcx> { /// This is permitted for both generators and ADTs. This does not necessarily write to the /// entire place; instead, it writes to the minimum set of bytes as required by the layout for /// the type. - SetDiscriminant { place: Box>, variant_index: VariantIdx }, + SetDiscriminant { + place: Box>, + variant_index: VariantIdx, + }, /// Deinitializes the place. /// @@ -355,6 +358,8 @@ pub enum StatementKind<'tcx> { /// This avoids adding a new block and a terminator for simple intrinsics. Intrinsic(Box>), + ConstEvalCounter, + /// No-op. Useful for deleting instructions without affecting statement indices. Nop, } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 1a264d2d5af..3ddac5e11fb 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -427,6 +427,7 @@ macro_rules! make_mir_visitor { } } } + StatementKind::ConstEvalCounter => {} StatementKind::Nop => {} } } diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index 923dc16c11b..2890fa32cc9 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -271,6 +271,7 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> { | StatementKind::AscribeUserType(..) | StatementKind::Coverage(..) | StatementKind::Intrinsic(..) + | StatementKind::ConstEvalCounter | StatementKind::Nop => None, }; if let Some(destination) = destination { diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index 8d379b90a86..fcf0ce9d821 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -141,6 +141,7 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc StatementKind::AscribeUserType(..) | StatementKind::Coverage(..) | StatementKind::FakeRead(..) + | StatementKind::ConstEvalCounter | StatementKind::Nop | StatementKind::Retag(..) | StatementKind::Intrinsic(..) diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index f46fd118bde..0195693a7cb 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -331,6 +331,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { | StatementKind::AscribeUserType(..) | StatementKind::Coverage(..) | StatementKind::Intrinsic(..) + | StatementKind::ConstEvalCounter | StatementKind::Nop => {} } } diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 0522c657939..6bdbda909d7 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -84,7 +84,8 @@ pub trait ValueAnalysis<'tcx> { StatementKind::Retag(..) => { // We don't track references. } - StatementKind::Nop + StatementKind::ConstEvalCounter + | StatementKind::Nop | StatementKind::FakeRead(..) | StatementKind::Coverage(..) | StatementKind::AscribeUserType(..) => (), diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index adf6ae4c727..837233953e7 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -104,6 +104,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { | StatementKind::AscribeUserType(..) | StatementKind::Coverage(..) | StatementKind::Intrinsic(..) + | StatementKind::ConstEvalCounter | StatementKind::Nop => { // safe (at least as emitted during MIR construction) } diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 31d5541a31b..f973c1ed28f 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -802,6 +802,8 @@ pub(super) fn filtered_statement_span(statement: &Statement<'_>) -> Option | StatementKind::StorageDead(_) // Coverage should not be encountered, but don't inject coverage coverage | StatementKind::Coverage(_) + // Ignore `ConstEvalCounter`s + | StatementKind::ConstEvalCounter // Ignore `Nop`s | StatementKind::Nop => None, diff --git a/compiler/rustc_mir_transform/src/ctfe_limit.rs b/compiler/rustc_mir_transform/src/ctfe_limit.rs new file mode 100644 index 00000000000..dc54b983c0e --- /dev/null +++ b/compiler/rustc_mir_transform/src/ctfe_limit.rs @@ -0,0 +1,92 @@ +use crate::MirPass; + +use rustc_middle::mir::{BasicBlock, Body, Statement, StatementKind, TerminatorKind}; +use rustc_middle::ty::TyCtxt; + +use tracing::{info, instrument}; + +pub struct CtfeLimit; + +impl<'tcx> MirPass<'tcx> for CtfeLimit { + #[instrument(skip(self, _tcx, body))] + fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let doms = body.basic_blocks.dominators(); + //info!("Got body with {} basic blocks: {:#?}", body.basic_blocks.len(), body.basic_blocks); + //info!("With doms: {doms:?}"); + + /* + for (index, basic_block) in body.basic_blocks.iter().enumerate() { + info!("bb{index}: {basic_block:#?}") + }*/ + for (index, basic_block) in body.basic_blocks.iter().enumerate() { + info!( + "bb{index} -> successors = {:?}", + basic_block.terminator().successors().collect::>() + ); + } + for (index, basic_block) in body.basic_blocks.iter().enumerate() { + info!("bb{index} -> unwind = {:?}", basic_block.terminator().unwind()) + } + + let mut dominators = Vec::new(); + for idom in 0..body.basic_blocks.len() { + let mut nodes = Vec::new(); + for inode in 0..body.basic_blocks.len() { + let dom = BasicBlock::from_usize(idom); + let node = BasicBlock::from_usize(inode); + if doms.is_reachable(dom) + && doms.is_reachable(node) + && doms.is_dominated_by(node, dom) + { + //info!("{idom} dominates {inode}"); + nodes.push(true); + } else { + nodes.push(false); + } + } + dominators.push(nodes); + } + /* + for idom in 0..body.basic_blocks.len() { + print!("{idom} | dom | "); + for inode in 0..body.basic_blocks.len() { + if dominators[idom][inode] { + print!("{inode} | "); + } else { + print!(" | "); + } + } + print!("\n"); + } + */ + + for (index, basic_block) in body.basic_blocks_mut().iter_mut().enumerate() { + // info!("bb{index}: {basic_block:#?}"); + //info!("bb{index} -> successors = {:?}", basic_block.terminator().successors().collect::>()); + let is_back_edge_or_fn_call = 'label: { + match basic_block.terminator().kind { + TerminatorKind::Call { .. } => { + break 'label true; + } + _ => (), + } + for successor in basic_block.terminator().successors() { + let s_index = successor.as_usize(); + if dominators[s_index][index] { + info!("{s_index} to {index} is a loop"); + break 'label true; + } + } + false + }; + if is_back_edge_or_fn_call { + basic_block.statements.push(Statement { + source_info: basic_block.terminator().source_info, + kind: StatementKind::ConstEvalCounter, + }); + info!("New basic block statements vector: {:?}", basic_block.statements); + } + } + info!("With doms: {doms:?}"); + } +} diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index 09546330cec..9dbfb089dc6 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -53,6 +53,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS | StatementKind::StorageDead(_) | StatementKind::Coverage(_) | StatementKind::Intrinsic(_) + | StatementKind::ConstEvalCounter | StatementKind::Nop => (), StatementKind::FakeRead(_) | StatementKind::AscribeUserType(_, _) => { diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 08e296a8371..20ffb0ab334 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -577,6 +577,7 @@ impl WriteInfo { self.add_place(**place); } StatementKind::Intrinsic(_) + | StatementKind::ConstEvalCounter | StatementKind::Nop | StatementKind::Coverage(_) | StatementKind::StorageLive(_) diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 39c61a34afc..0df732aa22b 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -1583,6 +1583,7 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> { | StatementKind::AscribeUserType(..) | StatementKind::Coverage(..) | StatementKind::Intrinsic(..) + | StatementKind::ConstEvalCounter | StatementKind::Nop => {} } } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 20b7fdcfe6d..e5c8127bea1 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -55,6 +55,7 @@ mod const_goto; mod const_prop; mod const_prop_lint; mod coverage; +mod ctfe_limit; mod dataflow_const_prop; mod dead_store_elimination; mod deaggregator; @@ -349,11 +350,14 @@ fn mir_promoted( /// Compute the MIR that is used during CTFE (and thus has no optimizations run on it) fn mir_for_ctfe(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> { let did = def_id.expect_local(); - if let Some(def) = ty::WithOptConstParam::try_lookup(did, tcx) { + let body = if let Some(def) = ty::WithOptConstParam::try_lookup(did, tcx) { tcx.mir_for_ctfe_of_const_arg(def) } else { tcx.arena.alloc(inner_mir_for_ctfe(tcx, ty::WithOptConstParam::unknown(did))) - } + }; + //info!("MIR_FOR_CTFE (DefId = {def_id:?}) body res: {:#?}", body); + info!("MIR_FOR_CTFE (DefId = {def_id:?})"); + body } /// Same as `mir_for_ctfe`, but used to get the MIR of a const generic parameter. @@ -447,6 +451,7 @@ fn mir_drops_elaborated_and_const_checked( run_analysis_to_runtime_passes(tcx, &mut body); + //info!("MIR after runtime passes: {:#?}", body); tcx.alloc_steal_mir(body) } @@ -517,6 +522,7 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // CTFE support for aggregates. &deaggregator::Deaggregator, &Lint(const_prop_lint::ConstProp), + &ctfe_limit::CtfeLimit, ]; pm::run_passes_no_validate(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::Initial))); } @@ -617,6 +623,7 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> { let mut body = remap_mir_for_const_eval_select(tcx, body, hir::Constness::NotConst); debug!("body: {:#?}", body); run_optimization_passes(tcx, &mut body); + //info!("body after OPTIMIZATION: {:#?}", body); debug_assert!(!body.has_free_regions(), "Free regions in optimized MIR"); diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index f1bbf2ea7e8..e3a03aa08af 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -35,6 +35,7 @@ impl RemoveNoopLandingPads { | StatementKind::StorageDead(_) | StatementKind::AscribeUserType(..) | StatementKind::Coverage(..) + | StatementKind::ConstEvalCounter | StatementKind::Nop => { // These are all noops in a landing pad } diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs index 2f116aaa958..a24d2d34d79 100644 --- a/compiler/rustc_mir_transform/src/separate_const_switch.rs +++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs @@ -250,6 +250,7 @@ fn is_likely_const<'tcx>(mut tracked_place: Place<'tcx>, block: &BasicBlockData< | StatementKind::Coverage(_) | StatementKind::StorageDead(_) | StatementKind::Intrinsic(_) + | StatementKind::ConstEvalCounter | StatementKind::Nop => {} } } @@ -318,6 +319,7 @@ fn find_determining_place<'tcx>( | StatementKind::AscribeUserType(_, _) | StatementKind::Coverage(_) | StatementKind::Intrinsic(_) + | StatementKind::ConstEvalCounter | StatementKind::Nop => {} // If the discriminant is set, it is always set diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 8f6abe7a912..7b6fa2baf2f 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -517,7 +517,7 @@ impl<'tcx> Visitor<'tcx> for UsedLocals { self.super_statement(statement, location); } - StatementKind::Nop => {} + StatementKind::ConstEvalCounter | StatementKind::Nop => {} StatementKind::StorageLive(_local) | StatementKind::StorageDead(_local) => {} diff --git a/src/test/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.rs b/src/test/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.rs new file mode 100644 index 00000000000..71f29ce8731 --- /dev/null +++ b/src/test/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.rs @@ -0,0 +1,25 @@ +// check-pass +#![feature(const_for)] + +const fn labelled_loop() -> u32 { + let mut n = 0; + 'outer: loop { + 'inner: loop { + n = n + 1; + if n > 5 && n <= 10 { + n = n + 1; + continue 'inner + } + if n > 30 { + break 'outer + } + } + } + n +} + +const X: u32 = labelled_loop(); + +fn main() { + println!("{X}"); +} diff --git a/src/test/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.stderr b/src/test/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.stderr new file mode 100644 index 00000000000..183bed3b75b --- /dev/null +++ b/src/test/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.stderr @@ -0,0 +1,4 @@ +warning: Const eval counter limit (20) has been crossed + +warning: 1 warning emitted + diff --git a/src/test/ui/consts/const-eval/stable-metric/ctfe-recursion.rs b/src/test/ui/consts/const-eval/stable-metric/ctfe-recursion.rs new file mode 100644 index 00000000000..00b4fc25859 --- /dev/null +++ b/src/test/ui/consts/const-eval/stable-metric/ctfe-recursion.rs @@ -0,0 +1,15 @@ +// check-pass + +const fn recurse(n: u32) -> u32 { + if n == 0 { + n + } else { + recurse(n - 1) + } +} + +const X: u32 = recurse(30); + +fn main() { + println!("{X}"); +} diff --git a/src/test/ui/consts/const-eval/stable-metric/ctfe-recursion.stderr b/src/test/ui/consts/const-eval/stable-metric/ctfe-recursion.stderr new file mode 100644 index 00000000000..183bed3b75b --- /dev/null +++ b/src/test/ui/consts/const-eval/stable-metric/ctfe-recursion.stderr @@ -0,0 +1,4 @@ +warning: Const eval counter limit (20) has been crossed + +warning: 1 warning emitted + diff --git a/src/test/ui/consts/const-eval/stable-metric/ctfe-simple-loop.rs b/src/test/ui/consts/const-eval/stable-metric/ctfe-simple-loop.rs new file mode 100644 index 00000000000..74dc74734b4 --- /dev/null +++ b/src/test/ui/consts/const-eval/stable-metric/ctfe-simple-loop.rs @@ -0,0 +1,16 @@ +// check-pass +const fn simple_loop(n: u32) -> u32 { + let mut index = 0; + let mut res = 0; + while index < n { + res = res + index; + index = index + 1; + } + res +} + +const X: u32 = simple_loop(30); + +fn main() { + println!("{X}"); +} diff --git a/src/test/ui/consts/const-eval/stable-metric/ctfe-simple-loop.stderr b/src/test/ui/consts/const-eval/stable-metric/ctfe-simple-loop.stderr new file mode 100644 index 00000000000..183bed3b75b --- /dev/null +++ b/src/test/ui/consts/const-eval/stable-metric/ctfe-simple-loop.stderr @@ -0,0 +1,4 @@ +warning: Const eval counter limit (20) has been crossed + +warning: 1 warning emitted +