From 360db516ccf358bd4b35c483ae44634a74c66c0b Mon Sep 17 00:00:00 2001 From: Bryan Garza <1396101+bryangarza@users.noreply.github.com> Date: Tue, 20 Dec 2022 00:51:17 +0000 Subject: Create stable metric to measure long computation in Const Eval This patch adds a `MirPass` that tracks the number of back-edges and function calls in the CFG, adds a new MIR instruction to increment a counter every time they are encountered during Const Eval, and emit a warning if a configured limit is breached. --- compiler/rustc_const_eval/src/interpret/eval_context.rs | 5 +++++ compiler/rustc_const_eval/src/interpret/place.rs | 11 +++++++++++ compiler/rustc_const_eval/src/interpret/step.rs | 5 +++++ 3 files changed, 21 insertions(+) (limited to 'compiler/rustc_const_eval/src/interpret') 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 => {} -- cgit 1.4.1-3-g733a5 From b763f9094fadc06fd65b906d5e8db0a9fd8ec6ba Mon Sep 17 00:00:00 2001 From: Bryan Garza <1396101+bryangarza@users.noreply.github.com> Date: Thu, 29 Dec 2022 03:49:48 +0000 Subject: Remove debugging-related code --- compiler/rustc_const_eval/src/const_eval/eval_queries.rs | 3 --- compiler/rustc_const_eval/src/const_eval/machine.rs | 1 - compiler/rustc_const_eval/src/interpret/step.rs | 1 - compiler/rustc_middle/src/mir/query.rs | 8 ++------ compiler/rustc_mir_transform/src/lib.rs | 9 ++------- 5 files changed, 4 insertions(+), 18 deletions(-) (limited to 'compiler/rustc_const_eval/src/interpret') 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 041e9d41357..18e01567ca3 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -22,8 +22,6 @@ 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."; @@ -35,7 +33,6 @@ 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 befc71ce6a0..4709514c82e 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -369,7 +369,6 @@ 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/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 0f0eb5aadd7..6c5594bc1b0 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -129,7 +129,6 @@ 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(); } diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index c281fe00591..a8a4532223c 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -441,14 +441,10 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mir_for_ctfe_opt_const_arg(self, def: ty::WithOptConstParam) -> &'tcx Body<'tcx> { - let res = if let Some((did, param_did)) = def.as_const_arg() { - info!("calling mir_for_ctfe_of_const_arg for DedId {did:?}"); + if let Some((did, param_did)) = def.as_const_arg() { 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_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index e5c8127bea1..9a786d0c8d6 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -350,14 +350,11 @@ 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(); - let body = if let Some(def) = ty::WithOptConstParam::try_lookup(did, tcx) { + 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. @@ -451,7 +448,6 @@ 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) } @@ -623,7 +619,6 @@ 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"); -- cgit 1.4.1-3-g733a5 From eea42733ac070b62492037107ee38028abb71f1a Mon Sep 17 00:00:00 2001 From: Bryan Garza <1396101+bryangarza@users.noreply.github.com> Date: Thu, 29 Dec 2022 23:14:29 +0000 Subject: Replace terminator-based const eval limit - Remove logic that limits const eval based on terminators, and use the stable metric instead (back edges + fn calls) - Add unstable flag `tiny-const-eval-limit` to add UI tests that do not have to go up to the regular 2M step limit --- .../rustc_const_eval/src/const_eval/machine.rs | 4 +-- .../rustc_const_eval/src/interpret/eval_context.rs | 5 ---- compiler/rustc_const_eval/src/interpret/machine.rs | 6 ++--- compiler/rustc_const_eval/src/interpret/place.rs | 11 -------- compiler/rustc_const_eval/src/interpret/step.rs | 4 +-- compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_middle/src/ty/context.rs | 8 +++++- compiler/rustc_session/src/options.rs | 2 ++ .../src/compiler-flags/tiny-const-eval-limit.md | 6 +++++ .../const-eval/stable-metric/ctfe-fn-call.rs | 9 ++++--- .../const-eval/stable-metric/ctfe-fn-call.stderr | 20 +++++++++++++-- .../const-eval/stable-metric/ctfe-labelled-loop.rs | 26 ++++++++----------- .../stable-metric/ctfe-labelled-loop.stderr | 30 ++++++++++++++++++++-- .../const-eval/stable-metric/ctfe-recursion.rs | 7 ++--- .../const-eval/stable-metric/ctfe-recursion.stderr | 25 ++++++++++++++++-- .../const-eval/stable-metric/ctfe-simple-loop.rs | 11 ++++---- .../stable-metric/ctfe-simple-loop.stderr | 24 +++++++++++++++-- 17 files changed, 138 insertions(+), 61 deletions(-) create mode 100644 src/doc/unstable-book/src/compiler-flags/tiny-const-eval-limit.md (limited to 'compiler/rustc_const_eval/src/interpret') diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 4709514c82e..a5bc121485d 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -561,8 +561,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, throw_unsup_format!("pointer arithmetic or comparison is not supported at compile-time"); } - fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { - // The step limit has already been hit in a previous call to `before_terminator`. + fn increment_const_eval_counter(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { + // The step limit has already been hit in a previous call to `increment_const_eval_counter`. if ecx.machine.steps_remaining == 0 { return Ok(()); } diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index cc97564e8fc..d13fed7a9c2 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -46,9 +46,6 @@ 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 @@ -411,8 +408,6 @@ 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/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 248953de867..1f63a4ac537 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -243,10 +243,10 @@ pub trait Machine<'mir, 'tcx>: Sized { ecx.stack_mut()[frame].locals[local].access_mut() } - /// Called before a basic block terminator is executed. - /// You can use this to detect endlessly running programs. + /// Called when the interpreter encounters a `StatementKind::ConstEvalCounter` instruction. + /// You can use this to detect long or endlessly running programs. #[inline] - fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { + fn increment_const_eval_counter(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { Ok(()) } diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 271a3a74fe3..274af61ee7c 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -293,17 +293,6 @@ 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 6c5594bc1b0..7668e890c7b 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -62,8 +62,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return Ok(true); } - M::before_terminator(self)?; - let terminator = basic_block.terminator(); self.terminator(terminator)?; Ok(true) @@ -130,7 +128,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Coverage(..) => {} ConstEvalCounter => { - self.increment_const_eval_counter(); + M::increment_const_eval_counter(self)?; } // Defined to do nothing. These are added by optimization passes, to avoid changing the diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index f94bc4d4c66..52a4e0e7418 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -802,6 +802,7 @@ fn test_unstable_options_tracking_hash() { tracked!(teach, true); tracked!(thinlto, Some(true)); tracked!(thir_unsafeck, true); + tracked!(tiny_const_eval_limit, true); tracked!(tls_model, Some(TlsModel::GeneralDynamic)); tracked!(trait_solver, TraitSolver::Chalk); tracked!(translate_remapped_path_to_local_path, false); diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index ce04d8d21f4..8a61fd2e029 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -75,6 +75,8 @@ use std::iter; use std::mem; use std::ops::{Bound, Deref}; +const TINY_CONST_EVAL_LIMIT: Limit = Limit(20); + pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync { /// Creates a new `OnDiskCache` instance from the serialized data in `data`. fn new(sess: &'tcx Session, data: Mmap, start_pos: usize) -> Self @@ -1078,7 +1080,11 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn const_eval_limit(self) -> Limit { - self.limits(()).const_eval_limit + if self.sess.opts.unstable_opts.tiny_const_eval_limit { + TINY_CONST_EVAL_LIMIT + } else { + self.limits(()).const_eval_limit + } } pub fn all_traits(self) -> impl Iterator + 'tcx { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 7b5fd6cc2a8..789af0c7bf9 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1616,6 +1616,8 @@ options! { "measure time of each LLVM pass (default: no)"), time_passes: bool = (false, parse_bool, [UNTRACKED], "measure time of each rustc pass (default: no)"), + tiny_const_eval_limit: bool = (false, parse_bool, [TRACKED], + "sets a tiny, non-configurable limit for const eval; useful for compiler tests"), #[rustc_lint_opt_deny_field_access("use `Session::tls_model` instead of this field")] tls_model: Option = (None, parse_tls_model, [TRACKED], "choose the TLS model to use (`rustc --print tls-models` for details)"), diff --git a/src/doc/unstable-book/src/compiler-flags/tiny-const-eval-limit.md b/src/doc/unstable-book/src/compiler-flags/tiny-const-eval-limit.md new file mode 100644 index 00000000000..51c5fd69c63 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/tiny-const-eval-limit.md @@ -0,0 +1,6 @@ +# `tiny-const-eval-limit` + +-------------------- + +The `-Ztiny-const-eval-limit` compiler flag sets a tiny, non-configurable limit for const eval. +This flag should only be used by const eval tests in the rustc test suite. diff --git a/src/test/ui/consts/const-eval/stable-metric/ctfe-fn-call.rs b/src/test/ui/consts/const-eval/stable-metric/ctfe-fn-call.rs index 33488bd1d1c..c59596238e1 100644 --- a/src/test/ui/consts/const-eval/stable-metric/ctfe-fn-call.rs +++ b/src/test/ui/consts/const-eval/stable-metric/ctfe-fn-call.rs @@ -1,4 +1,5 @@ -// check-pass +// check-fail +// compile-flags: -Z tiny-const-eval-limit const fn foo() {} @@ -8,21 +9,23 @@ const fn call_foo() -> u32 { foo(); foo(); foo(); + foo(); foo(); foo(); foo(); foo(); + foo(); foo(); foo(); foo(); foo(); + foo(); foo(); foo(); - foo(); - foo(); + foo(); //~ ERROR evaluation of constant value failed [E0080] 0 } diff --git a/src/test/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr b/src/test/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr index 183bed3b75b..ed70975af34 100644 --- a/src/test/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr +++ b/src/test/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr @@ -1,4 +1,20 @@ -warning: Const eval counter limit (20) has been crossed +error[E0080]: evaluation of constant value failed + --> $DIR/ctfe-fn-call.rs:28:5 + | +LL | foo(); + | ^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`) + | +note: inside `call_foo` + --> $DIR/ctfe-fn-call.rs:28:5 + | +LL | foo(); + | ^^^^^ +note: inside `X` + --> $DIR/ctfe-fn-call.rs:32:16 + | +LL | const X: u32 = call_foo(); + | ^^^^^^^^^^ -warning: 1 warning emitted +error: aborting due to previous error +For more information about this error, try `rustc --explain E0080`. 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 index 71f29ce8731..c10b8d83791 100644 --- 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 @@ -1,24 +1,18 @@ -// check-pass -#![feature(const_for)] +// check-fail +// compile-flags: -Z tiny-const-eval-limit -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 - } +const fn labelled_loop(n: u32) -> u32 { + let mut i = 0; + 'mylabel: loop { //~ ERROR evaluation of constant value failed [E0080] + if i > n { + break 'mylabel } + i += 1; } - n + 0 } -const X: u32 = labelled_loop(); +const X: u32 = labelled_loop(19); 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 index 183bed3b75b..d9404edd5b1 100644 --- 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 @@ -1,4 +1,30 @@ -warning: Const eval counter limit (20) has been crossed +error[E0080]: evaluation of constant value failed + --> $DIR/ctfe-labelled-loop.rs:6:5 + | +LL | / 'mylabel: loop { +LL | | if i > n { +LL | | break 'mylabel +LL | | } +LL | | i += 1; +LL | | } + | |_____^ exceeded interpreter step limit (see `#[const_eval_limit]`) + | +note: inside `labelled_loop` + --> $DIR/ctfe-labelled-loop.rs:6:5 + | +LL | / 'mylabel: loop { +LL | | if i > n { +LL | | break 'mylabel +LL | | } +LL | | i += 1; +LL | | } + | |_____^ +note: inside `X` + --> $DIR/ctfe-labelled-loop.rs:15:16 + | +LL | const X: u32 = labelled_loop(19); + | ^^^^^^^^^^^^^^^^^ -warning: 1 warning emitted +error: aborting due to previous error +For more information about this error, try `rustc --explain E0080`. 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 index 00b4fc25859..80ff835f3e8 100644 --- a/src/test/ui/consts/const-eval/stable-metric/ctfe-recursion.rs +++ b/src/test/ui/consts/const-eval/stable-metric/ctfe-recursion.rs @@ -1,14 +1,15 @@ -// check-pass +// check-fail +// compile-flags: -Z tiny-const-eval-limit const fn recurse(n: u32) -> u32 { if n == 0 { n } else { - recurse(n - 1) + recurse(n - 1) //~ ERROR evaluation of constant value failed [E0080] } } -const X: u32 = recurse(30); +const X: u32 = recurse(19); 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 index 183bed3b75b..ed9a3111942 100644 --- a/src/test/ui/consts/const-eval/stable-metric/ctfe-recursion.stderr +++ b/src/test/ui/consts/const-eval/stable-metric/ctfe-recursion.stderr @@ -1,4 +1,25 @@ -warning: Const eval counter limit (20) has been crossed +error[E0080]: evaluation of constant value failed + --> $DIR/ctfe-recursion.rs:8:9 + | +LL | recurse(n - 1) + | ^^^^^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`) + | +note: inside `recurse` + --> $DIR/ctfe-recursion.rs:8:9 + | +LL | recurse(n - 1) + | ^^^^^^^^^^^^^^ +note: [... 18 additional calls inside `recurse` ...] + --> $DIR/ctfe-recursion.rs:8:9 + | +LL | recurse(n - 1) + | ^^^^^^^^^^^^^^ +note: inside `X` + --> $DIR/ctfe-recursion.rs:12:16 + | +LL | const X: u32 = recurse(19); + | ^^^^^^^^^^^ -warning: 1 warning emitted +error: aborting due to previous error +For more information about this error, try `rustc --explain E0080`. 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 index 74dc74734b4..ca0eec93c5d 100644 --- 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 @@ -1,15 +1,14 @@ -// check-pass +// check-fail +// compile-flags: -Z tiny-const-eval-limit const fn simple_loop(n: u32) -> u32 { let mut index = 0; - let mut res = 0; - while index < n { - res = res + index; + while index < n { //~ ERROR evaluation of constant value failed [E0080] index = index + 1; } - res + 0 } -const X: u32 = simple_loop(30); +const X: u32 = simple_loop(19); 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 index 183bed3b75b..83ff275de70 100644 --- 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 @@ -1,4 +1,24 @@ -warning: Const eval counter limit (20) has been crossed +error[E0080]: evaluation of constant value failed + --> $DIR/ctfe-simple-loop.rs:5:5 + | +LL | / while index < n { +LL | | index = index + 1; +LL | | } + | |_____^ exceeded interpreter step limit (see `#[const_eval_limit]`) + | +note: inside `simple_loop` + --> $DIR/ctfe-simple-loop.rs:5:5 + | +LL | / while index < n { +LL | | index = index + 1; +LL | | } + | |_____^ +note: inside `X` + --> $DIR/ctfe-simple-loop.rs:11:16 + | +LL | const X: u32 = simple_loop(19); + | ^^^^^^^^^^^^^^^ -warning: 1 warning emitted +error: aborting due to previous error +For more information about this error, try `rustc --explain E0080`. -- cgit 1.4.1-3-g733a5 From 172662dede507cc678747cc3d090f2ae744733cf Mon Sep 17 00:00:00 2001 From: Bryan Garza <1396101+bryangarza@users.noreply.github.com> Date: Fri, 30 Dec 2022 00:34:17 +0000 Subject: Add back Machine::before_terminator(...) method Added it back because it's used by Miri, but in the compiler itself, it will not do anything (just return `Ok(())`. --- compiler/rustc_const_eval/src/const_eval/machine.rs | 5 +++++ compiler/rustc_const_eval/src/interpret/machine.rs | 6 ++++++ compiler/rustc_const_eval/src/interpret/step.rs | 2 ++ 3 files changed, 13 insertions(+) (limited to 'compiler/rustc_const_eval/src/interpret') diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index a5bc121485d..e51f52783d4 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -561,6 +561,11 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, throw_unsup_format!("pointer arithmetic or comparison is not supported at compile-time"); } + // Not used here, but used by Miri (see `src/tools/miri/src/machine.rs`). + fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { + Ok(()) + } + fn increment_const_eval_counter(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { // The step limit has already been hit in a previous call to `increment_const_eval_counter`. if ecx.machine.steps_remaining == 0 { diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 1f63a4ac537..76ed7b80f8d 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -243,6 +243,12 @@ pub trait Machine<'mir, 'tcx>: Sized { ecx.stack_mut()[frame].locals[local].access_mut() } + /// Called before a basic block terminator is executed. + #[inline] + fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { + Ok(()) + } + /// Called when the interpreter encounters a `StatementKind::ConstEvalCounter` instruction. /// You can use this to detect long or endlessly running programs. #[inline] diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 7668e890c7b..d101937fd74 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -62,6 +62,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return Ok(true); } + M::before_terminator(self)?; + let terminator = basic_block.terminator(); self.terminator(terminator)?; Ok(true) -- cgit 1.4.1-3-g733a5