mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Auto merge of #97383 - dingxiangfei2009:restore-region-scope-tree-query, r=dingxiangfei2009
Try to cache region_scope_tree as a query This PR will attempt to restore `region_scope_tree` as a query so that caching works again. It seems that `region_scope_tree` could be re-computed for nested items after all, which could explain the performance regression introduced by #95563. cc `@Mark-Simulacrum` `@pnkfelix` I will try to trigger a perf run here.
This commit is contained in:
commit
4f39fb1f34
@ -31,6 +31,7 @@ macro_rules! arena_types {
|
|||||||
[decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult,
|
[decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult,
|
||||||
[decode] code_region: rustc_middle::mir::coverage::CodeRegion,
|
[decode] code_region: rustc_middle::mir::coverage::CodeRegion,
|
||||||
[] const_allocs: rustc_middle::mir::interpret::Allocation,
|
[] const_allocs: rustc_middle::mir::interpret::Allocation,
|
||||||
|
[] region_scope_tree: rustc_middle::middle::region::ScopeTree,
|
||||||
// Required for the incremental on-disk cache
|
// Required for the incremental on-disk cache
|
||||||
[] mir_keys: rustc_hir::def_id::DefIdSet,
|
[] mir_keys: rustc_hir::def_id::DefIdSet,
|
||||||
[] dropck_outlives:
|
[] dropck_outlives:
|
||||||
|
@ -1044,6 +1044,12 @@ rustc_queries! {
|
|||||||
desc { "reachability" }
|
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.
|
/// Generates a MIR body for the shim.
|
||||||
query mir_shims(key: ty::InstanceDef<'tcx>) -> mir::Body<'tcx> {
|
query mir_shims(key: ty::InstanceDef<'tcx>) -> mir::Body<'tcx> {
|
||||||
storage(ArenaCacheSelector<'tcx>)
|
storage(ArenaCacheSelector<'tcx>)
|
||||||
|
@ -6,7 +6,6 @@ use crate::hir::place::Place as HirPlace;
|
|||||||
use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
|
use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
|
||||||
use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource};
|
use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource};
|
||||||
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
|
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||||
use crate::middle::region::ScopeTree;
|
|
||||||
use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath};
|
use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath};
|
||||||
use crate::middle::stability;
|
use crate::middle::stability;
|
||||||
use crate::mir::interpret::{self, Allocation, ConstAllocation, ConstValue, Scalar};
|
use crate::mir::interpret::{self, Allocation, ConstAllocation, ConstValue, Scalar};
|
||||||
@ -538,12 +537,6 @@ pub struct TypeckResults<'tcx> {
|
|||||||
/// issue by fake reading `t`.
|
/// issue by fake reading `t`.
|
||||||
pub closure_fake_reads: FxHashMap<DefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
|
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
|
/// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
|
||||||
/// by applying extended parameter rules.
|
/// by applying extended parameter rules.
|
||||||
/// Details may be find in `rustc_typeck::check::rvalue_scopes`.
|
/// Details may be find in `rustc_typeck::check::rvalue_scopes`.
|
||||||
@ -586,7 +579,6 @@ impl<'tcx> TypeckResults<'tcx> {
|
|||||||
concrete_opaque_types: Default::default(),
|
concrete_opaque_types: Default::default(),
|
||||||
closure_min_captures: Default::default(),
|
closure_min_captures: Default::default(),
|
||||||
closure_fake_reads: Default::default(),
|
closure_fake_reads: Default::default(),
|
||||||
region_scope_tree: Default::default(),
|
|
||||||
rvalue_scopes: Default::default(),
|
rvalue_scopes: Default::default(),
|
||||||
generator_interior_types: ty::Binder::dummy(Default::default()),
|
generator_interior_types: ty::Binder::dummy(Default::default()),
|
||||||
treat_byte_string_as_slice: Default::default(),
|
treat_byte_string_as_slice: Default::default(),
|
||||||
|
@ -108,8 +108,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
let_scope_stack.push(remainder_scope);
|
let_scope_stack.push(remainder_scope);
|
||||||
|
|
||||||
// Declare the bindings, which may create a source scope.
|
// Declare the bindings, which may create a source scope.
|
||||||
let remainder_span =
|
let remainder_span = remainder_scope.span(this.tcx, this.region_scope_tree);
|
||||||
remainder_scope.span(this.tcx, &this.typeck_results.region_scope_tree);
|
|
||||||
|
|
||||||
let visibility_scope =
|
let visibility_scope =
|
||||||
Some(this.new_source_scope(remainder_span, LintLevel::Inherited, None));
|
Some(this.new_source_scope(remainder_span, LintLevel::Inherited, None));
|
||||||
|
@ -700,7 +700,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
self.cfg.push(block, Statement { source_info, kind: StatementKind::StorageLive(local_id) });
|
self.cfg.push(block, Statement { source_info, kind: StatementKind::StorageLive(local_id) });
|
||||||
// Altough there is almost always scope for given variable in corner cases
|
// Altough there is almost always scope for given variable in corner cases
|
||||||
// like #92893 we might get variable with no scope.
|
// 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);
|
self.schedule_drop(span, region_scope, local_id, DropKind::Storage);
|
||||||
}
|
}
|
||||||
Place::from(local_id)
|
Place::from(local_id)
|
||||||
@ -713,7 +713,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
for_guard: ForGuard,
|
for_guard: ForGuard,
|
||||||
) {
|
) {
|
||||||
let local_id = self.var_local_id(var, for_guard);
|
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);
|
self.schedule_drop(span, region_scope, local_id, DropKind::Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -398,6 +398,7 @@ struct Builder<'a, 'tcx> {
|
|||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
infcx: &'a InferCtxt<'a, 'tcx>,
|
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||||
typeck_results: &'tcx TypeckResults<'tcx>,
|
typeck_results: &'tcx TypeckResults<'tcx>,
|
||||||
|
region_scope_tree: &'tcx region::ScopeTree,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
|
||||||
thir: &'a Thir<'tcx>,
|
thir: &'a Thir<'tcx>,
|
||||||
@ -880,6 +881,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
tcx,
|
tcx,
|
||||||
infcx,
|
infcx,
|
||||||
typeck_results: tcx.typeck_opt_const_arg(def),
|
typeck_results: tcx.typeck_opt_const_arg(def),
|
||||||
|
region_scope_tree: tcx.region_scope_tree(def.did),
|
||||||
param_env,
|
param_env,
|
||||||
def_id: def.did.to_def_id(),
|
def_id: def.did.to_def_id(),
|
||||||
hir_id,
|
hir_id,
|
||||||
|
@ -916,8 +916,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if scope.region_scope == region_scope {
|
if scope.region_scope == region_scope {
|
||||||
let region_scope_span =
|
let region_scope_span = region_scope.span(self.tcx, &self.region_scope_tree);
|
||||||
region_scope.span(self.tcx, &self.typeck_results.region_scope_tree);
|
|
||||||
// Attribute scope exit drops to scope's closing brace.
|
// Attribute scope exit drops to scope's closing brace.
|
||||||
let scope_end = self.tcx.sess.source_map().end_point(region_scope_span);
|
let scope_end = self.tcx.sess.source_map().end_point(region_scope_span);
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ impl<'tcx> Cx<'tcx> {
|
|||||||
tcx,
|
tcx,
|
||||||
thir: Thir::new(),
|
thir: Thir::new(),
|
||||||
param_env: tcx.param_env(def.did),
|
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,
|
typeck_results,
|
||||||
rvalue_scopes: &typeck_results.rvalue_scopes,
|
rvalue_scopes: &typeck_results.rvalue_scopes,
|
||||||
body_owner: def.did.to_def_id(),
|
body_owner: def.did.to_def_id(),
|
||||||
|
@ -4,7 +4,7 @@ use crate::astconv::{
|
|||||||
};
|
};
|
||||||
use crate::check::callee::{self, DeferredCallResolution};
|
use crate::check::callee::{self, DeferredCallResolution};
|
||||||
use crate::check::method::{self, MethodCallee, SelfSource};
|
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 crate::check::{BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy};
|
||||||
|
|
||||||
use rustc_data_structures::captures::Captures;
|
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) {
|
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 rvalue_scopes = { rvalue_scopes::resolve_rvalue_scopes(self, &scope_tree, def_id) };
|
||||||
let mut typeck_results = self.inh.typeck_results.borrow_mut();
|
let mut typeck_results = self.inh.typeck_results.borrow_mut();
|
||||||
typeck_results.region_scope_tree = scope_tree;
|
|
||||||
typeck_results.rvalue_scopes = rvalue_scopes;
|
typeck_results.rvalue_scopes = rvalue_scopes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ pub fn resolve_interior<'a, 'tcx>(
|
|||||||
let mut visitor = InteriorVisitor {
|
let mut visitor = InteriorVisitor {
|
||||||
fcx,
|
fcx,
|
||||||
types: FxIndexSet::default(),
|
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,
|
rvalue_scopes: &typeck_results.rvalue_scopes,
|
||||||
expr_count: 0,
|
expr_count: 0,
|
||||||
kind,
|
kind,
|
||||||
@ -195,7 +195,7 @@ pub fn resolve_interior<'a, 'tcx>(
|
|||||||
intravisit::walk_body(&mut visitor, body);
|
intravisit::walk_body(&mut visitor, body);
|
||||||
|
|
||||||
// Check that we visited the same amount of expressions as the RegionResolutionVisitor
|
// 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);
|
assert_eq!(region_expr_count, visitor.expr_count);
|
||||||
|
|
||||||
// The types are already kept in insertion order.
|
// The types are already kept in insertion order.
|
||||||
|
@ -42,7 +42,7 @@ pub fn compute_drop_ranges<'a, 'tcx>(
|
|||||||
let consumed_borrowed_places = find_consumed_and_borrowed(fcx, def_id, body);
|
let consumed_borrowed_places = find_consumed_and_borrowed(fcx, def_id, body);
|
||||||
|
|
||||||
let typeck_results = &fcx.typeck_results.borrow();
|
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(
|
let (mut drop_ranges, borrowed_temporaries) = build_control_flow_graph(
|
||||||
fcx.tcx.hir(),
|
fcx.tcx.hir(),
|
||||||
fcx.tcx,
|
fcx.tcx,
|
||||||
|
@ -139,6 +139,7 @@ use crate::require_c_abi_if_c_variadic;
|
|||||||
use crate::util::common::indenter;
|
use crate::util::common::indenter;
|
||||||
|
|
||||||
use self::coercion::DynamicCoerceMany;
|
use self::coercion::DynamicCoerceMany;
|
||||||
|
use self::region::region_scope_tree;
|
||||||
pub use self::Expectation::*;
|
pub use self::Expectation::*;
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
@ -256,6 +257,7 @@ pub fn provide(providers: &mut Providers) {
|
|||||||
check_trait_item_well_formed,
|
check_trait_item_well_formed,
|
||||||
check_impl_item_well_formed,
|
check_impl_item_well_formed,
|
||||||
check_mod_item_types,
|
check_mod_item_types,
|
||||||
|
region_scope_tree,
|
||||||
..*providers
|
..*providers
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -797,14 +797,19 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
|
|||||||
|
|
||||||
/// Per-body `region::ScopeTree`. The `DefId` should be the owner `DefId` for the body;
|
/// 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.
|
/// in the case of closures, this will be redirected to the enclosing function.
|
||||||
pub fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> ScopeTree {
|
///
|
||||||
|
/// Performance: This is a query rather than a simple function to enable
|
||||||
|
/// re-use in incremental scenarios. We may sometimes need to rerun the
|
||||||
|
/// type checker even when the HIR hasn't changed, and in those cases
|
||||||
|
/// we can avoid reconstructing the region scope tree.
|
||||||
|
pub fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree {
|
||||||
let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
|
let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
|
||||||
if 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());
|
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 {
|
let mut visitor = RegionResolutionVisitor {
|
||||||
tcx,
|
tcx,
|
||||||
scope_tree: ScopeTree::default(),
|
scope_tree: ScopeTree::default(),
|
||||||
@ -821,5 +826,7 @@ pub fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> ScopeTree {
|
|||||||
visitor.scope_tree
|
visitor.scope_tree
|
||||||
} else {
|
} else {
|
||||||
ScopeTree::default()
|
ScopeTree::default()
|
||||||
}
|
};
|
||||||
|
|
||||||
|
tcx.arena.alloc(scope_tree)
|
||||||
}
|
}
|
||||||
|
@ -71,8 +71,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
wbcx.visit_user_provided_sigs();
|
wbcx.visit_user_provided_sigs();
|
||||||
wbcx.visit_generator_interior_types();
|
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 =
|
wbcx.typeck_results.rvalue_scopes =
|
||||||
mem::take(&mut self.typeck_results.borrow_mut().rvalue_scopes);
|
mem::take(&mut self.typeck_results.borrow_mut().rvalue_scopes);
|
||||||
|
|
||||||
|
@ -55,11 +55,7 @@ pub(super) fn check<'tcx>(
|
|||||||
// ensure that the indexed variable was declared before the loop, see #601
|
// ensure that the indexed variable was declared before the loop, see #601
|
||||||
if let Some(indexed_extent) = indexed_extent {
|
if let Some(indexed_extent) = indexed_extent {
|
||||||
let parent_def_id = cx.tcx.hir().get_parent_item(expr.hir_id);
|
let parent_def_id = cx.tcx.hir().get_parent_item(expr.hir_id);
|
||||||
let parent_body_id = cx
|
let region_scope_tree = cx.tcx.region_scope_tree(parent_def_id);
|
||||||
.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 pat_extent = region_scope_tree.var_scope(pat.hir_id.local_id).unwrap();
|
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) {
|
if region_scope_tree.is_subscope_of(indexed_extent, pat_extent) {
|
||||||
return;
|
return;
|
||||||
@ -282,14 +278,9 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> {
|
|||||||
match res {
|
match res {
|
||||||
Res::Local(hir_id) => {
|
Res::Local(hir_id) => {
|
||||||
let parent_def_id = self.cx.tcx.hir().get_parent_item(expr.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
|
let extent = self.cx
|
||||||
.tcx
|
.tcx
|
||||||
.typeck_body(parent_body_id)
|
.region_scope_tree(parent_def_id)
|
||||||
.region_scope_tree
|
|
||||||
.var_scope(hir_id.local_id)
|
.var_scope(hir_id.local_id)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
if index_used_directly {
|
if index_used_directly {
|
||||||
|
@ -162,10 +162,7 @@ fn is_shadow(
|
|||||||
first: ItemLocalId,
|
first: ItemLocalId,
|
||||||
second: ItemLocalId,
|
second: ItemLocalId,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let scope_tree = &cx
|
let scope_tree = cx.tcx.region_scope_tree(owner);
|
||||||
.tcx
|
|
||||||
.typeck_body(cx.tcx.hir().body_owned_by(cx.tcx.hir().local_def_id_to_hir_id(owner)))
|
|
||||||
.region_scope_tree;
|
|
||||||
let first_scope = scope_tree.var_scope(first).unwrap();
|
let first_scope = scope_tree.var_scope(first).unwrap();
|
||||||
let second_scope = scope_tree.var_scope(second).unwrap();
|
let second_scope = scope_tree.var_scope(second).unwrap();
|
||||||
scope_tree.is_subscope_of(second_scope, first_scope)
|
scope_tree.is_subscope_of(second_scope, first_scope)
|
||||||
|
Loading…
Reference in New Issue
Block a user