Skip to content

Commit ff15b5e

Browse files
committed
Query-ify global limit attribute handling
1 parent 9044245 commit ff15b5e

File tree

30 files changed

+153
-91
lines changed

30 files changed

+153
-91
lines changed

compiler/rustc_interface/src/passes.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,6 @@ pub fn register_plugins<'a>(
211211
});
212212
}
213213

214-
sess.time("recursion_limit", || {
215-
middle::limits::update_limits(sess, &krate);
216-
});
217-
218214
let mut lint_store = rustc_lint::new_lint_store(
219215
sess.opts.debugging_opts.no_interleave_lints,
220216
sess.unstable_options(),
@@ -311,9 +307,11 @@ pub fn configure_and_expand(
311307

312308
// Create the config for macro expansion
313309
let features = sess.features_untracked();
310+
let recursion_limit =
311+
rustc_middle::middle::limits::get_recursion_limit(&krate.attrs, &sess);
314312
let cfg = rustc_expand::expand::ExpansionConfig {
315313
features: Some(&features),
316-
recursion_limit: sess.recursion_limit(),
314+
recursion_limit,
317315
trace_mac: sess.opts.debugging_opts.trace_macros,
318316
should_test: sess.opts.test,
319317
span_debug: sess.opts.debugging_opts.span_debug,
@@ -872,6 +870,15 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
872870
tcx.ensure().check_mod_unstable_api_usage(module);
873871
tcx.ensure().check_mod_const_bodies(module);
874872
});
873+
},
874+
{
875+
// Mark the attributes as used, and ensure that
876+
// they're not ill-formed. We force these queries
877+
// to run, since they might not otherwise get called.
878+
tcx.ensure().recursion_limit(());
879+
tcx.ensure().move_size_limit(());
880+
tcx.ensure().type_length_limit(());
881+
tcx.ensure().const_eval_limit(());
875882
}
876883
);
877884
});

compiler/rustc_middle/src/ich/hcx.rs

+2
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> {
245245
}
246246
}
247247

248+
impl rustc_session::HashStableContext for StableHashingContext<'a> {}
249+
248250
pub fn hash_stable_trait_impls<'a>(
249251
hcx: &mut StableHashingContext<'a>,
250252
hasher: &mut StableHasher,

compiler/rustc_middle/src/middle/limits.rs

+19-20
Original file line numberDiff line numberDiff line change
@@ -10,38 +10,37 @@
1010
//! just peeks and looks for that attribute.
1111
1212
use crate::bug;
13-
use rustc_ast as ast;
14-
use rustc_data_structures::sync::OnceCell;
13+
use crate::ty;
14+
use rustc_ast::Attribute;
15+
use rustc_session::Limit;
1516
use rustc_session::Session;
1617
use rustc_span::symbol::{sym, Symbol};
1718

1819
use std::num::IntErrorKind;
1920

20-
pub fn update_limits(sess: &Session, krate: &ast::Crate) {
21-
update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128);
22-
update_limit(sess, krate, &sess.move_size_limit, sym::move_size_limit, 0);
23-
update_limit(sess, krate, &sess.type_length_limit, sym::type_length_limit, 1048576);
24-
update_limit(sess, krate, &sess.const_eval_limit, sym::const_eval_limit, 1_000_000);
21+
pub fn provide(providers: &mut ty::query::Providers) {
22+
providers.recursion_limit = |tcx, ()| get_recursion_limit(tcx.hir().krate_attrs(), tcx.sess);
23+
providers.move_size_limit =
24+
|tcx, ()| get_limit(tcx.hir().krate_attrs(), tcx.sess, sym::move_size_limit, 0).0;
25+
providers.type_length_limit =
26+
|tcx, ()| get_limit(tcx.hir().krate_attrs(), tcx.sess, sym::type_length_limit, 1048576);
27+
providers.const_eval_limit =
28+
|tcx, ()| get_limit(tcx.hir().krate_attrs(), tcx.sess, sym::const_eval_limit, 1_000_000);
2529
}
2630

27-
fn update_limit(
28-
sess: &Session,
29-
krate: &ast::Crate,
30-
limit: &OnceCell<impl From<usize> + std::fmt::Debug>,
31-
name: Symbol,
32-
default: usize,
33-
) {
34-
for attr in &krate.attrs {
31+
pub fn get_recursion_limit(krate_attrs: &[Attribute], sess: &Session) -> Limit {
32+
get_limit(krate_attrs, sess, sym::recursion_limit, 128)
33+
}
34+
35+
fn get_limit(krate_attrs: &[Attribute], sess: &Session, name: Symbol, default: usize) -> Limit {
36+
for attr in krate_attrs {
3537
if !sess.check_name(attr, name) {
3638
continue;
3739
}
3840

3941
if let Some(s) = attr.value_str() {
4042
match s.as_str().parse() {
41-
Ok(n) => {
42-
limit.set(From::from(n)).unwrap();
43-
return;
44-
}
43+
Ok(n) => return Limit::new(n),
4544
Err(e) => {
4645
let mut err =
4746
sess.struct_span_err(attr.span, "`limit` must be a non-negative integer");
@@ -68,5 +67,5 @@ fn update_limit(
6867
}
6968
}
7069
}
71-
limit.set(From::from(default)).unwrap();
70+
return Limit::new(default);
7271
}

compiler/rustc_middle/src/middle/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,7 @@ pub mod privacy;
3232
pub mod region;
3333
pub mod resolve_lifetime;
3434
pub mod stability;
35+
36+
pub fn provide(providers: &mut crate::ty::query::Providers) {
37+
limits::provide(providers);
38+
}

compiler/rustc_middle/src/query/mod.rs

+22
Original file line numberDiff line numberDiff line change
@@ -1712,4 +1712,26 @@ rustc_queries! {
17121712
query conservative_is_privately_uninhabited(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
17131713
desc { "conservatively checking if {:?} is privately uninhabited", key }
17141714
}
1715+
1716+
/// The maximum recursion limit for potentially infinitely recursive
1717+
/// operations such as auto-dereference and monomorphization.
1718+
query recursion_limit(key: ()) -> Limit {
1719+
desc { "looking up recursion limit" }
1720+
}
1721+
1722+
/// The size at which the `large_assignments` lint starts
1723+
/// being emitted.
1724+
query move_size_limit(key: ()) -> usize {
1725+
desc { "looking up move size limit" }
1726+
}
1727+
1728+
/// The maximum length of types during monomorphization.
1729+
query type_length_limit(key: ()) -> Limit {
1730+
desc { "looking up type length limit" }
1731+
}
1732+
1733+
/// The maximum blocks a const expression can evaluate.
1734+
query const_eval_limit(key: ()) -> Limit {
1735+
desc { "looking up const eval limit" }
1736+
}
17151737
}

compiler/rustc_middle/src/ty/layout.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ fn layout_raw<'tcx>(
221221
ty::tls::with_related_context(tcx, move |icx| {
222222
let (param_env, ty) = query.into_parts();
223223

224-
if !tcx.sess.recursion_limit().value_within_limit(icx.layout_depth) {
224+
if !tcx.recursion_limit(()).value_within_limit(icx.layout_depth) {
225225
tcx.sess.fatal(&format!("overflow representing the type `{}`", ty));
226226
}
227227

compiler/rustc_middle/src/ty/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1987,6 +1987,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
19871987
util::provide(providers);
19881988
print::provide(providers);
19891989
super::util::bug::provide(providers);
1990+
super::middle::provide(providers);
19901991
*providers = ty::query::Providers {
19911992
trait_impls_of: trait_def::trait_impls_of_provider,
19921993
type_uninhabited_from: inhabitedness::type_uninhabited_from,

compiler/rustc_middle/src/ty/print/pretty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1437,7 +1437,7 @@ impl<F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> {
14371437
}
14381438

14391439
fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
1440-
let type_length_limit = self.tcx.sess.type_length_limit();
1440+
let type_length_limit = self.tcx.type_length_limit(());
14411441
if type_length_limit.value_within_limit(self.printed_type_count) {
14421442
self.printed_type_count += 1;
14431443
self.pretty_print_type(ty)

compiler/rustc_middle/src/ty/query/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ use rustc_serialize::opaque;
4949
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
5050
use rustc_session::utils::NativeLibKind;
5151
use rustc_session::CrateDisambiguator;
52+
use rustc_session::Limit;
5253
use rustc_target::spec::PanicStrategy;
5354

5455
use rustc_ast as ast;

compiler/rustc_middle/src/ty/util.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,9 @@ impl<'tcx> TyCtxt<'tcx> {
206206
mut ty: Ty<'tcx>,
207207
normalize: impl Fn(Ty<'tcx>) -> Ty<'tcx>,
208208
) -> Ty<'tcx> {
209+
let recursion_limit = self.recursion_limit(());
209210
for iteration in 0.. {
210-
if !self.sess.recursion_limit().value_within_limit(iteration) {
211+
if !recursion_limit.value_within_limit(iteration) {
211212
return self.ty_error_with_message(
212213
DUMMY_SP,
213214
&format!("reached the recursion limit finding the struct tail for {}", ty),

compiler/rustc_mir/src/const_eval/eval_queries.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>(
9898
tcx,
9999
root_span,
100100
param_env,
101-
CompileTimeInterpreter::new(tcx.sess.const_eval_limit()),
101+
CompileTimeInterpreter::new(tcx.const_eval_limit(())),
102102
MemoryExtra { can_access_statics },
103103
)
104104
}
@@ -300,7 +300,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
300300
tcx,
301301
tcx.def_span(def.did),
302302
key.param_env,
303-
CompileTimeInterpreter::new(tcx.sess.const_eval_limit()),
303+
CompileTimeInterpreter::new(tcx.const_eval_limit(())),
304304
// Statics (and promoteds inside statics) may access other statics, because unlike consts
305305
// they do not have to behave "as if" they were evaluated at runtime.
306306
MemoryExtra { can_access_statics: is_static },

compiler/rustc_mir/src/const_eval/machine.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
393393
frame: Frame<'mir, 'tcx>,
394394
) -> InterpResult<'tcx, Frame<'mir, 'tcx>> {
395395
// Enforce stack size limit. Add 1 because this is run before the new frame is pushed.
396-
if !ecx.tcx.sess.recursion_limit().value_within_limit(ecx.stack().len() + 1) {
396+
if !ecx.recursion_limit.value_within_limit(ecx.stack().len() + 1) {
397397
throw_exhaust!(StackFrameLimitReached)
398398
} else {
399399
Ok(frame)

compiler/rustc_mir/src/interpret/eval_context.rs

+5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use rustc_middle::ty::layout::{self, TyAndLayout};
1313
use rustc_middle::ty::{
1414
self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
1515
};
16+
use rustc_session::Limit;
1617
use rustc_span::{Pos, Span};
1718
use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size, TargetDataLayout};
1819

@@ -39,6 +40,9 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
3940

4041
/// The virtual memory system.
4142
pub memory: Memory<'mir, 'tcx, M>,
43+
44+
/// The recursion limit (cached from `tcx.recursion_limit(())`)
45+
pub recursion_limit: Limit,
4246
}
4347

4448
// The Phantomdata exists to prevent this type from being `Send`. If it were sent across a thread
@@ -388,6 +392,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
388392
tcx: tcx.at(root_span),
389393
param_env,
390394
memory: Memory::new(tcx, memory_extra),
395+
recursion_limit: tcx.recursion_limit(()),
391396
}
392397
}
393398

compiler/rustc_mir/src/monomorphize/collector.rs

+16-6
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ use rustc_middle::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFold
200200
use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyContext};
201201
use rustc_session::config::EntryFnType;
202202
use rustc_session::lint::builtin::LARGE_ASSIGNMENTS;
203+
use rustc_session::Limit;
203204
use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP};
204205
use rustc_target::abi::Size;
205206
use smallvec::SmallVec;
@@ -294,6 +295,7 @@ pub fn collect_crate_mono_items(
294295

295296
let mut visited = MTLock::new(FxHashSet::default());
296297
let mut inlining_map = MTLock::new(InliningMap::new());
298+
let recursion_limit = tcx.recursion_limit(());
297299

298300
{
299301
let visited: MTRef<'_, _> = &mut visited;
@@ -307,6 +309,7 @@ pub fn collect_crate_mono_items(
307309
dummy_spanned(root),
308310
visited,
309311
&mut recursion_depths,
312+
recursion_limit,
310313
inlining_map,
311314
);
312315
});
@@ -350,6 +353,7 @@ fn collect_items_rec<'tcx>(
350353
starting_point: Spanned<MonoItem<'tcx>>,
351354
visited: MTRef<'_, MTLock<FxHashSet<MonoItem<'tcx>>>>,
352355
recursion_depths: &mut DefIdMap<usize>,
356+
recursion_limit: Limit,
353357
inlining_map: MTRef<'_, MTLock<InliningMap<'tcx>>>,
354358
) {
355359
if !visited.lock_mut().insert(starting_point.node) {
@@ -409,8 +413,13 @@ fn collect_items_rec<'tcx>(
409413
debug_assert!(should_codegen_locally(tcx, &instance));
410414

411415
// Keep track of the monomorphization recursion depth
412-
recursion_depth_reset =
413-
Some(check_recursion_limit(tcx, instance, starting_point.span, recursion_depths));
416+
recursion_depth_reset = Some(check_recursion_limit(
417+
tcx,
418+
instance,
419+
starting_point.span,
420+
recursion_depths,
421+
recursion_limit,
422+
));
414423
check_type_length_limit(tcx, instance);
415424

416425
rustc_data_structures::stack::ensure_sufficient_stack(|| {
@@ -455,7 +464,7 @@ fn collect_items_rec<'tcx>(
455464
record_accesses(tcx, starting_point.node, neighbors.iter().map(|i| &i.node), inlining_map);
456465

457466
for neighbour in neighbors {
458-
collect_items_rec(tcx, neighbour, visited, recursion_depths, inlining_map);
467+
collect_items_rec(tcx, neighbour, visited, recursion_depths, recursion_limit, inlining_map);
459468
}
460469

461470
if let Some((def_id, depth)) = recursion_depth_reset {
@@ -523,6 +532,7 @@ fn check_recursion_limit<'tcx>(
523532
instance: Instance<'tcx>,
524533
span: Span,
525534
recursion_depths: &mut DefIdMap<usize>,
535+
recursion_limit: Limit,
526536
) -> (DefId, usize) {
527537
let def_id = instance.def_id();
528538
let recursion_depth = recursion_depths.get(&def_id).cloned().unwrap_or(0);
@@ -539,7 +549,7 @@ fn check_recursion_limit<'tcx>(
539549
// Code that needs to instantiate the same function recursively
540550
// more than the recursion limit is assumed to be causing an
541551
// infinite expansion.
542-
if !tcx.sess.recursion_limit().value_within_limit(adjusted_recursion_depth) {
552+
if !recursion_limit.value_within_limit(adjusted_recursion_depth) {
543553
let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32);
544554
let error = format!("reached the recursion limit while instantiating `{}`", shrunk);
545555
let mut err = tcx.sess.struct_span_fatal(span, &error);
@@ -577,7 +587,7 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
577587
// which means that rustc basically hangs.
578588
//
579589
// Bail out in these cases to avoid that bad user experience.
580-
if !tcx.sess.type_length_limit().value_within_limit(type_length) {
590+
if !tcx.type_length_limit(()).value_within_limit(type_length) {
581591
let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32);
582592
let msg = format!("reached the type-length limit while instantiating `{}`", shrunk);
583593
let mut diag = tcx.sess.struct_span_fatal(tcx.def_span(instance.def_id()), &msg);
@@ -814,7 +824,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
814824

815825
fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) {
816826
self.super_operand(operand, location);
817-
let limit = self.tcx.sess.move_size_limit();
827+
let limit = self.tcx.move_size_limit(());
818828
if limit == 0 {
819829
return;
820830
}

compiler/rustc_mir/src/transform/inline/cycle.rs

+15-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
55
use rustc_middle::mir::TerminatorKind;
66
use rustc_middle::ty::TypeFoldable;
77
use rustc_middle::ty::{self, subst::SubstsRef, InstanceDef, TyCtxt};
8+
use rustc_session::Limit;
89

910
// FIXME: check whether it is cheaper to precompute the entire call graph instead of invoking
1011
// this query riddiculously often.
@@ -30,7 +31,7 @@ crate fn mir_callgraph_reachable(
3031
);
3132
#[instrument(
3233
level = "debug",
33-
skip(tcx, param_env, target, stack, seen, recursion_limiter, caller)
34+
skip(tcx, param_env, target, stack, seen, recursion_limiter, caller, recursion_limit)
3435
)]
3536
fn process(
3637
tcx: TyCtxt<'tcx>,
@@ -40,6 +41,7 @@ crate fn mir_callgraph_reachable(
4041
stack: &mut Vec<ty::Instance<'tcx>>,
4142
seen: &mut FxHashSet<ty::Instance<'tcx>>,
4243
recursion_limiter: &mut FxHashMap<DefId, usize>,
44+
recursion_limit: Limit,
4345
) -> bool {
4446
trace!(%caller);
4547
for &(callee, substs) in tcx.mir_inliner_callees(caller.def) {
@@ -96,11 +98,20 @@ crate fn mir_callgraph_reachable(
9698
if seen.insert(callee) {
9799
let recursion = recursion_limiter.entry(callee.def_id()).or_default();
98100
trace!(?callee, recursion = *recursion);
99-
if tcx.sess.recursion_limit().value_within_limit(*recursion) {
101+
if recursion_limit.value_within_limit(*recursion) {
100102
*recursion += 1;
101103
stack.push(callee);
102104
let found_recursion = ensure_sufficient_stack(|| {
103-
process(tcx, param_env, callee, target, stack, seen, recursion_limiter)
105+
process(
106+
tcx,
107+
param_env,
108+
callee,
109+
target,
110+
stack,
111+
seen,
112+
recursion_limiter,
113+
recursion_limit,
114+
)
104115
});
105116
if found_recursion {
106117
return true;
@@ -122,6 +133,7 @@ crate fn mir_callgraph_reachable(
122133
&mut Vec::new(),
123134
&mut FxHashSet::default(),
124135
&mut FxHashMap::default(),
136+
tcx.recursion_limit(()),
125137
)
126138
}
127139

0 commit comments

Comments
 (0)