about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorAaron Hill <aa1ronham@gmail.com>2021-06-25 18:48:26 -0500
committerAaron Hill <aa1ronham@gmail.com>2021-07-04 12:33:14 -0500
commitff15b5e2c76bb5c0fdd64e49ee76fbd2023415bd (patch)
tree8ffd85d54373d3a3f22cd528d948ec7fde919b2f /compiler
parent90442458ac46b1d5eed752c316da25450f67285b (diff)
downloadrust-ff15b5e2c76bb5c0fdd64e49ee76fbd2023415bd.tar.gz
rust-ff15b5e2c76bb5c0fdd64e49ee76fbd2023415bd.zip
Query-ify global limit attribute handling
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_interface/src/passes.rs17
-rw-r--r--compiler/rustc_middle/src/ich/hcx.rs2
-rw-r--r--compiler/rustc_middle/src/middle/limits.rs39
-rw-r--r--compiler/rustc_middle/src/middle/mod.rs4
-rw-r--r--compiler/rustc_middle/src/query/mod.rs22
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs2
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs1
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs2
-rw-r--r--compiler/rustc_middle/src/ty/query/mod.rs1
-rw-r--r--compiler/rustc_middle/src/ty/util.rs3
-rw-r--r--compiler/rustc_mir/src/const_eval/eval_queries.rs4
-rw-r--r--compiler/rustc_mir/src/const_eval/machine.rs2
-rw-r--r--compiler/rustc_mir/src/interpret/eval_context.rs5
-rw-r--r--compiler/rustc_mir/src/monomorphize/collector.rs22
-rw-r--r--compiler/rustc_mir/src/transform/inline/cycle.rs18
-rw-r--r--compiler/rustc_session/src/lib.rs5
-rw-r--r--compiler/rustc_session/src/session.rs40
-rw-r--r--compiler/rustc_trait_selection/src/autoderef.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs2
-rw-r--r--compiler/rustc_traits/src/dropck_outlives.rs2
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs2
24 files changed, 120 insertions, 87 deletions
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index c0f7ea8df49..a5d97ef4111 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -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,15 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
                     tcx.ensure().check_mod_unstable_api_usage(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(());
             }
         );
     });
diff --git a/compiler/rustc_middle/src/ich/hcx.rs b/compiler/rustc_middle/src/ich/hcx.rs
index 91c81c367a1..f1c4529b855 100644
--- a/compiler/rustc_middle/src/ich/hcx.rs
+++ b/compiler/rustc_middle/src/ich/hcx.rs
@@ -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,
diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs
index 601198fd0de..eb706b57004 100644
--- a/compiler/rustc_middle/src/middle/limits.rs
+++ b/compiler/rustc_middle/src/middle/limits.rs
@@ -10,38 +10,37 @@
 //! 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::Limit;
 use rustc_session::Session;
 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.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);
 }
 
-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 +67,5 @@ fn update_limit(
             }
         }
     }
-    limit.set(From::from(default)).unwrap();
+    return Limit::new(default);
 }
diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs
index a369e85306b..b370ec152e8 100644
--- a/compiler/rustc_middle/src/middle/mod.rs
+++ b/compiler/rustc_middle/src/middle/mod.rs
@@ -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);
+}
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 23ee0e05062..189cd5e589d 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1712,4 +1712,26 @@ rustc_queries! {
     query conservative_is_privately_uninhabited(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
         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" }
+    }
 }
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 6b1ec1b0646..b08888006bc 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.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));
         }
 
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 7036c05a593..f9dad42a4b7 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -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,
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index c59394a23d0..efeb0ea5bef 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -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)
diff --git a/compiler/rustc_middle/src/ty/query/mod.rs b/compiler/rustc_middle/src/ty/query/mod.rs
index 2ac121fec7e..e9a5709543f 100644
--- a/compiler/rustc_middle/src/ty/query/mod.rs
+++ b/compiler/rustc_middle/src/ty/query/mod.rs
@@ -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::Limit;
 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 24a9cea6d21..ada5d059814 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -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),
diff --git a/compiler/rustc_mir/src/const_eval/eval_queries.rs b/compiler/rustc_mir/src/const_eval/eval_queries.rs
index 7a7dbe50e72..078f4cf7477 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.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 },
diff --git a/compiler/rustc_mir/src/const_eval/machine.rs b/compiler/rustc_mir/src/const_eval/machine.rs
index 992e32e298f..279f414e7fe 100644
--- a/compiler/rustc_mir/src/const_eval/machine.rs
+++ b/compiler/rustc_mir/src/const_eval/machine.rs
@@ -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)
diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs
index 801e4b1e478..3a77b30a328 100644
--- a/compiler/rustc_mir/src/interpret/eval_context.rs
+++ b/compiler/rustc_mir/src/interpret/eval_context.rs
@@ -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(()),
         }
     }
 
diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs
index 4bd431dcc6a..698cf765e49 100644
--- a/compiler/rustc_mir/src/monomorphize/collector.rs
+++ b/compiler/rustc_mir/src/monomorphize/collector.rs
@@ -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(());
         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 295f3ec70dc..106e3fd4985 100644
--- a/compiler/rustc_mir/src/transform/inline/cycle.rs
+++ b/compiler/rustc_mir/src/transform/inline/cycle.rs
@@ -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(()),
     )
 }
 
diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs
index 8d00a9a959e..9a82ae3fc10 100644
--- a/compiler/rustc_session/src/lib.rs
+++ b/compiler/rustc_session/src/lib.rs
@@ -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 {}
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index f792e319867..609144f7411 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -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 {
@@ -144,20 +145,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 +334,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 +1359,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,
diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs
index ac2e0ebae32..3b12b6fcf2a 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.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);
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 5c35b515f3d..11092c365d1 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.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 (`{}`)",
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 352829234a4..e76f3368360 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().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.
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index eb7ea8715c2..be34b67d979 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().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(),
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 6cecff4b89d..54f74b74edc 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.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);
diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs
index 9d5b9d7357f..a4930ba4507 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.sess.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 bc8f10e15db..3d4a455ff61 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.sess.recursion_limit(),
+            recursion_limit: tcx.recursion_limit(()),
             adt_components,
         }
     }