diff options
| author | Bryan Garza <1396101+bryangarza@users.noreply.github.com> | 2022-12-29 23:14:29 +0000 |
|---|---|---|
| committer | Bryan Garza <1396101+bryangarza@users.noreply.github.com> | 2023-01-23 23:56:22 +0000 |
| commit | eea42733ac070b62492037107ee38028abb71f1a (patch) | |
| tree | 6c78cf3fd8c0fb4b22a3b14d314d4b1af4033d1d | |
| parent | 8d99b0fc8d732bcef84127bf431517922878461f (diff) | |
| download | rust-eea42733ac070b62492037107ee38028abb71f1a.tar.gz rust-eea42733ac070b62492037107ee38028abb71f1a.zip | |
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
17 files changed, 138 insertions, 61 deletions
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<Item = DefId> + '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<TlsModel> = (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`. |
