Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit eea4273

Browse files
committed
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
1 parent 8d99b0f commit eea4273

File tree

17 files changed

+138
-61
lines changed

17 files changed

+138
-61
lines changed

compiler/rustc_const_eval/src/const_eval/machine.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -561,8 +561,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
561561
throw_unsup_format!("pointer arithmetic or comparison is not supported at compile-time");
562562
}
563563

564-
fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
565-
// The step limit has already been hit in a previous call to `before_terminator`.
564+
fn increment_const_eval_counter(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
565+
// The step limit has already been hit in a previous call to `increment_const_eval_counter`.
566566
if ecx.machine.steps_remaining == 0 {
567567
return Ok(());
568568
}

compiler/rustc_const_eval/src/interpret/eval_context.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,6 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
4646

4747
/// The recursion limit (cached from `tcx.recursion_limit(())`)
4848
pub recursion_limit: Limit,
49-
50-
pub const_eval_limit: u32,
51-
pub const_eval_counter: u32,
5249
}
5350

5451
// 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> {
411408
param_env,
412409
memory: Memory::new(),
413410
recursion_limit: tcx.recursion_limit(),
414-
const_eval_limit: 20,
415-
const_eval_counter: 0,
416411
}
417412
}
418413

compiler/rustc_const_eval/src/interpret/machine.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -243,10 +243,10 @@ pub trait Machine<'mir, 'tcx>: Sized {
243243
ecx.stack_mut()[frame].locals[local].access_mut()
244244
}
245245

246-
/// Called before a basic block terminator is executed.
247-
/// You can use this to detect endlessly running programs.
246+
/// Called when the interpreter encounters a `StatementKind::ConstEvalCounter` instruction.
247+
/// You can use this to detect long or endlessly running programs.
248248
#[inline]
249-
fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
249+
fn increment_const_eval_counter(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
250250
Ok(())
251251
}
252252

compiler/rustc_const_eval/src/interpret/place.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -293,17 +293,6 @@ where
293293
Prov: Provenance + 'static,
294294
M: Machine<'mir, 'tcx, Provenance = Prov>,
295295
{
296-
pub fn increment_const_eval_counter(&mut self) {
297-
self.const_eval_counter = self.const_eval_counter + 1;
298-
if self.const_eval_counter == self.const_eval_limit {
299-
let mut warn = self.tcx.sess.struct_warn(format!(
300-
"Const eval counter limit ({}) has been crossed",
301-
self.const_eval_limit
302-
));
303-
warn.emit();
304-
}
305-
}
306-
307296
/// Take a value, which represents a (thin or wide) reference, and make it a place.
308297
/// Alignment is just based on the type. This is the inverse of `MemPlace::to_ref()`.
309298
///

compiler/rustc_const_eval/src/interpret/step.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
6262
return Ok(true);
6363
}
6464

65-
M::before_terminator(self)?;
66-
6765
let terminator = basic_block.terminator();
6866
self.terminator(terminator)?;
6967
Ok(true)
@@ -130,7 +128,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
130128
Coverage(..) => {}
131129

132130
ConstEvalCounter => {
133-
self.increment_const_eval_counter();
131+
M::increment_const_eval_counter(self)?;
134132
}
135133

136134
// Defined to do nothing. These are added by optimization passes, to avoid changing the

compiler/rustc_interface/src/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,7 @@ fn test_unstable_options_tracking_hash() {
802802
tracked!(teach, true);
803803
tracked!(thinlto, Some(true));
804804
tracked!(thir_unsafeck, true);
805+
tracked!(tiny_const_eval_limit, true);
805806
tracked!(tls_model, Some(TlsModel::GeneralDynamic));
806807
tracked!(trait_solver, TraitSolver::Chalk);
807808
tracked!(translate_remapped_path_to_local_path, false);

compiler/rustc_middle/src/ty/context.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ use std::iter;
7575
use std::mem;
7676
use std::ops::{Bound, Deref};
7777

78+
const TINY_CONST_EVAL_LIMIT: Limit = Limit(20);
79+
7880
pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
7981
/// Creates a new `OnDiskCache` instance from the serialized data in `data`.
8082
fn new(sess: &'tcx Session, data: Mmap, start_pos: usize) -> Self
@@ -1078,7 +1080,11 @@ impl<'tcx> TyCtxt<'tcx> {
10781080
}
10791081

10801082
pub fn const_eval_limit(self) -> Limit {
1081-
self.limits(()).const_eval_limit
1083+
if self.sess.opts.unstable_opts.tiny_const_eval_limit {
1084+
TINY_CONST_EVAL_LIMIT
1085+
} else {
1086+
self.limits(()).const_eval_limit
1087+
}
10821088
}
10831089

10841090
pub fn all_traits(self) -> impl Iterator<Item = DefId> + 'tcx {

compiler/rustc_session/src/options.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1616,6 +1616,8 @@ options! {
16161616
"measure time of each LLVM pass (default: no)"),
16171617
time_passes: bool = (false, parse_bool, [UNTRACKED],
16181618
"measure time of each rustc pass (default: no)"),
1619+
tiny_const_eval_limit: bool = (false, parse_bool, [TRACKED],
1620+
"sets a tiny, non-configurable limit for const eval; useful for compiler tests"),
16191621
#[rustc_lint_opt_deny_field_access("use `Session::tls_model` instead of this field")]
16201622
tls_model: Option<TlsModel> = (None, parse_tls_model, [TRACKED],
16211623
"choose the TLS model to use (`rustc --print tls-models` for details)"),
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# `tiny-const-eval-limit`
2+
3+
--------------------
4+
5+
The `-Ztiny-const-eval-limit` compiler flag sets a tiny, non-configurable limit for const eval.
6+
This flag should only be used by const eval tests in the rustc test suite.

src/test/ui/consts/const-eval/stable-metric/ctfe-fn-call.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
// check-pass
1+
// check-fail
2+
// compile-flags: -Z tiny-const-eval-limit
23

34
const fn foo() {}
45

@@ -8,21 +9,23 @@ const fn call_foo() -> u32 {
89
foo();
910
foo();
1011
foo();
12+
1113
foo();
1214
foo();
1315
foo();
1416
foo();
1517
foo();
18+
1619
foo();
1720
foo();
1821
foo();
1922
foo();
2023
foo();
24+
2125
foo();
2226
foo();
2327
foo();
24-
foo();
25-
foo();
28+
foo(); //~ ERROR evaluation of constant value failed [E0080]
2629
0
2730
}
2831

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,20 @@
1-
warning: Const eval counter limit (20) has been crossed
1+
error[E0080]: evaluation of constant value failed
2+
--> $DIR/ctfe-fn-call.rs:28:5
3+
|
4+
LL | foo();
5+
| ^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
6+
|
7+
note: inside `call_foo`
8+
--> $DIR/ctfe-fn-call.rs:28:5
9+
|
10+
LL | foo();
11+
| ^^^^^
12+
note: inside `X`
13+
--> $DIR/ctfe-fn-call.rs:32:16
14+
|
15+
LL | const X: u32 = call_foo();
16+
| ^^^^^^^^^^
217

3-
warning: 1 warning emitted
18+
error: aborting due to previous error
419

20+
For more information about this error, try `rustc --explain E0080`.

src/test/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.rs

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,18 @@
1-
// check-pass
2-
#![feature(const_for)]
1+
// check-fail
2+
// compile-flags: -Z tiny-const-eval-limit
33

4-
const fn labelled_loop() -> u32 {
5-
let mut n = 0;
6-
'outer: loop {
7-
'inner: loop {
8-
n = n + 1;
9-
if n > 5 && n <= 10 {
10-
n = n + 1;
11-
continue 'inner
12-
}
13-
if n > 30 {
14-
break 'outer
15-
}
4+
const fn labelled_loop(n: u32) -> u32 {
5+
let mut i = 0;
6+
'mylabel: loop { //~ ERROR evaluation of constant value failed [E0080]
7+
if i > n {
8+
break 'mylabel
169
}
10+
i += 1;
1711
}
18-
n
12+
0
1913
}
2014

21-
const X: u32 = labelled_loop();
15+
const X: u32 = labelled_loop(19);
2216

2317
fn main() {
2418
println!("{X}");
Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,30 @@
1-
warning: Const eval counter limit (20) has been crossed
1+
error[E0080]: evaluation of constant value failed
2+
--> $DIR/ctfe-labelled-loop.rs:6:5
3+
|
4+
LL | / 'mylabel: loop {
5+
LL | | if i > n {
6+
LL | | break 'mylabel
7+
LL | | }
8+
LL | | i += 1;
9+
LL | | }
10+
| |_____^ exceeded interpreter step limit (see `#[const_eval_limit]`)
11+
|
12+
note: inside `labelled_loop`
13+
--> $DIR/ctfe-labelled-loop.rs:6:5
14+
|
15+
LL | / 'mylabel: loop {
16+
LL | | if i > n {
17+
LL | | break 'mylabel
18+
LL | | }
19+
LL | | i += 1;
20+
LL | | }
21+
| |_____^
22+
note: inside `X`
23+
--> $DIR/ctfe-labelled-loop.rs:15:16
24+
|
25+
LL | const X: u32 = labelled_loop(19);
26+
| ^^^^^^^^^^^^^^^^^
227

3-
warning: 1 warning emitted
28+
error: aborting due to previous error
429

30+
For more information about this error, try `rustc --explain E0080`.

src/test/ui/consts/const-eval/stable-metric/ctfe-recursion.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1-
// check-pass
1+
// check-fail
2+
// compile-flags: -Z tiny-const-eval-limit
23

34
const fn recurse(n: u32) -> u32 {
45
if n == 0 {
56
n
67
} else {
7-
recurse(n - 1)
8+
recurse(n - 1) //~ ERROR evaluation of constant value failed [E0080]
89
}
910
}
1011

11-
const X: u32 = recurse(30);
12+
const X: u32 = recurse(19);
1213

1314
fn main() {
1415
println!("{X}");
Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,25 @@
1-
warning: Const eval counter limit (20) has been crossed
1+
error[E0080]: evaluation of constant value failed
2+
--> $DIR/ctfe-recursion.rs:8:9
3+
|
4+
LL | recurse(n - 1)
5+
| ^^^^^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
6+
|
7+
note: inside `recurse`
8+
--> $DIR/ctfe-recursion.rs:8:9
9+
|
10+
LL | recurse(n - 1)
11+
| ^^^^^^^^^^^^^^
12+
note: [... 18 additional calls inside `recurse` ...]
13+
--> $DIR/ctfe-recursion.rs:8:9
14+
|
15+
LL | recurse(n - 1)
16+
| ^^^^^^^^^^^^^^
17+
note: inside `X`
18+
--> $DIR/ctfe-recursion.rs:12:16
19+
|
20+
LL | const X: u32 = recurse(19);
21+
| ^^^^^^^^^^^
222

3-
warning: 1 warning emitted
23+
error: aborting due to previous error
424

25+
For more information about this error, try `rustc --explain E0080`.

src/test/ui/consts/const-eval/stable-metric/ctfe-simple-loop.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
// check-pass
1+
// check-fail
2+
// compile-flags: -Z tiny-const-eval-limit
23
const fn simple_loop(n: u32) -> u32 {
34
let mut index = 0;
4-
let mut res = 0;
5-
while index < n {
6-
res = res + index;
5+
while index < n { //~ ERROR evaluation of constant value failed [E0080]
76
index = index + 1;
87
}
9-
res
8+
0
109
}
1110

12-
const X: u32 = simple_loop(30);
11+
const X: u32 = simple_loop(19);
1312

1413
fn main() {
1514
println!("{X}");
Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,24 @@
1-
warning: Const eval counter limit (20) has been crossed
1+
error[E0080]: evaluation of constant value failed
2+
--> $DIR/ctfe-simple-loop.rs:5:5
3+
|
4+
LL | / while index < n {
5+
LL | | index = index + 1;
6+
LL | | }
7+
| |_____^ exceeded interpreter step limit (see `#[const_eval_limit]`)
8+
|
9+
note: inside `simple_loop`
10+
--> $DIR/ctfe-simple-loop.rs:5:5
11+
|
12+
LL | / while index < n {
13+
LL | | index = index + 1;
14+
LL | | }
15+
| |_____^
16+
note: inside `X`
17+
--> $DIR/ctfe-simple-loop.rs:11:16
18+
|
19+
LL | const X: u32 = simple_loop(19);
20+
| ^^^^^^^^^^^^^^^
221

3-
warning: 1 warning emitted
22+
error: aborting due to previous error
423

24+
For more information about this error, try `rustc --explain E0080`.

0 commit comments

Comments
 (0)