Skip to content

Commit 969a6c2

Browse files
committed
Auto merge of #86674 - Aaron1011:new-querify-limits, r=michaelwoerister
Query-ify global limit attribute handling Currently, we read various 'global limits' from inner attributes the crate root (`recursion_limit`, `move_size_limit`, `type_length_limit`, `const_eval_limit`). These limits are then stored in `Sessions`, allowing them to be access from a `TyCtxt` without registering a dependency on the crate root attributes. This PR moves the calculation of these global limits behind queries, so that we properly track dependencies on crate root attributes. During the setup of macro expansion (before we've created a `TyCtxt`), we need to access the recursion limit, which is now done by directly calling into the code shared by the normal query implementations.
2 parents 6e9b369 + 7e5a88a commit 969a6c2

File tree

31 files changed

+173
-91
lines changed

31 files changed

+173
-91
lines changed

compiler/rustc_interface/src/passes.rs

+10-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,13 @@ 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+
// We force these querie to run,
876+
// since they might not otherwise get called.
877+
// This marks the corresponding crate-level attributes
878+
// as used, and ensures that their values are valid.
879+
tcx.ensure().limits(());
875880
}
876881
);
877882
});

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

+28-20
Original file line numberDiff line numberDiff line change
@@ -10,38 +10,46 @@
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;
1515
use rustc_session::Session;
16+
use rustc_session::{Limit, Limits};
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.limits = |tcx, ()| Limits {
23+
recursion_limit: get_recursion_limit(tcx.hir().krate_attrs(), tcx.sess),
24+
move_size_limit: get_limit(tcx.hir().krate_attrs(), tcx.sess, sym::move_size_limit, 0),
25+
type_length_limit: get_limit(
26+
tcx.hir().krate_attrs(),
27+
tcx.sess,
28+
sym::type_length_limit,
29+
1048576,
30+
),
31+
const_eval_limit: get_limit(
32+
tcx.hir().krate_attrs(),
33+
tcx.sess,
34+
sym::const_eval_limit,
35+
1_000_000,
36+
),
37+
}
38+
}
39+
40+
pub fn get_recursion_limit(krate_attrs: &[Attribute], sess: &Session) -> Limit {
41+
get_limit(krate_attrs, sess, sym::recursion_limit, 128)
2542
}
2643

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 {
44+
fn get_limit(krate_attrs: &[Attribute], sess: &Session, name: Symbol, default: usize) -> Limit {
45+
for attr in krate_attrs {
3546
if !sess.check_name(attr, name) {
3647
continue;
3748
}
3849

3950
if let Some(s) = attr.value_str() {
4051
match s.as_str().parse() {
41-
Ok(n) => {
42-
limit.set(From::from(n)).unwrap();
43-
return;
44-
}
52+
Ok(n) => return Limit::new(n),
4553
Err(e) => {
4654
let mut err =
4755
sess.struct_span_err(attr.span, "`limit` must be a non-negative integer");
@@ -68,5 +76,5 @@ fn update_limit(
6876
}
6977
}
7078
}
71-
limit.set(From::from(default)).unwrap();
79+
return Limit::new(default);
7280
}

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

+4
Original file line numberDiff line numberDiff line change
@@ -1725,4 +1725,8 @@ rustc_queries! {
17251725
query conservative_is_privately_uninhabited(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
17261726
desc { "conservatively checking if {:?} is privately uninhabited", key }
17271727
}
1728+
1729+
query limits(key: ()) -> Limits {
1730+
desc { "looking up limits" }
1731+
}
17281732
}

compiler/rustc_middle/src/ty/context.rs

+17
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ use rustc_middle::ty::OpaqueTypeKey;
5353
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
5454
use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
5555
use rustc_session::lint::{Level, Lint};
56+
use rustc_session::Limit;
5657
use rustc_session::Session;
5758
use rustc_span::def_id::StableCrateId;
5859
use rustc_span::source_map::MultiSpan;
@@ -1569,6 +1570,22 @@ impl<'tcx> TyCtxt<'tcx> {
15691570
def_kind => (def_kind.article(), def_kind.descr(def_id)),
15701571
}
15711572
}
1573+
1574+
pub fn type_length_limit(self) -> Limit {
1575+
self.limits(()).type_length_limit
1576+
}
1577+
1578+
pub fn recursion_limit(self) -> Limit {
1579+
self.limits(()).recursion_limit
1580+
}
1581+
1582+
pub fn move_size_limit(self) -> Limit {
1583+
self.limits(()).move_size_limit
1584+
}
1585+
1586+
pub fn const_eval_limit(self) -> Limit {
1587+
self.limits(()).const_eval_limit
1588+
}
15721589
}
15731590

15741591
/// A trait implemented for all `X<'a>` types that can be safely and

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::Limits;
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().0;
818828
if limit == 0 {
819829
return;
820830
}

0 commit comments

Comments
 (0)