Query-ify global limit attribute handling
This commit is contained in:
parent
90442458ac
commit
ff15b5e2c7
30 changed files with 153 additions and 91 deletions
|
@ -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(
|
let mut lint_store = rustc_lint::new_lint_store(
|
||||||
sess.opts.debugging_opts.no_interleave_lints,
|
sess.opts.debugging_opts.no_interleave_lints,
|
||||||
sess.unstable_options(),
|
sess.unstable_options(),
|
||||||
|
@ -311,9 +307,11 @@ pub fn configure_and_expand(
|
||||||
|
|
||||||
// Create the config for macro expansion
|
// Create the config for macro expansion
|
||||||
let features = sess.features_untracked();
|
let features = sess.features_untracked();
|
||||||
|
let recursion_limit =
|
||||||
|
rustc_middle::middle::limits::get_recursion_limit(&krate.attrs, &sess);
|
||||||
let cfg = rustc_expand::expand::ExpansionConfig {
|
let cfg = rustc_expand::expand::ExpansionConfig {
|
||||||
features: Some(&features),
|
features: Some(&features),
|
||||||
recursion_limit: sess.recursion_limit(),
|
recursion_limit,
|
||||||
trace_mac: sess.opts.debugging_opts.trace_macros,
|
trace_mac: sess.opts.debugging_opts.trace_macros,
|
||||||
should_test: sess.opts.test,
|
should_test: sess.opts.test,
|
||||||
span_debug: sess.opts.debugging_opts.span_debug,
|
span_debug: sess.opts.debugging_opts.span_debug,
|
||||||
|
@ -872,6 +870,15 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
|
||||||
tcx.ensure().check_mod_unstable_api_usage(module);
|
tcx.ensure().check_mod_unstable_api_usage(module);
|
||||||
tcx.ensure().check_mod_const_bodies(module);
|
tcx.ensure().check_mod_const_bodies(module);
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Mark the attributes as used, and ensure that
|
||||||
|
// they're not ill-formed. We force these queries
|
||||||
|
// to run, since they might not otherwise get called.
|
||||||
|
tcx.ensure().recursion_limit(());
|
||||||
|
tcx.ensure().move_size_limit(());
|
||||||
|
tcx.ensure().type_length_limit(());
|
||||||
|
tcx.ensure().const_eval_limit(());
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -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>(
|
pub fn hash_stable_trait_impls<'a>(
|
||||||
hcx: &mut StableHashingContext<'a>,
|
hcx: &mut StableHashingContext<'a>,
|
||||||
hasher: &mut StableHasher,
|
hasher: &mut StableHasher,
|
||||||
|
|
|
@ -10,38 +10,37 @@
|
||||||
//! just peeks and looks for that attribute.
|
//! just peeks and looks for that attribute.
|
||||||
|
|
||||||
use crate::bug;
|
use crate::bug;
|
||||||
use rustc_ast as ast;
|
use crate::ty;
|
||||||
use rustc_data_structures::sync::OnceCell;
|
use rustc_ast::Attribute;
|
||||||
|
use rustc_session::Limit;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::symbol::{sym, Symbol};
|
use rustc_span::symbol::{sym, Symbol};
|
||||||
|
|
||||||
use std::num::IntErrorKind;
|
use std::num::IntErrorKind;
|
||||||
|
|
||||||
pub fn update_limits(sess: &Session, krate: &ast::Crate) {
|
pub fn provide(providers: &mut ty::query::Providers) {
|
||||||
update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128);
|
providers.recursion_limit = |tcx, ()| get_recursion_limit(tcx.hir().krate_attrs(), tcx.sess);
|
||||||
update_limit(sess, krate, &sess.move_size_limit, sym::move_size_limit, 0);
|
providers.move_size_limit =
|
||||||
update_limit(sess, krate, &sess.type_length_limit, sym::type_length_limit, 1048576);
|
|tcx, ()| get_limit(tcx.hir().krate_attrs(), tcx.sess, sym::move_size_limit, 0).0;
|
||||||
update_limit(sess, krate, &sess.const_eval_limit, sym::const_eval_limit, 1_000_000);
|
providers.type_length_limit =
|
||||||
|
|tcx, ()| get_limit(tcx.hir().krate_attrs(), tcx.sess, sym::type_length_limit, 1048576);
|
||||||
|
providers.const_eval_limit =
|
||||||
|
|tcx, ()| get_limit(tcx.hir().krate_attrs(), tcx.sess, sym::const_eval_limit, 1_000_000);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_limit(
|
pub fn get_recursion_limit(krate_attrs: &[Attribute], sess: &Session) -> Limit {
|
||||||
sess: &Session,
|
get_limit(krate_attrs, sess, sym::recursion_limit, 128)
|
||||||
krate: &ast::Crate,
|
}
|
||||||
limit: &OnceCell<impl From<usize> + std::fmt::Debug>,
|
|
||||||
name: Symbol,
|
fn get_limit(krate_attrs: &[Attribute], sess: &Session, name: Symbol, default: usize) -> Limit {
|
||||||
default: usize,
|
for attr in krate_attrs {
|
||||||
) {
|
|
||||||
for attr in &krate.attrs {
|
|
||||||
if !sess.check_name(attr, name) {
|
if !sess.check_name(attr, name) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(s) = attr.value_str() {
|
if let Some(s) = attr.value_str() {
|
||||||
match s.as_str().parse() {
|
match s.as_str().parse() {
|
||||||
Ok(n) => {
|
Ok(n) => return Limit::new(n),
|
||||||
limit.set(From::from(n)).unwrap();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let mut err =
|
let mut err =
|
||||||
sess.struct_span_err(attr.span, "`limit` must be a non-negative integer");
|
sess.struct_span_err(attr.span, "`limit` must be a non-negative integer");
|
||||||
|
@ -68,5 +67,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 region;
|
||||||
pub mod resolve_lifetime;
|
pub mod resolve_lifetime;
|
||||||
pub mod stability;
|
pub mod stability;
|
||||||
|
|
||||||
|
pub fn provide(providers: &mut crate::ty::query::Providers) {
|
||||||
|
limits::provide(providers);
|
||||||
|
}
|
||||||
|
|
|
@ -1712,4 +1712,26 @@ rustc_queries! {
|
||||||
query conservative_is_privately_uninhabited(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
query conservative_is_privately_uninhabited(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||||
desc { "conservatively checking if {:?} is privately uninhabited", key }
|
desc { "conservatively checking if {:?} is privately uninhabited", key }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The maximum recursion limit for potentially infinitely recursive
|
||||||
|
/// operations such as auto-dereference and monomorphization.
|
||||||
|
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" }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.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));
|
tcx.sess.fatal(&format!("overflow representing the type `{}`", ty));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1987,6 +1987,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
|
||||||
util::provide(providers);
|
util::provide(providers);
|
||||||
print::provide(providers);
|
print::provide(providers);
|
||||||
super::util::bug::provide(providers);
|
super::util::bug::provide(providers);
|
||||||
|
super::middle::provide(providers);
|
||||||
*providers = ty::query::Providers {
|
*providers = ty::query::Providers {
|
||||||
trait_impls_of: trait_def::trait_impls_of_provider,
|
trait_impls_of: trait_def::trait_impls_of_provider,
|
||||||
type_uninhabited_from: inhabitedness::type_uninhabited_from,
|
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> {
|
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) {
|
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)
|
||||||
|
|
|
@ -49,6 +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_target::spec::PanicStrategy;
|
use rustc_target::spec::PanicStrategy;
|
||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
|
|
|
@ -206,8 +206,9 @@ 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(());
|
||||||
for iteration in 0.. {
|
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(
|
return self.ty_error_with_message(
|
||||||
DUMMY_SP,
|
DUMMY_SP,
|
||||||
&format!("reached the recursion limit finding the struct tail for {}", ty),
|
&format!("reached the recursion limit finding the struct tail for {}", ty),
|
||||||
|
|
|
@ -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.sess.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.sess.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 },
|
||||||
|
|
|
@ -393,7 +393,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
||||||
frame: Frame<'mir, 'tcx>,
|
frame: Frame<'mir, 'tcx>,
|
||||||
) -> InterpResult<'tcx, Frame<'mir, 'tcx>> {
|
) -> InterpResult<'tcx, Frame<'mir, 'tcx>> {
|
||||||
// Enforce stack size limit. Add 1 because this is run before the new frame is pushed.
|
// 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)
|
throw_exhaust!(StackFrameLimitReached)
|
||||||
} else {
|
} else {
|
||||||
Ok(frame)
|
Ok(frame)
|
||||||
|
|
|
@ -13,6 +13,7 @@ use rustc_middle::ty::layout::{self, TyAndLayout};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
|
self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
|
||||||
};
|
};
|
||||||
|
use rustc_session::Limit;
|
||||||
use rustc_span::{Pos, Span};
|
use rustc_span::{Pos, Span};
|
||||||
use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size, TargetDataLayout};
|
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.
|
/// The virtual memory system.
|
||||||
pub memory: Memory<'mir, 'tcx, M>,
|
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
|
// 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),
|
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(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyContext};
|
||||||
use rustc_session::config::EntryFnType;
|
use rustc_session::config::EntryFnType;
|
||||||
use rustc_session::lint::builtin::LARGE_ASSIGNMENTS;
|
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_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP};
|
||||||
use rustc_target::abi::Size;
|
use rustc_target::abi::Size;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
@ -294,6 +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 visited: MTRef<'_, _> = &mut visited;
|
let visited: MTRef<'_, _> = &mut visited;
|
||||||
|
@ -307,6 +309,7 @@ pub fn collect_crate_mono_items(
|
||||||
dummy_spanned(root),
|
dummy_spanned(root),
|
||||||
visited,
|
visited,
|
||||||
&mut recursion_depths,
|
&mut recursion_depths,
|
||||||
|
recursion_limit,
|
||||||
inlining_map,
|
inlining_map,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -350,6 +353,7 @@ fn collect_items_rec<'tcx>(
|
||||||
starting_point: Spanned<MonoItem<'tcx>>,
|
starting_point: Spanned<MonoItem<'tcx>>,
|
||||||
visited: MTRef<'_, MTLock<FxHashSet<MonoItem<'tcx>>>>,
|
visited: MTRef<'_, MTLock<FxHashSet<MonoItem<'tcx>>>>,
|
||||||
recursion_depths: &mut DefIdMap<usize>,
|
recursion_depths: &mut DefIdMap<usize>,
|
||||||
|
recursion_limit: Limit,
|
||||||
inlining_map: MTRef<'_, MTLock<InliningMap<'tcx>>>,
|
inlining_map: MTRef<'_, MTLock<InliningMap<'tcx>>>,
|
||||||
) {
|
) {
|
||||||
if !visited.lock_mut().insert(starting_point.node) {
|
if !visited.lock_mut().insert(starting_point.node) {
|
||||||
|
@ -409,8 +413,13 @@ fn collect_items_rec<'tcx>(
|
||||||
debug_assert!(should_codegen_locally(tcx, &instance));
|
debug_assert!(should_codegen_locally(tcx, &instance));
|
||||||
|
|
||||||
// Keep track of the monomorphization recursion depth
|
// Keep track of the monomorphization recursion depth
|
||||||
recursion_depth_reset =
|
recursion_depth_reset = Some(check_recursion_limit(
|
||||||
Some(check_recursion_limit(tcx, instance, starting_point.span, recursion_depths));
|
tcx,
|
||||||
|
instance,
|
||||||
|
starting_point.span,
|
||||||
|
recursion_depths,
|
||||||
|
recursion_limit,
|
||||||
|
));
|
||||||
check_type_length_limit(tcx, instance);
|
check_type_length_limit(tcx, instance);
|
||||||
|
|
||||||
rustc_data_structures::stack::ensure_sufficient_stack(|| {
|
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);
|
record_accesses(tcx, starting_point.node, neighbors.iter().map(|i| &i.node), inlining_map);
|
||||||
|
|
||||||
for neighbour in neighbors {
|
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 {
|
if let Some((def_id, depth)) = recursion_depth_reset {
|
||||||
|
@ -523,6 +532,7 @@ fn check_recursion_limit<'tcx>(
|
||||||
instance: Instance<'tcx>,
|
instance: Instance<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
recursion_depths: &mut DefIdMap<usize>,
|
recursion_depths: &mut DefIdMap<usize>,
|
||||||
|
recursion_limit: Limit,
|
||||||
) -> (DefId, usize) {
|
) -> (DefId, usize) {
|
||||||
let def_id = instance.def_id();
|
let def_id = instance.def_id();
|
||||||
let recursion_depth = recursion_depths.get(&def_id).cloned().unwrap_or(0);
|
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
|
// Code that needs to instantiate the same function recursively
|
||||||
// more than the recursion limit is assumed to be causing an
|
// more than the recursion limit is assumed to be causing an
|
||||||
// infinite expansion.
|
// 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 (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32);
|
||||||
let error = format!("reached the recursion limit while instantiating `{}`", shrunk);
|
let error = format!("reached the recursion limit while instantiating `{}`", shrunk);
|
||||||
let mut err = tcx.sess.struct_span_fatal(span, &error);
|
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.
|
// 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.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 (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);
|
||||||
|
@ -814,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.sess.move_size_limit();
|
let limit = self.tcx.move_size_limit(());
|
||||||
if limit == 0 {
|
if limit == 0 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_middle::mir::TerminatorKind;
|
use rustc_middle::mir::TerminatorKind;
|
||||||
use rustc_middle::ty::TypeFoldable;
|
use rustc_middle::ty::TypeFoldable;
|
||||||
use rustc_middle::ty::{self, subst::SubstsRef, InstanceDef, TyCtxt};
|
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
|
// FIXME: check whether it is cheaper to precompute the entire call graph instead of invoking
|
||||||
// this query riddiculously often.
|
// this query riddiculously often.
|
||||||
|
@ -30,7 +31,7 @@ crate fn mir_callgraph_reachable(
|
||||||
);
|
);
|
||||||
#[instrument(
|
#[instrument(
|
||||||
level = "debug",
|
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(
|
fn process(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
|
@ -40,6 +41,7 @@ crate fn mir_callgraph_reachable(
|
||||||
stack: &mut Vec<ty::Instance<'tcx>>,
|
stack: &mut Vec<ty::Instance<'tcx>>,
|
||||||
seen: &mut FxHashSet<ty::Instance<'tcx>>,
|
seen: &mut FxHashSet<ty::Instance<'tcx>>,
|
||||||
recursion_limiter: &mut FxHashMap<DefId, usize>,
|
recursion_limiter: &mut FxHashMap<DefId, usize>,
|
||||||
|
recursion_limit: Limit,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
trace!(%caller);
|
trace!(%caller);
|
||||||
for &(callee, substs) in tcx.mir_inliner_callees(caller.def) {
|
for &(callee, substs) in tcx.mir_inliner_callees(caller.def) {
|
||||||
|
@ -96,11 +98,20 @@ crate fn mir_callgraph_reachable(
|
||||||
if seen.insert(callee) {
|
if seen.insert(callee) {
|
||||||
let recursion = recursion_limiter.entry(callee.def_id()).or_default();
|
let recursion = recursion_limiter.entry(callee.def_id()).or_default();
|
||||||
trace!(?callee, recursion = *recursion);
|
trace!(?callee, recursion = *recursion);
|
||||||
if tcx.sess.recursion_limit().value_within_limit(*recursion) {
|
if recursion_limit.value_within_limit(*recursion) {
|
||||||
*recursion += 1;
|
*recursion += 1;
|
||||||
stack.push(callee);
|
stack.push(callee);
|
||||||
let found_recursion = ensure_sufficient_stack(|| {
|
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 {
|
if found_recursion {
|
||||||
return true;
|
return true;
|
||||||
|
@ -122,6 +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(()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,3 +24,8 @@ pub use session::*;
|
||||||
pub mod output;
|
pub mod output;
|
||||||
|
|
||||||
pub use getopts;
|
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::registry::Registry;
|
||||||
use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorReported};
|
use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorReported};
|
||||||
use rustc_lint_defs::FutureBreakage;
|
use rustc_lint_defs::FutureBreakage;
|
||||||
|
use rustc_macros::HashStable_Generic;
|
||||||
pub use rustc_span::crate_disambiguator::CrateDisambiguator;
|
pub use rustc_span::crate_disambiguator::CrateDisambiguator;
|
||||||
use rustc_span::source_map::{FileLoader, MultiSpan, RealFileLoader, SourceMap, Span};
|
use rustc_span::source_map::{FileLoader, MultiSpan, RealFileLoader, SourceMap, Span};
|
||||||
use rustc_span::{edition::Edition, RealFileName};
|
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
|
/// New-type wrapper around `usize` for representing limits. Ensures that comparisons against
|
||||||
/// limits are consistent throughout the compiler.
|
/// limits are consistent throughout the compiler.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug, HashStable_Generic)]
|
||||||
pub struct Limit(pub usize);
|
pub struct Limit(pub usize);
|
||||||
|
|
||||||
impl Limit {
|
impl Limit {
|
||||||
|
@ -144,20 +145,6 @@ pub struct Session {
|
||||||
|
|
||||||
lint_store: OnceCell<Lrc<dyn SessionLintStore>>,
|
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>>,
|
incr_comp_session: OneThread<RefCell<IncrCompSession>>,
|
||||||
/// Used for incremental compilation tests. Will only be populated if
|
/// Used for incremental compilation tests. Will only be populated if
|
||||||
/// `-Zquery-dep-graph` is specified.
|
/// `-Zquery-dep-graph` is specified.
|
||||||
|
@ -347,25 +334,6 @@ impl Session {
|
||||||
self.crate_types.set(crate_types).expect("`crate_types` was initialized twice")
|
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<'_> {
|
pub fn struct_span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'_> {
|
||||||
self.diagnostic().struct_span_warn(sp, msg)
|
self.diagnostic().struct_span_warn(sp, msg)
|
||||||
}
|
}
|
||||||
|
@ -1391,10 +1359,6 @@ pub fn build_session(
|
||||||
crate_disambiguator: OnceCell::new(),
|
crate_disambiguator: OnceCell::new(),
|
||||||
features: OnceCell::new(),
|
features: OnceCell::new(),
|
||||||
lint_store: 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)),
|
incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
|
||||||
cgu_reuse_tracker,
|
cgu_reuse_tracker,
|
||||||
prof,
|
prof,
|
||||||
|
|
|
@ -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.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 {
|
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.sess.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);
|
||||||
|
|
|
@ -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.sess.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 (`{}`)",
|
||||||
|
|
|
@ -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().sess.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().sess.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.
|
||||||
|
|
|
@ -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().sess.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(),
|
||||||
|
|
|
@ -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.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 {
|
match self.query_mode {
|
||||||
TraitQueryMode::Standard => {
|
TraitQueryMode::Standard => {
|
||||||
self.infcx().report_overflow_error(error_obligation, true);
|
self.infcx().report_overflow_error(error_obligation, true);
|
||||||
|
|
|
@ -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.sess.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(());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.sess.recursion_limit(),
|
recursion_limit: tcx.recursion_limit(()),
|
||||||
adt_components,
|
adt_components,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,5 +2,7 @@
|
||||||
|
|
||||||
#![recursion_limit = ""] //~ ERROR `limit` must be a non-negative integer
|
#![recursion_limit = ""] //~ ERROR `limit` must be a non-negative integer
|
||||||
//~| `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() {}
|
fn main() {}
|
||||||
|
|
|
@ -6,5 +6,13 @@ LL | #![recursion_limit = ""]
|
||||||
| |
|
| |
|
||||||
| `limit` must be a non-negative integer
|
| `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
|
#![recursion_limit = "-100"] //~ ERROR `limit` must be a non-negative integer
|
||||||
//~| not a valid integer
|
//~| not a valid integer
|
||||||
|
//~| ERROR `limit` must be a non-negative integer
|
||||||
|
//~| not a valid integer
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -6,5 +6,13 @@ LL | #![recursion_limit = "-100"]
|
||||||
| |
|
| |
|
||||||
| not a valid integer
|
| 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"]
|
#![recursion_limit = "999999999999999999999999"]
|
||||||
//~^ ERROR `limit` must be a non-negative integer
|
//~^ ERROR `limit` must be a non-negative integer
|
||||||
//~| `limit` is too large
|
//~| `limit` is too large
|
||||||
|
//~| ERROR `limit` must be a non-negative integer
|
||||||
|
//~| `limit` is too large
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -6,5 +6,13 @@ LL | #![recursion_limit = "999999999999999999999999"]
|
||||||
| |
|
| |
|
||||||
| `limit` is too large
|
| `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…
Add table
Add a link
Reference in a new issue