Combine individual limit queries into single limits query

This commit is contained in:
Aaron Hill 2021-07-04 13:02:51 -05:00
parent ff15b5e2c7
commit 7e5a88a56c
No known key found for this signature in database
GPG Key ID: B4087E510E98B164
20 changed files with 75 additions and 55 deletions

View File

@ -872,13 +872,11 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
}); });
}, },
{ {
// Mark the attributes as used, and ensure that // We force these querie to run,
// they're not ill-formed. We force these queries // since they might not otherwise get called.
// to run, since they might not otherwise get called. // This marks the corresponding crate-level attributes
tcx.ensure().recursion_limit(()); // as used, and ensures that their values are valid.
tcx.ensure().move_size_limit(()); tcx.ensure().limits(());
tcx.ensure().type_length_limit(());
tcx.ensure().const_eval_limit(());
} }
); );
}); });

View File

@ -12,20 +12,29 @@
use crate::bug; use crate::bug;
use crate::ty; use crate::ty;
use rustc_ast::Attribute; use rustc_ast::Attribute;
use rustc_session::Limit;
use rustc_session::Session; use rustc_session::Session;
use rustc_session::{Limit, Limits};
use rustc_span::symbol::{sym, Symbol}; use rustc_span::symbol::{sym, Symbol};
use std::num::IntErrorKind; use std::num::IntErrorKind;
pub fn provide(providers: &mut ty::query::Providers) { pub fn provide(providers: &mut ty::query::Providers) {
providers.recursion_limit = |tcx, ()| get_recursion_limit(tcx.hir().krate_attrs(), tcx.sess); providers.limits = |tcx, ()| Limits {
providers.move_size_limit = recursion_limit: get_recursion_limit(tcx.hir().krate_attrs(), tcx.sess),
|tcx, ()| get_limit(tcx.hir().krate_attrs(), tcx.sess, sym::move_size_limit, 0).0; move_size_limit: get_limit(tcx.hir().krate_attrs(), tcx.sess, sym::move_size_limit, 0),
providers.type_length_limit = type_length_limit: get_limit(
|tcx, ()| get_limit(tcx.hir().krate_attrs(), tcx.sess, sym::type_length_limit, 1048576); tcx.hir().krate_attrs(),
providers.const_eval_limit = tcx.sess,
|tcx, ()| get_limit(tcx.hir().krate_attrs(), tcx.sess, sym::const_eval_limit, 1_000_000); sym::type_length_limit,
1048576,
),
const_eval_limit: get_limit(
tcx.hir().krate_attrs(),
tcx.sess,
sym::const_eval_limit,
1_000_000,
),
}
} }
pub fn get_recursion_limit(krate_attrs: &[Attribute], sess: &Session) -> Limit { pub fn get_recursion_limit(krate_attrs: &[Attribute], sess: &Session) -> Limit {

View File

@ -1713,25 +1713,7 @@ rustc_queries! {
desc { "conservatively checking if {:?} is privately uninhabited", key } desc { "conservatively checking if {:?} is privately uninhabited", key }
} }
/// The maximum recursion limit for potentially infinitely recursive query limits(key: ()) -> Limits {
/// operations such as auto-dereference and monomorphization. desc { "looking up limits" }
query recursion_limit(key: ()) -> Limit {
desc { "looking up recursion limit" }
}
/// The size at which the `large_assignments` lint starts
/// being emitted.
query move_size_limit(key: ()) -> usize {
desc { "looking up move size limit" }
}
/// The maximum length of types during monomorphization.
query type_length_limit(key: ()) -> Limit {
desc { "looking up type length limit" }
}
/// The maximum blocks a const expression can evaluate.
query const_eval_limit(key: ()) -> Limit {
desc { "looking up const eval limit" }
} }
} }

View File

@ -53,6 +53,7 @@ use rustc_middle::ty::OpaqueTypeKey;
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames}; use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
use rustc_session::lint::{Level, Lint}; use rustc_session::lint::{Level, Lint};
use rustc_session::Limit;
use rustc_session::Session; use rustc_session::Session;
use rustc_span::def_id::StableCrateId; use rustc_span::def_id::StableCrateId;
use rustc_span::source_map::MultiSpan; use rustc_span::source_map::MultiSpan;
@ -1569,6 +1570,22 @@ impl<'tcx> TyCtxt<'tcx> {
def_kind => (def_kind.article(), def_kind.descr(def_id)), def_kind => (def_kind.article(), def_kind.descr(def_id)),
} }
} }
pub fn type_length_limit(self) -> Limit {
self.limits(()).type_length_limit
}
pub fn recursion_limit(self) -> Limit {
self.limits(()).recursion_limit
}
pub fn move_size_limit(self) -> Limit {
self.limits(()).move_size_limit
}
pub fn const_eval_limit(self) -> Limit {
self.limits(()).const_eval_limit
}
} }
/// A trait implemented for all `X<'a>` types that can be safely and /// A trait implemented for all `X<'a>` types that can be safely and

View File

@ -221,7 +221,7 @@ fn layout_raw<'tcx>(
ty::tls::with_related_context(tcx, move |icx| { ty::tls::with_related_context(tcx, move |icx| {
let (param_env, ty) = query.into_parts(); let (param_env, ty) = query.into_parts();
if !tcx.recursion_limit(()).value_within_limit(icx.layout_depth) { if !tcx.recursion_limit().value_within_limit(icx.layout_depth) {
tcx.sess.fatal(&format!("overflow representing the type `{}`", ty)); tcx.sess.fatal(&format!("overflow representing the type `{}`", ty));
} }

View File

@ -1437,7 +1437,7 @@ impl<F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> {
} }
fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> { fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
let type_length_limit = self.tcx.type_length_limit(()); let type_length_limit = self.tcx.type_length_limit();
if type_length_limit.value_within_limit(self.printed_type_count) { if type_length_limit.value_within_limit(self.printed_type_count) {
self.printed_type_count += 1; self.printed_type_count += 1;
self.pretty_print_type(ty) self.pretty_print_type(ty)

View File

@ -49,7 +49,7 @@ use rustc_serialize::opaque;
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
use rustc_session::utils::NativeLibKind; use rustc_session::utils::NativeLibKind;
use rustc_session::CrateDisambiguator; use rustc_session::CrateDisambiguator;
use rustc_session::Limit; use rustc_session::Limits;
use rustc_target::spec::PanicStrategy; use rustc_target::spec::PanicStrategy;
use rustc_ast as ast; use rustc_ast as ast;

View File

@ -206,7 +206,7 @@ impl<'tcx> TyCtxt<'tcx> {
mut ty: Ty<'tcx>, mut ty: Ty<'tcx>,
normalize: impl Fn(Ty<'tcx>) -> Ty<'tcx>, normalize: impl Fn(Ty<'tcx>) -> Ty<'tcx>,
) -> Ty<'tcx> { ) -> Ty<'tcx> {
let recursion_limit = self.recursion_limit(()); let recursion_limit = self.recursion_limit();
for iteration in 0.. { for iteration in 0.. {
if !recursion_limit.value_within_limit(iteration) { if !recursion_limit.value_within_limit(iteration) {
return self.ty_error_with_message( return self.ty_error_with_message(

View File

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

View File

@ -392,7 +392,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
tcx: tcx.at(root_span), tcx: tcx.at(root_span),
param_env, param_env,
memory: Memory::new(tcx, memory_extra), memory: Memory::new(tcx, memory_extra),
recursion_limit: tcx.recursion_limit(()), recursion_limit: tcx.recursion_limit(),
} }
} }

View File

@ -295,7 +295,7 @@ pub fn collect_crate_mono_items(
let mut visited = MTLock::new(FxHashSet::default()); let mut visited = MTLock::new(FxHashSet::default());
let mut inlining_map = MTLock::new(InliningMap::new()); let mut inlining_map = MTLock::new(InliningMap::new());
let recursion_limit = tcx.recursion_limit(()); let recursion_limit = tcx.recursion_limit();
{ {
let visited: MTRef<'_, _> = &mut visited; let visited: MTRef<'_, _> = &mut visited;
@ -587,7 +587,7 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
// which means that rustc basically hangs. // which means that rustc basically hangs.
// //
// Bail out in these cases to avoid that bad user experience. // Bail out in these cases to avoid that bad user experience.
if !tcx.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 (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32);
let msg = format!("reached the type-length limit while instantiating `{}`", shrunk); 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); let mut diag = tcx.sess.struct_span_fatal(tcx.def_span(instance.def_id()), &msg);
@ -824,7 +824,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) { fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) {
self.super_operand(operand, location); self.super_operand(operand, location);
let limit = self.tcx.move_size_limit(()); let limit = self.tcx.move_size_limit().0;
if limit == 0 { if limit == 0 {
return; return;
} }

View File

@ -133,7 +133,7 @@ crate fn mir_callgraph_reachable(
&mut Vec::new(), &mut Vec::new(),
&mut FxHashSet::default(), &mut FxHashSet::default(),
&mut FxHashMap::default(), &mut FxHashMap::default(),
tcx.recursion_limit(()), tcx.recursion_limit(),
) )
} }

View File

@ -112,6 +112,20 @@ impl Mul<usize> for Limit {
} }
} }
#[derive(Clone, Copy, Debug, HashStable_Generic)]
pub struct Limits {
/// The maximum recursion limit for potentially infinitely recursive
/// operations such as auto-dereference and monomorphization.
pub recursion_limit: Limit,
/// The size at which the `large_assignments` lint starts
/// being emitted.
pub move_size_limit: Limit,
/// The maximum length of types during monomorphization.
pub type_length_limit: Limit,
/// The maximum blocks a const expression can evaluate.
pub const_eval_limit: Limit,
}
/// Represents the data associated with a compilation /// Represents the data associated with a compilation
/// session for a single crate. /// session for a single crate.
pub struct Session { pub struct Session {

View File

@ -53,7 +53,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
} }
// If we have reached the recursion limit, error gracefully. // If we have reached the recursion limit, error gracefully.
if !tcx.recursion_limit(()).value_within_limit(self.state.steps.len()) { if !tcx.recursion_limit().value_within_limit(self.state.steps.len()) {
if !self.silence_errors { if !self.silence_errors {
report_autoderef_recursion_limit_error(tcx, self.span, self.state.cur_ty); report_autoderef_recursion_limit_error(tcx, self.span, self.state.cur_ty);
} }
@ -217,7 +217,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) { pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) {
// We've reached the recursion limit, error gracefully. // We've reached the recursion limit, error gracefully.
let suggested_limit = tcx.recursion_limit(()) * 2; let suggested_limit = tcx.recursion_limit() * 2;
let msg = format!("reached the recursion limit while auto-dereferencing `{:?}`", ty); let msg = format!("reached the recursion limit while auto-dereferencing `{:?}`", ty);
let error_id = (DiagnosticMessageId::ErrorId(55), Some(span), msg); let error_id = (DiagnosticMessageId::ErrorId(55), Some(span), msg);
let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id); let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);

View File

@ -2310,7 +2310,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
} }
fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) { fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) {
let current_limit = self.tcx.recursion_limit(()); let current_limit = self.tcx.recursion_limit();
let suggested_limit = current_limit * 2; let suggested_limit = current_limit * 2;
err.help(&format!( err.help(&format!(
"consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)", "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",

View File

@ -344,7 +344,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
Reveal::UserFacing => ty, Reveal::UserFacing => ty,
Reveal::All => { Reveal::All => {
let recursion_limit = self.tcx().recursion_limit(()); let recursion_limit = self.tcx().recursion_limit();
if !recursion_limit.value_within_limit(self.depth) { if !recursion_limit.value_within_limit(self.depth) {
let obligation = Obligation::with_depth( let obligation = Obligation::with_depth(
self.cause.clone(), self.cause.clone(),
@ -726,7 +726,7 @@ fn project_type<'cx, 'tcx>(
) -> Result<ProjectedTy<'tcx>, ProjectionTyError<'tcx>> { ) -> Result<ProjectedTy<'tcx>, ProjectionTyError<'tcx>> {
debug!(?obligation, "project_type"); debug!(?obligation, "project_type");
if !selcx.tcx().recursion_limit(()).value_within_limit(obligation.recursion_depth) { if !selcx.tcx().recursion_limit().value_within_limit(obligation.recursion_depth) {
debug!("project: overflow!"); debug!("project: overflow!");
// This should really be an immediate error, but some existing code // This should really be an immediate error, but some existing code
// relies on being able to recover from this. // relies on being able to recover from this.

View File

@ -116,7 +116,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
Reveal::UserFacing => ty, Reveal::UserFacing => ty,
Reveal::All => { Reveal::All => {
let recursion_limit = self.tcx().recursion_limit(()); let recursion_limit = self.tcx().recursion_limit();
if !recursion_limit.value_within_limit(self.anon_depth) { if !recursion_limit.value_within_limit(self.anon_depth) {
let obligation = Obligation::with_depth( let obligation = Obligation::with_depth(
self.cause.clone(), self.cause.clone(),

View File

@ -993,7 +993,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation: &Obligation<'tcx, T>, obligation: &Obligation<'tcx, T>,
error_obligation: &Obligation<'tcx, V>, error_obligation: &Obligation<'tcx, V>,
) -> Result<(), OverflowError> { ) -> Result<(), OverflowError> {
if !self.infcx.tcx.recursion_limit(()).value_within_limit(obligation.recursion_depth) { if !self.infcx.tcx.recursion_limit().value_within_limit(obligation.recursion_depth) {
match self.query_mode { match self.query_mode {
TraitQueryMode::Standard => { TraitQueryMode::Standard => {
self.infcx().report_overflow_error(error_obligation, true); self.infcx().report_overflow_error(error_obligation, true);

View File

@ -163,7 +163,7 @@ fn dtorck_constraint_for_ty<'tcx>(
) -> Result<(), NoSolution> { ) -> Result<(), NoSolution> {
debug!("dtorck_constraint_for_ty({:?}, {:?}, {:?}, {:?})", span, for_ty, depth, ty); debug!("dtorck_constraint_for_ty({:?}, {:?}, {:?}, {:?})", span, for_ty, depth, ty);
if !tcx.recursion_limit(()).value_within_limit(depth) { if !tcx.recursion_limit().value_within_limit(depth) {
constraints.overflows.push(ty); constraints.overflows.push(ty);
return Ok(()); return Ok(());
} }

View File

@ -63,7 +63,7 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> {
seen_tys, seen_tys,
query_ty: ty, query_ty: ty,
unchecked_tys: vec![(ty, 0)], unchecked_tys: vec![(ty, 0)],
recursion_limit: tcx.recursion_limit(()), recursion_limit: tcx.recursion_limit(),
adt_components, adt_components,
} }
} }