From 4c6074fbb03d2cb3d175a8f71606fc264e30e8d3 Mon Sep 17 00:00:00 2001
From: Ding Xiang Fei <dingxiangfei2009@protonmail.ch>
Date: Wed, 25 May 2022 13:52:32 +0800
Subject: [PATCH] try to cache region_scope_tree as a query

---
 compiler/rustc_middle/src/arena.rs                  |  1 +
 compiler/rustc_middle/src/query/mod.rs              |  6 ++++++
 compiler/rustc_middle/src/ty/context.rs             |  8 --------
 compiler/rustc_mir_build/src/build/block.rs         |  3 +--
 compiler/rustc_mir_build/src/build/matches/mod.rs   |  4 ++--
 compiler/rustc_mir_build/src/build/mod.rs           |  2 ++
 compiler/rustc_mir_build/src/build/scope.rs         |  3 +--
 compiler/rustc_mir_build/src/thir/cx/mod.rs         |  2 +-
 compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs    |  5 ++---
 .../rustc_typeck/src/check/generator_interior.rs    |  4 ++--
 .../src/check/generator_interior/drop_ranges.rs     |  2 +-
 compiler/rustc_typeck/src/check/mod.rs              |  2 ++
 compiler/rustc_typeck/src/check/region.rs           | 10 ++++++----
 compiler/rustc_typeck/src/check/writeback.rs        |  2 --
 .../clippy_lints/src/loops/needless_range_loop.rs   | 13 ++-----------
 src/tools/clippy/clippy_lints/src/shadow.rs         |  5 +----
 16 files changed, 30 insertions(+), 42 deletions(-)

diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index 2f0bb24537e..984c95b314b 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -31,6 +31,7 @@ macro_rules! arena_types {
             [decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult,
             [decode] code_region: rustc_middle::mir::coverage::CodeRegion,
             [] const_allocs: rustc_middle::mir::interpret::Allocation,
+            [] region_scope_tree: rustc_middle::middle::region::ScopeTree,
             // Required for the incremental on-disk cache
             [] mir_keys: rustc_hir::def_id::DefIdSet,
             [] dropck_outlives:
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 0c936b7ae10..fd1be1b4879 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1048,6 +1048,12 @@ rustc_queries! {
         desc { "reachability" }
     }
 
+    /// Per-body `region::ScopeTree`. The `DefId` should be the owner `DefId` for the body;
+    /// in the case of closures, this will be redirected to the enclosing function.
+    query region_scope_tree(def_id: DefId) -> &'tcx crate::middle::region::ScopeTree {
+        desc { |tcx| "computing drop scopes for `{}`", tcx.def_path_str(def_id) }
+    }
+
     /// Generates a MIR body for the shim.
     query mir_shims(key: ty::InstanceDef<'tcx>) -> mir::Body<'tcx> {
         storage(ArenaCacheSelector<'tcx>)
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 6b92a4c0a2e..3c08db5dc68 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -6,7 +6,6 @@ use crate::hir::place::Place as HirPlace;
 use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
 use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource};
 use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
-use crate::middle::region::ScopeTree;
 use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath};
 use crate::middle::stability;
 use crate::mir::interpret::{self, Allocation, ConstAllocation, ConstValue, Scalar};
@@ -538,12 +537,6 @@ pub struct TypeckResults<'tcx> {
     /// issue by fake reading `t`.
     pub closure_fake_reads: FxHashMap<DefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
 
-    /// Tracks critical information about regions in a body.
-    /// This includes containment relationship between regions,
-    /// liveness relationship between variables and regions and
-    /// information about yield points.
-    pub region_scope_tree: ScopeTree,
-
     /// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
     /// by applying extended parameter rules.
     /// Details may be find in `rustc_typeck::check::rvalue_scopes`.
@@ -586,7 +579,6 @@ impl<'tcx> TypeckResults<'tcx> {
             concrete_opaque_types: Default::default(),
             closure_min_captures: Default::default(),
             closure_fake_reads: Default::default(),
-            region_scope_tree: Default::default(),
             rvalue_scopes: Default::default(),
             generator_interior_types: ty::Binder::dummy(Default::default()),
             treat_byte_string_as_slice: Default::default(),
diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs
index e8b939fb51d..a83328c0cab 100644
--- a/compiler/rustc_mir_build/src/build/block.rs
+++ b/compiler/rustc_mir_build/src/build/block.rs
@@ -108,8 +108,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     let_scope_stack.push(remainder_scope);
 
                     // Declare the bindings, which may create a source scope.
-                    let remainder_span =
-                        remainder_scope.span(this.tcx, &this.typeck_results.region_scope_tree);
+                    let remainder_span = remainder_scope.span(this.tcx, this.region_scope_tree);
 
                     let visibility_scope =
                         Some(this.new_source_scope(remainder_span, LintLevel::Inherited, None));
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 9df86c6ada1..15660365938 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -700,7 +700,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         self.cfg.push(block, Statement { source_info, kind: StatementKind::StorageLive(local_id) });
         // Altough there is almost always scope for given variable in corner cases
         // like #92893 we might get variable with no scope.
-        if let Some(region_scope) = self.typeck_results.region_scope_tree.var_scope(var.local_id) && schedule_drop{
+        if let Some(region_scope) = self.region_scope_tree.var_scope(var.local_id) && schedule_drop{
             self.schedule_drop(span, region_scope, local_id, DropKind::Storage);
         }
         Place::from(local_id)
@@ -713,7 +713,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         for_guard: ForGuard,
     ) {
         let local_id = self.var_local_id(var, for_guard);
-        if let Some(region_scope) = self.typeck_results.region_scope_tree.var_scope(var.local_id) {
+        if let Some(region_scope) = self.region_scope_tree.var_scope(var.local_id) {
             self.schedule_drop(span, region_scope, local_id, DropKind::Value);
         }
     }
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index c42f2b3a67a..4ae74433df6 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -398,6 +398,7 @@ struct Builder<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     infcx: &'a InferCtxt<'a, 'tcx>,
     typeck_results: &'tcx TypeckResults<'tcx>,
+    region_scope_tree: &'tcx region::ScopeTree,
     param_env: ty::ParamEnv<'tcx>,
 
     thir: &'a Thir<'tcx>,
@@ -880,6 +881,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             tcx,
             infcx,
             typeck_results: tcx.typeck_opt_const_arg(def),
+            region_scope_tree: tcx.region_scope_tree(def.did),
             param_env,
             def_id: def.did.to_def_id(),
             hir_id,
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 53f9706f021..2d14a78accf 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -916,8 +916,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
 
             if scope.region_scope == region_scope {
-                let region_scope_span =
-                    region_scope.span(self.tcx, &self.typeck_results.region_scope_tree);
+                let region_scope_span = region_scope.span(self.tcx, &self.region_scope_tree);
                 // Attribute scope exit drops to scope's closing brace.
                 let scope_end = self.tcx.sess.source_map().end_point(region_scope_span);
 
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index bd17df60cd7..d853a5e9ee7 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -72,7 +72,7 @@ impl<'tcx> Cx<'tcx> {
             tcx,
             thir: Thir::new(),
             param_env: tcx.param_env(def.did),
-            region_scope_tree: &typeck_results.region_scope_tree,
+            region_scope_tree: tcx.region_scope_tree(def.did),
             typeck_results,
             rvalue_scopes: &typeck_results.rvalue_scopes,
             body_owner: def.did.to_def_id(),
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
index 649bc211321..ac2dc6522ad 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
@@ -4,7 +4,7 @@ use crate::astconv::{
 };
 use crate::check::callee::{self, DeferredCallResolution};
 use crate::check::method::{self, MethodCallee, SelfSource};
-use crate::check::{region, rvalue_scopes};
+use crate::check::rvalue_scopes;
 use crate::check::{BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy};
 
 use rustc_data_structures::captures::Captures;
@@ -622,10 +622,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     pub(in super::super) fn resolve_rvalue_scopes(&self, def_id: DefId) {
-        let scope_tree = region::region_scope_tree(self.tcx, def_id);
+        let scope_tree = self.tcx.region_scope_tree(def_id);
         let rvalue_scopes = { rvalue_scopes::resolve_rvalue_scopes(self, &scope_tree, def_id) };
         let mut typeck_results = self.inh.typeck_results.borrow_mut();
-        typeck_results.region_scope_tree = scope_tree;
         typeck_results.rvalue_scopes = rvalue_scopes;
     }
 
diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs
index 02167ddef44..f09c7f51f47 100644
--- a/compiler/rustc_typeck/src/check/generator_interior.rs
+++ b/compiler/rustc_typeck/src/check/generator_interior.rs
@@ -184,7 +184,7 @@ pub fn resolve_interior<'a, 'tcx>(
     let mut visitor = InteriorVisitor {
         fcx,
         types: FxIndexSet::default(),
-        region_scope_tree: &typeck_results.region_scope_tree,
+        region_scope_tree: fcx.tcx.region_scope_tree(def_id),
         rvalue_scopes: &typeck_results.rvalue_scopes,
         expr_count: 0,
         kind,
@@ -195,7 +195,7 @@ pub fn resolve_interior<'a, 'tcx>(
     intravisit::walk_body(&mut visitor, body);
 
     // Check that we visited the same amount of expressions as the RegionResolutionVisitor
-    let region_expr_count = typeck_results.region_scope_tree.body_expr_count(body_id).unwrap();
+    let region_expr_count = fcx.tcx.region_scope_tree(def_id).body_expr_count(body_id).unwrap();
     assert_eq!(region_expr_count, visitor.expr_count);
 
     // The types are already kept in insertion order.
diff --git a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges.rs b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges.rs
index ba6fcb98924..c2b4c478ba3 100644
--- a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges.rs
+++ b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges.rs
@@ -42,7 +42,7 @@ pub fn compute_drop_ranges<'a, 'tcx>(
         let consumed_borrowed_places = find_consumed_and_borrowed(fcx, def_id, body);
 
         let typeck_results = &fcx.typeck_results.borrow();
-        let num_exprs = typeck_results.region_scope_tree.body_expr_count(body.id()).unwrap_or(0);
+        let num_exprs = fcx.tcx.region_scope_tree(def_id).body_expr_count(body.id()).unwrap_or(0);
         let (mut drop_ranges, borrowed_temporaries) = build_control_flow_graph(
             fcx.tcx.hir(),
             fcx.tcx,
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index 280fae5fe6d..1df82eca82a 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -138,6 +138,7 @@ use crate::require_c_abi_if_c_variadic;
 use crate::util::common::indenter;
 
 use self::coercion::DynamicCoerceMany;
+use self::region::region_scope_tree;
 pub use self::Expectation::*;
 
 #[macro_export]
@@ -255,6 +256,7 @@ pub fn provide(providers: &mut Providers) {
         check_trait_item_well_formed,
         check_impl_item_well_formed,
         check_mod_item_types,
+        region_scope_tree,
         ..*providers
     };
 }
diff --git a/compiler/rustc_typeck/src/check/region.rs b/compiler/rustc_typeck/src/check/region.rs
index 43d189abcf7..9e94511fdc4 100644
--- a/compiler/rustc_typeck/src/check/region.rs
+++ b/compiler/rustc_typeck/src/check/region.rs
@@ -797,14 +797,14 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
 
 /// Per-body `region::ScopeTree`. The `DefId` should be the owner `DefId` for the body;
 /// in the case of closures, this will be redirected to the enclosing function.
-pub fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> ScopeTree {
+pub fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree {
     let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
     if typeck_root_def_id != def_id {
-        return region_scope_tree(tcx, typeck_root_def_id);
+        return tcx.region_scope_tree(typeck_root_def_id);
     }
 
     let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-    if let Some(body_id) = tcx.hir().maybe_body_owned_by(id) {
+    let scope_tree = if let Some(body_id) = tcx.hir().maybe_body_owned_by(id) {
         let mut visitor = RegionResolutionVisitor {
             tcx,
             scope_tree: ScopeTree::default(),
@@ -821,5 +821,7 @@ pub fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> ScopeTree {
         visitor.scope_tree
     } else {
         ScopeTree::default()
-    }
+    };
+
+    tcx.arena.alloc(scope_tree)
 }
diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs
index 16096ea3d74..c37f4ce3a93 100644
--- a/compiler/rustc_typeck/src/check/writeback.rs
+++ b/compiler/rustc_typeck/src/check/writeback.rs
@@ -71,8 +71,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         wbcx.visit_user_provided_sigs();
         wbcx.visit_generator_interior_types();
 
-        wbcx.typeck_results.region_scope_tree =
-            mem::take(&mut self.typeck_results.borrow_mut().region_scope_tree);
         wbcx.typeck_results.rvalue_scopes =
             mem::take(&mut self.typeck_results.borrow_mut().rvalue_scopes);
 
diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
index e2b82f9fd02..4f85364965b 100644
--- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
@@ -55,11 +55,7 @@ pub(super) fn check<'tcx>(
                 // ensure that the indexed variable was declared before the loop, see #601
                 if let Some(indexed_extent) = indexed_extent {
                     let parent_def_id = cx.tcx.hir().get_parent_item(expr.hir_id);
-                    let parent_body_id = cx
-                        .tcx
-                        .hir()
-                        .body_owned_by(cx.tcx.hir().local_def_id_to_hir_id(parent_def_id));
-                    let region_scope_tree = &cx.tcx.typeck_body(parent_body_id).region_scope_tree;
+                    let region_scope_tree = cx.tcx.region_scope_tree(parent_def_id);
                     let pat_extent = region_scope_tree.var_scope(pat.hir_id.local_id).unwrap();
                     if region_scope_tree.is_subscope_of(indexed_extent, pat_extent) {
                         return;
@@ -282,14 +278,9 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> {
                 match res {
                     Res::Local(hir_id) => {
                         let parent_def_id = self.cx.tcx.hir().get_parent_item(expr.hir_id);
-                        let parent_body_id = self.cx
-                            .tcx
-                            .hir()
-                            .body_owned_by(self.cx.tcx.hir().local_def_id_to_hir_id(parent_def_id));
                         let extent = self.cx
                             .tcx
-                            .typeck_body(parent_body_id)
-                            .region_scope_tree
+                            .region_scope_tree(parent_def_id)
                             .var_scope(hir_id.local_id)
                             .unwrap();
                         if index_used_directly {
diff --git a/src/tools/clippy/clippy_lints/src/shadow.rs b/src/tools/clippy/clippy_lints/src/shadow.rs
index db32b8d740b..2a80e6f918d 100644
--- a/src/tools/clippy/clippy_lints/src/shadow.rs
+++ b/src/tools/clippy/clippy_lints/src/shadow.rs
@@ -162,10 +162,7 @@ fn is_shadow(
     first: ItemLocalId,
     second: ItemLocalId,
 ) -> bool {
-    let scope_tree = &cx
-        .tcx
-        .typeck_body(cx.tcx.hir().body_owned_by(cx.tcx.hir().local_def_id_to_hir_id(owner)))
-        .region_scope_tree;
+    let scope_tree = cx.tcx.region_scope_tree(owner);
     let first_scope = scope_tree.var_scope(first).unwrap();
     let second_scope = scope_tree.var_scope(second).unwrap();
     scope_tree.is_subscope_of(second_scope, first_scope)