1
Fork 0

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.
This commit is contained in:
bors 2021-07-05 16:30:53 +00:00
commit 969a6c2481
31 changed files with 173 additions and 91 deletions

View file

@ -98,7 +98,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>(
tcx,
root_span,
param_env,
CompileTimeInterpreter::new(tcx.sess.const_eval_limit()),
CompileTimeInterpreter::new(tcx.const_eval_limit()),
MemoryExtra { can_access_statics },
)
}
@ -300,7 +300,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
tcx,
tcx.def_span(def.did),
key.param_env,
CompileTimeInterpreter::new(tcx.sess.const_eval_limit()),
CompileTimeInterpreter::new(tcx.const_eval_limit()),
// Statics (and promoteds inside statics) may access other statics, because unlike consts
// they do not have to behave "as if" they were evaluated at runtime.
MemoryExtra { can_access_statics: is_static },

View file

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

View file

@ -13,6 +13,7 @@ use rustc_middle::ty::layout::{self, TyAndLayout};
use rustc_middle::ty::{
self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
};
use rustc_session::Limit;
use rustc_span::{Pos, Span};
use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size, TargetDataLayout};
@ -39,6 +40,9 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
/// The virtual memory system.
pub memory: Memory<'mir, 'tcx, M>,
/// The recursion limit (cached from `tcx.recursion_limit(())`)
pub recursion_limit: Limit,
}
// 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> {
tcx: tcx.at(root_span),
param_env,
memory: Memory::new(tcx, memory_extra),
recursion_limit: tcx.recursion_limit(),
}
}

View file

@ -200,6 +200,7 @@ use rustc_middle::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFold
use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyContext};
use rustc_session::config::EntryFnType;
use rustc_session::lint::builtin::LARGE_ASSIGNMENTS;
use rustc_session::Limit;
use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP};
use rustc_target::abi::Size;
use smallvec::SmallVec;
@ -294,6 +295,7 @@ pub fn collect_crate_mono_items(
let mut visited = MTLock::new(FxHashSet::default());
let mut inlining_map = MTLock::new(InliningMap::new());
let recursion_limit = tcx.recursion_limit();
{
let visited: MTRef<'_, _> = &mut visited;
@ -307,6 +309,7 @@ pub fn collect_crate_mono_items(
dummy_spanned(root),
visited,
&mut recursion_depths,
recursion_limit,
inlining_map,
);
});
@ -350,6 +353,7 @@ fn collect_items_rec<'tcx>(
starting_point: Spanned<MonoItem<'tcx>>,
visited: MTRef<'_, MTLock<FxHashSet<MonoItem<'tcx>>>>,
recursion_depths: &mut DefIdMap<usize>,
recursion_limit: Limit,
inlining_map: MTRef<'_, MTLock<InliningMap<'tcx>>>,
) {
if !visited.lock_mut().insert(starting_point.node) {
@ -409,8 +413,13 @@ fn collect_items_rec<'tcx>(
debug_assert!(should_codegen_locally(tcx, &instance));
// Keep track of the monomorphization recursion depth
recursion_depth_reset =
Some(check_recursion_limit(tcx, instance, starting_point.span, recursion_depths));
recursion_depth_reset = Some(check_recursion_limit(
tcx,
instance,
starting_point.span,
recursion_depths,
recursion_limit,
));
check_type_length_limit(tcx, instance);
rustc_data_structures::stack::ensure_sufficient_stack(|| {
@ -455,7 +464,7 @@ fn collect_items_rec<'tcx>(
record_accesses(tcx, starting_point.node, neighbors.iter().map(|i| &i.node), inlining_map);
for neighbour in neighbors {
collect_items_rec(tcx, neighbour, visited, recursion_depths, inlining_map);
collect_items_rec(tcx, neighbour, visited, recursion_depths, recursion_limit, inlining_map);
}
if let Some((def_id, depth)) = recursion_depth_reset {
@ -523,6 +532,7 @@ fn check_recursion_limit<'tcx>(
instance: Instance<'tcx>,
span: Span,
recursion_depths: &mut DefIdMap<usize>,
recursion_limit: Limit,
) -> (DefId, usize) {
let def_id = instance.def_id();
let recursion_depth = recursion_depths.get(&def_id).cloned().unwrap_or(0);
@ -539,7 +549,7 @@ fn check_recursion_limit<'tcx>(
// Code that needs to instantiate the same function recursively
// more than the recursion limit is assumed to be causing an
// infinite expansion.
if !tcx.sess.recursion_limit().value_within_limit(adjusted_recursion_depth) {
if !recursion_limit.value_within_limit(adjusted_recursion_depth) {
let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32);
let error = format!("reached the recursion limit while instantiating `{}`", shrunk);
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>) {
// which means that rustc basically hangs.
//
// Bail out in these cases to avoid that bad user experience.
if !tcx.sess.type_length_limit().value_within_limit(type_length) {
if !tcx.type_length_limit().value_within_limit(type_length) {
let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32);
let msg = format!("reached the type-length limit while instantiating `{}`", shrunk);
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> {
fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) {
self.super_operand(operand, location);
let limit = self.tcx.sess.move_size_limit();
let limit = self.tcx.move_size_limit().0;
if limit == 0 {
return;
}

View file

@ -5,6 +5,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::mir::TerminatorKind;
use rustc_middle::ty::TypeFoldable;
use rustc_middle::ty::{self, subst::SubstsRef, InstanceDef, TyCtxt};
use rustc_session::Limit;
// FIXME: check whether it is cheaper to precompute the entire call graph instead of invoking
// this query riddiculously often.
@ -30,7 +31,7 @@ crate fn mir_callgraph_reachable(
);
#[instrument(
level = "debug",
skip(tcx, param_env, target, stack, seen, recursion_limiter, caller)
skip(tcx, param_env, target, stack, seen, recursion_limiter, caller, recursion_limit)
)]
fn process(
tcx: TyCtxt<'tcx>,
@ -40,6 +41,7 @@ crate fn mir_callgraph_reachable(
stack: &mut Vec<ty::Instance<'tcx>>,
seen: &mut FxHashSet<ty::Instance<'tcx>>,
recursion_limiter: &mut FxHashMap<DefId, usize>,
recursion_limit: Limit,
) -> bool {
trace!(%caller);
for &(callee, substs) in tcx.mir_inliner_callees(caller.def) {
@ -96,11 +98,20 @@ crate fn mir_callgraph_reachable(
if seen.insert(callee) {
let recursion = recursion_limiter.entry(callee.def_id()).or_default();
trace!(?callee, recursion = *recursion);
if tcx.sess.recursion_limit().value_within_limit(*recursion) {
if recursion_limit.value_within_limit(*recursion) {
*recursion += 1;
stack.push(callee);
let found_recursion = ensure_sufficient_stack(|| {
process(tcx, param_env, callee, target, stack, seen, recursion_limiter)
process(
tcx,
param_env,
callee,
target,
stack,
seen,
recursion_limiter,
recursion_limit,
)
});
if found_recursion {
return true;
@ -122,6 +133,7 @@ crate fn mir_callgraph_reachable(
&mut Vec::new(),
&mut FxHashSet::default(),
&mut FxHashMap::default(),
tcx.recursion_limit(),
)
}