about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBryan Garza <1396101+bryangarza@users.noreply.github.com>2022-12-29 23:14:29 +0000
committerBryan Garza <1396101+bryangarza@users.noreply.github.com>2023-01-23 23:56:22 +0000
commiteea42733ac070b62492037107ee38028abb71f1a (patch)
tree6c78cf3fd8c0fb4b22a3b14d314d4b1af4033d1d
parent8d99b0fc8d732bcef84127bf431517922878461f (diff)
downloadrust-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
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs5
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs11
-rw-r--r--compiler/rustc_const_eval/src/interpret/step.rs4
-rw-r--r--compiler/rustc_interface/src/tests.rs1
-rw-r--r--compiler/rustc_middle/src/ty/context.rs8
-rw-r--r--compiler/rustc_session/src/options.rs2
-rw-r--r--src/doc/unstable-book/src/compiler-flags/tiny-const-eval-limit.md6
-rw-r--r--src/test/ui/consts/const-eval/stable-metric/ctfe-fn-call.rs9
-rw-r--r--src/test/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr20
-rw-r--r--src/test/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.rs26
-rw-r--r--src/test/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.stderr30
-rw-r--r--src/test/ui/consts/const-eval/stable-metric/ctfe-recursion.rs7
-rw-r--r--src/test/ui/consts/const-eval/stable-metric/ctfe-recursion.stderr25
-rw-r--r--src/test/ui/consts/const-eval/stable-metric/ctfe-simple-loop.rs11
-rw-r--r--src/test/ui/consts/const-eval/stable-metric/ctfe-simple-loop.stderr24
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`.