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:
commit
969a6c2481
@ -211,10 +211,6 @@ pub fn register_plugins<'a>(
|
||||
});
|
||||
}
|
||||
|
||||
sess.time("recursion_limit", || {
|
||||
middle::limits::update_limits(sess, &krate);
|
||||
});
|
||||
|
||||
let mut lint_store = rustc_lint::new_lint_store(
|
||||
sess.opts.debugging_opts.no_interleave_lints,
|
||||
sess.unstable_options(),
|
||||
@ -311,9 +307,11 @@ pub fn configure_and_expand(
|
||||
|
||||
// Create the config for macro expansion
|
||||
let features = sess.features_untracked();
|
||||
let recursion_limit =
|
||||
rustc_middle::middle::limits::get_recursion_limit(&krate.attrs, &sess);
|
||||
let cfg = rustc_expand::expand::ExpansionConfig {
|
||||
features: Some(&features),
|
||||
recursion_limit: sess.recursion_limit(),
|
||||
recursion_limit,
|
||||
trace_mac: sess.opts.debugging_opts.trace_macros,
|
||||
should_test: sess.opts.test,
|
||||
span_debug: sess.opts.debugging_opts.span_debug,
|
||||
@ -872,6 +870,13 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
|
||||
tcx.ensure().check_mod_unstable_api_usage(module);
|
||||
tcx.ensure().check_mod_const_bodies(module);
|
||||
});
|
||||
},
|
||||
{
|
||||
// We force these querie to run,
|
||||
// since they might not otherwise get called.
|
||||
// This marks the corresponding crate-level attributes
|
||||
// as used, and ensures that their values are valid.
|
||||
tcx.ensure().limits(());
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -245,6 +245,8 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl rustc_session::HashStableContext for StableHashingContext<'a> {}
|
||||
|
||||
pub fn hash_stable_trait_impls<'a>(
|
||||
hcx: &mut StableHashingContext<'a>,
|
||||
hasher: &mut StableHasher,
|
||||
|
@ -10,38 +10,46 @@
|
||||
//! just peeks and looks for that attribute.
|
||||
|
||||
use crate::bug;
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::sync::OnceCell;
|
||||
use crate::ty;
|
||||
use rustc_ast::Attribute;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::{Limit, Limits};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
|
||||
use std::num::IntErrorKind;
|
||||
|
||||
pub fn update_limits(sess: &Session, krate: &ast::Crate) {
|
||||
update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128);
|
||||
update_limit(sess, krate, &sess.move_size_limit, sym::move_size_limit, 0);
|
||||
update_limit(sess, krate, &sess.type_length_limit, sym::type_length_limit, 1048576);
|
||||
update_limit(sess, krate, &sess.const_eval_limit, sym::const_eval_limit, 1_000_000);
|
||||
pub fn provide(providers: &mut ty::query::Providers) {
|
||||
providers.limits = |tcx, ()| Limits {
|
||||
recursion_limit: get_recursion_limit(tcx.hir().krate_attrs(), tcx.sess),
|
||||
move_size_limit: get_limit(tcx.hir().krate_attrs(), tcx.sess, sym::move_size_limit, 0),
|
||||
type_length_limit: get_limit(
|
||||
tcx.hir().krate_attrs(),
|
||||
tcx.sess,
|
||||
sym::type_length_limit,
|
||||
1048576,
|
||||
),
|
||||
const_eval_limit: get_limit(
|
||||
tcx.hir().krate_attrs(),
|
||||
tcx.sess,
|
||||
sym::const_eval_limit,
|
||||
1_000_000,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn update_limit(
|
||||
sess: &Session,
|
||||
krate: &ast::Crate,
|
||||
limit: &OnceCell<impl From<usize> + std::fmt::Debug>,
|
||||
name: Symbol,
|
||||
default: usize,
|
||||
) {
|
||||
for attr in &krate.attrs {
|
||||
pub fn get_recursion_limit(krate_attrs: &[Attribute], sess: &Session) -> Limit {
|
||||
get_limit(krate_attrs, sess, sym::recursion_limit, 128)
|
||||
}
|
||||
|
||||
fn get_limit(krate_attrs: &[Attribute], sess: &Session, name: Symbol, default: usize) -> Limit {
|
||||
for attr in krate_attrs {
|
||||
if !sess.check_name(attr, name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(s) = attr.value_str() {
|
||||
match s.as_str().parse() {
|
||||
Ok(n) => {
|
||||
limit.set(From::from(n)).unwrap();
|
||||
return;
|
||||
}
|
||||
Ok(n) => return Limit::new(n),
|
||||
Err(e) => {
|
||||
let mut err =
|
||||
sess.struct_span_err(attr.span, "`limit` must be a non-negative integer");
|
||||
@ -68,5 +76,5 @@ fn update_limit(
|
||||
}
|
||||
}
|
||||
}
|
||||
limit.set(From::from(default)).unwrap();
|
||||
return Limit::new(default);
|
||||
}
|
||||
|
@ -32,3 +32,7 @@ pub mod privacy;
|
||||
pub mod region;
|
||||
pub mod resolve_lifetime;
|
||||
pub mod stability;
|
||||
|
||||
pub fn provide(providers: &mut crate::ty::query::Providers) {
|
||||
limits::provide(providers);
|
||||
}
|
||||
|
@ -1725,4 +1725,8 @@ rustc_queries! {
|
||||
query conservative_is_privately_uninhabited(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
desc { "conservatively checking if {:?} is privately uninhabited", key }
|
||||
}
|
||||
|
||||
query limits(key: ()) -> Limits {
|
||||
desc { "looking up limits" }
|
||||
}
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ use rustc_middle::ty::OpaqueTypeKey;
|
||||
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
|
||||
use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
|
||||
use rustc_session::lint::{Level, Lint};
|
||||
use rustc_session::Limit;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::def_id::StableCrateId;
|
||||
use rustc_span::source_map::MultiSpan;
|
||||
@ -1569,6 +1570,22 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
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
|
||||
|
@ -221,7 +221,7 @@ fn layout_raw<'tcx>(
|
||||
ty::tls::with_related_context(tcx, move |icx| {
|
||||
let (param_env, ty) = query.into_parts();
|
||||
|
||||
if !tcx.sess.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));
|
||||
}
|
||||
|
||||
|
@ -1987,6 +1987,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
|
||||
util::provide(providers);
|
||||
print::provide(providers);
|
||||
super::util::bug::provide(providers);
|
||||
super::middle::provide(providers);
|
||||
*providers = ty::query::Providers {
|
||||
trait_impls_of: trait_def::trait_impls_of_provider,
|
||||
type_uninhabited_from: inhabitedness::type_uninhabited_from,
|
||||
|
@ -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> {
|
||||
let type_length_limit = self.tcx.sess.type_length_limit();
|
||||
let type_length_limit = self.tcx.type_length_limit();
|
||||
if type_length_limit.value_within_limit(self.printed_type_count) {
|
||||
self.printed_type_count += 1;
|
||||
self.pretty_print_type(ty)
|
||||
|
@ -49,6 +49,7 @@ use rustc_serialize::opaque;
|
||||
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
|
||||
use rustc_session::utils::NativeLibKind;
|
||||
use rustc_session::CrateDisambiguator;
|
||||
use rustc_session::Limits;
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
|
||||
use rustc_ast as ast;
|
||||
|
@ -206,8 +206,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
mut ty: Ty<'tcx>,
|
||||
normalize: impl Fn(Ty<'tcx>) -> Ty<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let recursion_limit = self.recursion_limit();
|
||||
for iteration in 0.. {
|
||||
if !self.sess.recursion_limit().value_within_limit(iteration) {
|
||||
if !recursion_limit.value_within_limit(iteration) {
|
||||
return self.ty_error_with_message(
|
||||
DUMMY_SP,
|
||||
&format!("reached the recursion limit finding the struct tail for {}", ty),
|
||||
|
@ -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 },
|
||||
|
@ -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)
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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(),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -24,3 +24,8 @@ pub use session::*;
|
||||
pub mod output;
|
||||
|
||||
pub use getopts;
|
||||
|
||||
/// Requirements for a `StableHashingContext` to be used in this crate.
|
||||
/// This is a hack to allow using the `HashStable_Generic` derive macro
|
||||
/// instead of implementing everything in `rustc_middle`.
|
||||
pub trait HashStableContext {}
|
||||
|
@ -22,6 +22,7 @@ use rustc_errors::json::JsonEmitter;
|
||||
use rustc_errors::registry::Registry;
|
||||
use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorReported};
|
||||
use rustc_lint_defs::FutureBreakage;
|
||||
use rustc_macros::HashStable_Generic;
|
||||
pub use rustc_span::crate_disambiguator::CrateDisambiguator;
|
||||
use rustc_span::source_map::{FileLoader, MultiSpan, RealFileLoader, SourceMap, Span};
|
||||
use rustc_span::{edition::Edition, RealFileName};
|
||||
@ -66,7 +67,7 @@ pub enum CtfeBacktrace {
|
||||
|
||||
/// New-type wrapper around `usize` for representing limits. Ensures that comparisons against
|
||||
/// limits are consistent throughout the compiler.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[derive(Clone, Copy, Debug, HashStable_Generic)]
|
||||
pub struct Limit(pub usize);
|
||||
|
||||
impl Limit {
|
||||
@ -111,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
|
||||
/// session for a single crate.
|
||||
pub struct Session {
|
||||
@ -144,20 +159,6 @@ pub struct Session {
|
||||
|
||||
lint_store: OnceCell<Lrc<dyn SessionLintStore>>,
|
||||
|
||||
/// The maximum recursion limit for potentially infinitely recursive
|
||||
/// operations such as auto-dereference and monomorphization.
|
||||
pub recursion_limit: OnceCell<Limit>,
|
||||
|
||||
/// The size at which the `large_assignments` lint starts
|
||||
/// being emitted.
|
||||
pub move_size_limit: OnceCell<usize>,
|
||||
|
||||
/// The maximum length of types during monomorphization.
|
||||
pub type_length_limit: OnceCell<Limit>,
|
||||
|
||||
/// The maximum blocks a const expression can evaluate.
|
||||
pub const_eval_limit: OnceCell<Limit>,
|
||||
|
||||
incr_comp_session: OneThread<RefCell<IncrCompSession>>,
|
||||
/// Used for incremental compilation tests. Will only be populated if
|
||||
/// `-Zquery-dep-graph` is specified.
|
||||
@ -347,25 +348,6 @@ impl Session {
|
||||
self.crate_types.set(crate_types).expect("`crate_types` was initialized twice")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn recursion_limit(&self) -> Limit {
|
||||
self.recursion_limit.get().copied().unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn move_size_limit(&self) -> usize {
|
||||
self.move_size_limit.get().copied().unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn type_length_limit(&self) -> Limit {
|
||||
self.type_length_limit.get().copied().unwrap()
|
||||
}
|
||||
|
||||
pub fn const_eval_limit(&self) -> Limit {
|
||||
self.const_eval_limit.get().copied().unwrap()
|
||||
}
|
||||
|
||||
pub fn struct_span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'_> {
|
||||
self.diagnostic().struct_span_warn(sp, msg)
|
||||
}
|
||||
@ -1391,10 +1373,6 @@ pub fn build_session(
|
||||
crate_disambiguator: OnceCell::new(),
|
||||
features: OnceCell::new(),
|
||||
lint_store: OnceCell::new(),
|
||||
recursion_limit: OnceCell::new(),
|
||||
move_size_limit: OnceCell::new(),
|
||||
type_length_limit: OnceCell::new(),
|
||||
const_eval_limit: OnceCell::new(),
|
||||
incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
|
||||
cgu_reuse_tracker,
|
||||
prof,
|
||||
|
@ -53,7 +53,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
|
||||
}
|
||||
|
||||
// If we have reached the recursion limit, error gracefully.
|
||||
if !tcx.sess.recursion_limit().value_within_limit(self.state.steps.len()) {
|
||||
if !tcx.recursion_limit().value_within_limit(self.state.steps.len()) {
|
||||
if !self.silence_errors {
|
||||
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>) {
|
||||
// We've reached the recursion limit, error gracefully.
|
||||
let suggested_limit = tcx.sess.recursion_limit() * 2;
|
||||
let suggested_limit = tcx.recursion_limit() * 2;
|
||||
let msg = format!("reached the recursion limit while auto-dereferencing `{:?}`", ty);
|
||||
let error_id = (DiagnosticMessageId::ErrorId(55), Some(span), msg);
|
||||
let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
|
||||
|
@ -2310,7 +2310,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) {
|
||||
let current_limit = self.tcx.sess.recursion_limit();
|
||||
let current_limit = self.tcx.recursion_limit();
|
||||
let suggested_limit = current_limit * 2;
|
||||
err.help(&format!(
|
||||
"consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
|
||||
|
@ -344,7 +344,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
|
||||
Reveal::UserFacing => ty,
|
||||
|
||||
Reveal::All => {
|
||||
let recursion_limit = self.tcx().sess.recursion_limit();
|
||||
let recursion_limit = self.tcx().recursion_limit();
|
||||
if !recursion_limit.value_within_limit(self.depth) {
|
||||
let obligation = Obligation::with_depth(
|
||||
self.cause.clone(),
|
||||
@ -726,7 +726,7 @@ fn project_type<'cx, 'tcx>(
|
||||
) -> Result<ProjectedTy<'tcx>, ProjectionTyError<'tcx>> {
|
||||
debug!(?obligation, "project_type");
|
||||
|
||||
if !selcx.tcx().sess.recursion_limit().value_within_limit(obligation.recursion_depth) {
|
||||
if !selcx.tcx().recursion_limit().value_within_limit(obligation.recursion_depth) {
|
||||
debug!("project: overflow!");
|
||||
// This should really be an immediate error, but some existing code
|
||||
// relies on being able to recover from this.
|
||||
|
@ -116,7 +116,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
||||
Reveal::UserFacing => ty,
|
||||
|
||||
Reveal::All => {
|
||||
let recursion_limit = self.tcx().sess.recursion_limit();
|
||||
let recursion_limit = self.tcx().recursion_limit();
|
||||
if !recursion_limit.value_within_limit(self.anon_depth) {
|
||||
let obligation = Obligation::with_depth(
|
||||
self.cause.clone(),
|
||||
|
@ -993,7 +993,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
obligation: &Obligation<'tcx, T>,
|
||||
error_obligation: &Obligation<'tcx, V>,
|
||||
) -> Result<(), OverflowError> {
|
||||
if !self.infcx.tcx.sess.recursion_limit().value_within_limit(obligation.recursion_depth) {
|
||||
if !self.infcx.tcx.recursion_limit().value_within_limit(obligation.recursion_depth) {
|
||||
match self.query_mode {
|
||||
TraitQueryMode::Standard => {
|
||||
self.infcx().report_overflow_error(error_obligation, true);
|
||||
|
@ -163,7 +163,7 @@ fn dtorck_constraint_for_ty<'tcx>(
|
||||
) -> Result<(), NoSolution> {
|
||||
debug!("dtorck_constraint_for_ty({:?}, {:?}, {:?}, {:?})", span, for_ty, depth, ty);
|
||||
|
||||
if !tcx.sess.recursion_limit().value_within_limit(depth) {
|
||||
if !tcx.recursion_limit().value_within_limit(depth) {
|
||||
constraints.overflows.push(ty);
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> {
|
||||
seen_tys,
|
||||
query_ty: ty,
|
||||
unchecked_tys: vec![(ty, 0)],
|
||||
recursion_limit: tcx.sess.recursion_limit(),
|
||||
recursion_limit: tcx.recursion_limit(),
|
||||
adt_components,
|
||||
}
|
||||
}
|
||||
|
@ -2,5 +2,7 @@
|
||||
|
||||
#![recursion_limit = ""] //~ ERROR `limit` must be a non-negative integer
|
||||
//~| `limit` must be a non-negative integer
|
||||
//~| ERROR `limit` must be a non-negative integer
|
||||
//~| `limit` must be a non-negative integer
|
||||
|
||||
fn main() {}
|
||||
|
@ -6,5 +6,13 @@ LL | #![recursion_limit = ""]
|
||||
| |
|
||||
| `limit` must be a non-negative integer
|
||||
|
||||
error: aborting due to previous error
|
||||
error: `limit` must be a non-negative integer
|
||||
--> $DIR/empty.rs:3:1
|
||||
|
|
||||
LL | #![recursion_limit = ""]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^--^
|
||||
| |
|
||||
| `limit` must be a non-negative integer
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -2,5 +2,6 @@
|
||||
|
||||
#![recursion_limit = "-100"] //~ ERROR `limit` must be a non-negative integer
|
||||
//~| not a valid integer
|
||||
|
||||
//~| ERROR `limit` must be a non-negative integer
|
||||
//~| not a valid integer
|
||||
fn main() {}
|
||||
|
@ -6,5 +6,13 @@ LL | #![recursion_limit = "-100"]
|
||||
| |
|
||||
| not a valid integer
|
||||
|
||||
error: aborting due to previous error
|
||||
error: `limit` must be a non-negative integer
|
||||
--> $DIR/invalid_digit.rs:3:1
|
||||
|
|
||||
LL | #![recursion_limit = "-100"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^------^
|
||||
| |
|
||||
| not a valid integer
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -3,5 +3,7 @@
|
||||
#![recursion_limit = "999999999999999999999999"]
|
||||
//~^ ERROR `limit` must be a non-negative integer
|
||||
//~| `limit` is too large
|
||||
//~| ERROR `limit` must be a non-negative integer
|
||||
//~| `limit` is too large
|
||||
|
||||
fn main() {}
|
||||
|
@ -6,5 +6,13 @@ LL | #![recursion_limit = "999999999999999999999999"]
|
||||
| |
|
||||
| `limit` is too large
|
||||
|
||||
error: aborting due to previous error
|
||||
error: `limit` must be a non-negative integer
|
||||
--> $DIR/overflow.rs:3:1
|
||||
|
|
||||
LL | #![recursion_limit = "999999999999999999999999"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^--------------------------^
|
||||
| |
|
||||
| `limit` is too large
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user