diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index a5d97ef4111..a7bfffbc38a 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -872,13 +872,11 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { }); }, { - // 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(()); + // 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(()); } ); }); diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs index eb706b57004..c4bfd0ebb2f 100644 --- a/compiler/rustc_middle/src/middle/limits.rs +++ b/compiler/rustc_middle/src/middle/limits.rs @@ -12,20 +12,29 @@ use crate::bug; use crate::ty; use rustc_ast::Attribute; -use rustc_session::Limit; use rustc_session::Session; +use rustc_session::{Limit, Limits}; use rustc_span::symbol::{sym, Symbol}; use std::num::IntErrorKind; pub fn provide(providers: &mut ty::query::Providers) { - providers.recursion_limit = |tcx, ()| get_recursion_limit(tcx.hir().krate_attrs(), tcx.sess); - providers.move_size_limit = - |tcx, ()| get_limit(tcx.hir().krate_attrs(), tcx.sess, sym::move_size_limit, 0).0; - 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); + 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, + ), + } } pub fn get_recursion_limit(krate_attrs: &[Attribute], sess: &Session) -> Limit { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 189cd5e589d..3db413194b3 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1713,25 +1713,7 @@ rustc_queries! { 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" } + query limits(key: ()) -> Limits { + desc { "looking up limits" } } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 257912ad57e..932187e15f4 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -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 diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index b08888006bc..dbb5064c4f5 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -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.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)); } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index efeb0ea5bef..cb326996111 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1437,7 +1437,7 @@ impl Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { } fn print_type(mut self, ty: Ty<'tcx>) -> Result { - 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) { self.printed_type_count += 1; self.pretty_print_type(ty) diff --git a/compiler/rustc_middle/src/ty/query/mod.rs b/compiler/rustc_middle/src/ty/query/mod.rs index e9a5709543f..875453bb80b 100644 --- a/compiler/rustc_middle/src/ty/query/mod.rs +++ b/compiler/rustc_middle/src/ty/query/mod.rs @@ -49,7 +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::Limit; +use rustc_session::Limits; use rustc_target::spec::PanicStrategy; use rustc_ast as ast; diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index ada5d059814..17acb508de3 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -206,7 +206,7 @@ impl<'tcx> TyCtxt<'tcx> { mut ty: Ty<'tcx>, normalize: impl Fn(Ty<'tcx>) -> Ty<'tcx>, ) -> Ty<'tcx> { - let recursion_limit = self.recursion_limit(()); + let recursion_limit = self.recursion_limit(); for iteration in 0.. { if !recursion_limit.value_within_limit(iteration) { return self.ty_error_with_message( diff --git a/compiler/rustc_mir/src/const_eval/eval_queries.rs b/compiler/rustc_mir/src/const_eval/eval_queries.rs index 078f4cf7477..c1c26d4e810 100644 --- a/compiler/rustc_mir/src/const_eval/eval_queries.rs +++ b/compiler/rustc_mir/src/const_eval/eval_queries.rs @@ -98,7 +98,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>( tcx, root_span, param_env, - CompileTimeInterpreter::new(tcx.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.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 }, diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs index 3a77b30a328..227abeb7e7c 100644 --- a/compiler/rustc_mir/src/interpret/eval_context.rs +++ b/compiler/rustc_mir/src/interpret/eval_context.rs @@ -392,7 +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(()), + recursion_limit: tcx.recursion_limit(), } } diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs index 698cf765e49..ced35d47b11 100644 --- a/compiler/rustc_mir/src/monomorphize/collector.rs +++ b/compiler/rustc_mir/src/monomorphize/collector.rs @@ -295,7 +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 recursion_limit = tcx.recursion_limit(); { 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. // // 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 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); @@ -824,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.move_size_limit(()); + let limit = self.tcx.move_size_limit().0; if limit == 0 { return; } diff --git a/compiler/rustc_mir/src/transform/inline/cycle.rs b/compiler/rustc_mir/src/transform/inline/cycle.rs index 106e3fd4985..c9eafafff57 100644 --- a/compiler/rustc_mir/src/transform/inline/cycle.rs +++ b/compiler/rustc_mir/src/transform/inline/cycle.rs @@ -133,7 +133,7 @@ crate fn mir_callgraph_reachable( &mut Vec::new(), &mut FxHashSet::default(), &mut FxHashMap::default(), - tcx.recursion_limit(()), + tcx.recursion_limit(), ) } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 609144f7411..70dddfb6704 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -112,6 +112,20 @@ impl Mul 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 { diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs index 3b12b6fcf2a..969962e55b0 100644 --- a/compiler/rustc_trait_selection/src/autoderef.rs +++ b/compiler/rustc_trait_selection/src/autoderef.rs @@ -53,7 +53,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> { } // 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 { 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.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); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 11092c365d1..dd84a81a651 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -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.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 (`{}`)", diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index e76f3368360..0e685205069 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -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().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, ProjectionTyError<'tcx>> { 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!"); // This should really be an immediate error, but some existing code // relies on being able to recover from this. diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index be34b67d979..6673e021bf3 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -116,7 +116,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { Reveal::UserFacing => ty, 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) { let obligation = Obligation::with_depth( self.cause.clone(), diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 54f74b74edc..708688fa8a6 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -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.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); diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs index a4930ba4507..4a41dfe0143 100644 --- a/compiler/rustc_traits/src/dropck_outlives.rs +++ b/compiler/rustc_traits/src/dropck_outlives.rs @@ -163,7 +163,7 @@ fn dtorck_constraint_for_ty<'tcx>( ) -> Result<(), NoSolution> { 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); return Ok(()); } diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 3d4a455ff61..d837af85d58 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -63,7 +63,7 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> { seen_tys, query_ty: ty, unchecked_tys: vec![(ty, 0)], - recursion_limit: tcx.recursion_limit(()), + recursion_limit: tcx.recursion_limit(), adt_components, } }