Skip to content

Commit 8262523

Browse files
committed
add new unstable flag for minimal recursion
1 parent 801bc19 commit 8262523

File tree

13 files changed

+122
-9
lines changed

13 files changed

+122
-9
lines changed

compiler/rustc_interface/src/limits.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
use rustc_hir::limit::Limit;
1212
use rustc_hir::{Attribute, find_attr};
1313
use rustc_middle::query::Providers;
14-
use rustc_session::Limits;
14+
use rustc_session::{Limits, Session};
1515

1616
pub(crate) fn provide(providers: &mut Providers) {
1717
providers.limits = |tcx, ()| {
1818
let attrs = tcx.hir_krate_attrs();
1919
Limits {
20-
recursion_limit: get_recursion_limit(tcx.hir_krate_attrs()),
20+
recursion_limit: get_recursion_limit(tcx.hir_krate_attrs(), tcx.sess),
2121
move_size_limit: find_attr!(attrs, MoveSizeLimit { limit, .. } => *limit)
2222
.unwrap_or(Limit::new(tcx.sess.opts.unstable_opts.move_size_limit.unwrap_or(0))),
2323
type_length_limit: find_attr!(attrs, TypeLengthLimit { limit, .. } => *limit)
@@ -30,6 +30,13 @@ pub(crate) fn provide(providers: &mut Providers) {
3030
}
3131

3232
// This one is separate because it must be read prior to macro expansion.
33-
pub(crate) fn get_recursion_limit(attrs: &[Attribute]) -> Limit {
34-
find_attr!(attrs, RecursionLimit { limit, .. } => *limit).unwrap_or(Limit::new(128))
33+
pub(crate) fn get_recursion_limit(attrs: &[Attribute], sess: &Session) -> Limit {
34+
let limit_from_crate =
35+
find_attr!(attrs, RecursionLimit { limit, .. } => limit.0).unwrap_or(128);
36+
Limit::new(
37+
sess.opts
38+
.unstable_opts
39+
.min_recursion_limit
40+
.map_or(limit_from_crate, |min| min.max(limit_from_crate)),
41+
)
3542
}

compiler/rustc_interface/src/passes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1429,5 +1429,5 @@ fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit
14291429
// So, no lints here to avoid duplicates.
14301430
ShouldEmit::EarlyFatal { also_emit_lints: false },
14311431
);
1432-
crate::limits::get_recursion_limit(attr.as_slice())
1432+
crate::limits::get_recursion_limit(attr.as_slice(), sess)
14331433
}

compiler/rustc_interface/src/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,7 @@ fn test_unstable_options_tracking_hash() {
822822
tracked!(maximal_hir_to_mir_coverage, true);
823823
tracked!(merge_functions, Some(MergeFunctions::Disabled));
824824
tracked!(min_function_alignment, Some(Align::EIGHT));
825+
tracked!(min_recursion_limit, Some(256));
825826
tracked!(mir_emit_retag, true);
826827
tracked!(mir_enable_passes, vec![("DestProp".to_string(), false)]);
827828
tracked!(mir_opt_level, Some(4));

compiler/rustc_session/src/options.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2456,6 +2456,8 @@ options! {
24562456
"the directory metrics emitted by rustc are dumped into (implicitly enables default set of metrics)"),
24572457
min_function_alignment: Option<Align> = (None, parse_align, [TRACKED],
24582458
"align all functions to at least this many bytes. Must be a power of 2"),
2459+
min_recursion_limit: Option<usize> = (None, parse_opt_number, [TRACKED],
2460+
"set a minimum recursion limit (final limit = max(this, recursion_limit_from_crate))"),
24592461
mir_emit_retag: bool = (false, parse_bool, [TRACKED],
24602462
"emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \
24612463
(default: no)"),
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# `min-recursion-limit`
2+
3+
This flag sets a minimum recursion limit for the compiler. The final recursion limit is calculated as `max(min_recursion_limit, recursion_limit_from_crate)`. This cannot ever lower the recursion limit. Unless the current crate has an explicitly low `recursion_limit` attribute, any value less than the current default does not have an effect.
4+
5+
The recursion limit affects (among other things):
6+
7+
- macro expansion
8+
- the trait solver
9+
- const evaluation
10+
- query depth
11+
12+
This flag is particularly useful when using the next trait solver (`-Z next-solver`), which may require a higher recursion limit for crates that were compiled successfully with the old solver.

src/tools/cargo

Submodule cargo updated 56 files
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//@ compile-flags: -Z min-recursion-limit=0
2+
//@ check-pass
3+
4+
// Checks that `min-recursion-limit` cannot lower the default recursion limit
5+
6+
macro_rules! count {
7+
() => {};
8+
($_:tt $($rest:tt)*) => { count!($($rest)*) };
9+
}
10+
11+
fn main() {
12+
// 100
13+
count!(
14+
a a a a a a a a a a a a a a a a a a a a
15+
a a a a a a a a a a a a a a a a a a a a
16+
a a a a a a a a a a a a a a a a a a a a
17+
a a a a a a a a a a a a a a a a a a a a
18+
a a a a a a a a a a a a a a a a a a a a
19+
);
20+
}

0 commit comments

Comments
 (0)