Skip to content

Commit 027a232

Browse files
committed
Auto merge of #95487 - cjgillot:menhir, r=oli-obk
Avoid accessing HIR from MIR passes `hir_owner_nodes` contains a lot of information, and the query result is typically dirty. This forces dependent queries to be re-executed needlessly. This PR refactors some accesses to HIR to go through more targeted queries that yield the same result. Based on #95435 and #95436
2 parents 18f32b7 + bbacfcb commit 027a232

File tree

17 files changed

+89
-110
lines changed

17 files changed

+89
-110
lines changed

Diff for: compiler/rustc_borrowck/src/lib.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use rustc_data_structures::graph::dominators::Dominators;
2323
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
2424
use rustc_hir as hir;
2525
use rustc_hir::def_id::LocalDefId;
26-
use rustc_hir::Node;
2726
use rustc_index::bit_set::ChunkedBitSet;
2827
use rustc_index::vec::IndexVec;
2928
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
@@ -288,14 +287,16 @@ fn do_mir_borrowck<'a, 'tcx>(
288287
.pass_name("borrowck")
289288
.iterate_to_fixpoint();
290289

291-
let def_hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
292-
let movable_generator = !matches!(
293-
tcx.hir().get(def_hir_id),
294-
Node::Expr(&hir::Expr {
295-
kind: hir::ExprKind::Closure(.., Some(hir::Movability::Static)),
296-
..
297-
})
298-
);
290+
let movable_generator =
291+
// The first argument is the generator type passed by value
292+
if let Some(local) = body.local_decls.raw.get(1)
293+
// Get the interior types and substs which typeck computed
294+
&& let ty::Generator(_, _, hir::Movability::Static) = local.ty.kind()
295+
{
296+
false
297+
} else {
298+
true
299+
};
299300

300301
for (idx, move_data_results) in promoted_errors {
301302
let promoted_body = &promoted[idx];
@@ -385,7 +386,7 @@ fn do_mir_borrowck<'a, 'tcx>(
385386
let scope = mbcx.body.source_info(location).scope;
386387
let lint_root = match &mbcx.body.source_scopes[scope].local_data {
387388
ClearCrossCrate::Set(data) => data.lint_root,
388-
_ => def_hir_id,
389+
_ => tcx.hir().local_def_id_to_hir_id(def.did),
389390
};
390391

391392
// Span and message don't matter; we overwrite them below anyway

Diff for: compiler/rustc_borrowck/src/universal_regions.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -828,10 +828,8 @@ fn for_each_late_bound_region_defined_on<'tcx>(
828828
mut f: impl FnMut(ty::Region<'tcx>),
829829
) {
830830
if let Some((owner, late_bounds)) = tcx.is_late_bound_map(fn_def_id.expect_local()) {
831-
for &late_bound in late_bounds.iter() {
832-
let hir_id = HirId { owner, local_id: late_bound };
833-
let name = tcx.hir().name(hir_id);
834-
let region_def_id = tcx.hir().local_def_id(hir_id);
831+
for &region_def_id in late_bounds.iter() {
832+
let name = tcx.item_name(region_def_id.to_def_id());
835833
let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion {
836834
scope: owner.to_def_id(),
837835
bound_region: ty::BoundRegionKind::BrNamed(region_def_id.to_def_id(), name),

Diff for: compiler/rustc_const_eval/src/transform/check_consts/check.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
222222

223223
// `async` functions cannot be `const fn`. This is checked during AST lowering, so there's
224224
// no need to emit duplicate errors here.
225-
if is_async_fn(self.ccx) || body.generator.is_some() {
225+
if self.ccx.is_async() || body.generator.is_some() {
226226
tcx.sess.delay_span_bug(body.span, "`async` functions cannot be `const fn`");
227227
return;
228228
}
@@ -1056,12 +1056,8 @@ fn is_int_bool_or_char(ty: Ty<'_>) -> bool {
10561056
ty.is_bool() || ty.is_integral() || ty.is_char()
10571057
}
10581058

1059-
fn is_async_fn(ccx: &ConstCx<'_, '_>) -> bool {
1060-
ccx.fn_sig().map_or(false, |sig| sig.header.asyncness == hir::IsAsync::Async)
1061-
}
1062-
10631059
fn emit_unstable_in_stable_error(ccx: &ConstCx<'_, '_>, span: Span, gate: Symbol) {
1064-
let attr_span = ccx.fn_sig().map_or(ccx.body.span, |sig| sig.span.shrink_to_lo());
1060+
let attr_span = ccx.tcx.def_span(ccx.def_id()).shrink_to_lo();
10651061

10661062
ccx.tcx
10671063
.sess

Diff for: compiler/rustc_const_eval/src/transform/check_consts/mod.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,8 @@ impl<'mir, 'tcx> ConstCx<'mir, 'tcx> {
6161
&& is_const_stable_const_fn(self.tcx, self.def_id().to_def_id())
6262
}
6363

64-
/// Returns the function signature of the item being const-checked if it is a `fn` or `const fn`.
65-
pub fn fn_sig(&self) -> Option<&'tcx hir::FnSig<'tcx>> {
66-
// Get this from the HIR map instead of a query to avoid cycle errors.
67-
//
68-
// FIXME: Is this still an issue?
69-
let hir_map = self.tcx.hir();
70-
let hir_id = hir_map.local_def_id_to_hir_id(self.def_id());
71-
hir_map.fn_sig_by_hir_id(hir_id)
64+
fn is_async(&self) -> bool {
65+
self.tcx.asyncness(self.def_id()) == hir::IsAsync::Async
7266
}
7367
}
7468

Diff for: compiler/rustc_hir/src/def.rs

+8
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,14 @@ impl DefKind {
223223
| DefKind::Impl => None,
224224
}
225225
}
226+
227+
#[inline]
228+
pub fn is_fn_like(self) -> bool {
229+
match self {
230+
DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Generator => true,
231+
_ => false,
232+
}
233+
}
226234
}
227235

228236
/// The resolution of a path or export.

Diff for: compiler/rustc_middle/src/middle/resolve_lifetime.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ pub struct ResolveLifetimes {
6464
/// Set of lifetime def ids that are late-bound; a region can
6565
/// be late-bound if (a) it does NOT appear in a where-clause and
6666
/// (b) it DOES appear in the arguments.
67-
pub late_bound: FxHashMap<LocalDefId, FxHashSet<ItemLocalId>>,
67+
pub late_bound: FxHashMap<LocalDefId, FxHashSet<LocalDefId>>,
6868

6969
pub late_bound_vars: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>>,
7070
}

Diff for: compiler/rustc_middle/src/query/mod.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1502,8 +1502,7 @@ rustc_queries! {
15021502
Option<&'tcx FxHashMap<ItemLocalId, Region>> {
15031503
desc { "looking up a named region" }
15041504
}
1505-
query is_late_bound_map(_: LocalDefId) ->
1506-
Option<(LocalDefId, &'tcx FxHashSet<ItemLocalId>)> {
1505+
query is_late_bound_map(_: LocalDefId) -> Option<(LocalDefId, &'tcx FxHashSet<LocalDefId>)> {
15071506
desc { "testing if a region is late bound" }
15081507
}
15091508
/// For a given item (like a struct), gets the default lifetimes to be used

Diff for: compiler/rustc_middle/src/ty/context.rs

-5
Original file line numberDiff line numberDiff line change
@@ -2772,11 +2772,6 @@ impl<'tcx> TyCtxt<'tcx> {
27722772
self.named_region_map(id.owner).and_then(|map| map.get(&id.local_id).cloned())
27732773
}
27742774

2775-
pub fn is_late_bound(self, id: HirId) -> bool {
2776-
self.is_late_bound_map(id.owner)
2777-
.map_or(false, |(owner, set)| owner == id.owner && set.contains(&id.local_id))
2778-
}
2779-
27802775
pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> {
27812776
self.mk_bound_variable_kinds(
27822777
self.late_bound_vars_map(id.owner)

Diff for: compiler/rustc_mir_transform/src/const_prop.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,9 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
7171
}
7272

7373
let def_id = body.source.def_id().expect_local();
74-
let is_fn_like = tcx.hir().get_by_def_id(def_id).fn_kind().is_some();
75-
let is_assoc_const = tcx.def_kind(def_id) == DefKind::AssocConst;
74+
let def_kind = tcx.def_kind(def_id);
75+
let is_fn_like = def_kind.is_fn_like();
76+
let is_assoc_const = def_kind == DefKind::AssocConst;
7677

7778
// Only run const prop on functions, methods, closures and associated constants
7879
if !is_fn_like && !is_assoc_const {

Diff for: compiler/rustc_mir_transform/src/const_prop_lint.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ impl<'tcx> MirLint<'tcx> for ConstProp {
6767
}
6868

6969
let def_id = body.source.def_id().expect_local();
70-
let is_fn_like = tcx.hir().get_by_def_id(def_id).fn_kind().is_some();
70+
let is_fn_like = tcx.def_kind(def_id).is_fn_like();
7171
let is_assoc_const = tcx.def_kind(def_id) == DefKind::AssocConst;
7272

7373
// Only run const prop on functions, methods, closures and associated constants

Diff for: compiler/rustc_mir_transform/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ fn mir_drops_elaborated_and_const_checked<'tcx>(
366366

367367
let mir_borrowck = tcx.mir_borrowck_opt_const_arg(def);
368368

369-
let is_fn_like = tcx.hir().get_by_def_id(def.did).fn_kind().is_some();
369+
let is_fn_like = tcx.def_kind(def.did).is_fn_like();
370370
if is_fn_like {
371371
let did = def.did.to_def_id();
372372
let def = ty::WithOptConstParam::unknown(did);

Diff for: compiler/rustc_mir_transform/src/shim.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -725,9 +725,6 @@ fn build_call_shim<'tcx>(
725725
pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
726726
debug_assert!(tcx.is_constructor(ctor_id));
727727

728-
let span =
729-
tcx.hir().span_if_local(ctor_id).unwrap_or_else(|| bug!("no span for ctor {:?}", ctor_id));
730-
731728
let param_env = tcx.param_env(ctor_id);
732729

733730
// Normalize the sig.
@@ -740,6 +737,8 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
740737

741738
debug!("build_ctor: ctor_id={:?} sig={:?}", ctor_id, sig);
742739

740+
let span = tcx.def_span(ctor_id);
741+
743742
let local_decls = local_decls_for_sig(&sig, span);
744743

745744
let source_info = SourceInfo::outermost(span);

Diff for: compiler/rustc_resolve/src/late/lifetimes.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -427,15 +427,15 @@ fn resolve_lifetimes_trait_definition(
427427
tcx: TyCtxt<'_>,
428428
local_def_id: LocalDefId,
429429
) -> ResolveLifetimes {
430-
convert_named_region_map(do_resolve(tcx, local_def_id, true, false))
430+
convert_named_region_map(tcx, do_resolve(tcx, local_def_id, true, false))
431431
}
432432

433433
/// Computes the `ResolveLifetimes` map that contains data for an entire `Item`.
434434
/// You should not read the result of this query directly, but rather use
435435
/// `named_region_map`, `is_late_bound_map`, etc.
436436
#[tracing::instrument(level = "debug", skip(tcx))]
437437
fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> ResolveLifetimes {
438-
convert_named_region_map(do_resolve(tcx, local_def_id, false, false))
438+
convert_named_region_map(tcx, do_resolve(tcx, local_def_id, false, false))
439439
}
440440

441441
fn do_resolve(
@@ -468,7 +468,7 @@ fn do_resolve(
468468
named_region_map
469469
}
470470

471-
fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetimes {
471+
fn convert_named_region_map(tcx: TyCtxt<'_>, named_region_map: NamedRegionMap) -> ResolveLifetimes {
472472
let mut rl = ResolveLifetimes::default();
473473

474474
for (hir_id, v) in named_region_map.defs {
@@ -477,7 +477,8 @@ fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetime
477477
}
478478
for hir_id in named_region_map.late_bound {
479479
let map = rl.late_bound.entry(hir_id.owner).or_default();
480-
map.insert(hir_id.local_id);
480+
let def_id = tcx.hir().local_def_id(hir_id);
481+
map.insert(def_id);
481482
}
482483
for (hir_id, v) in named_region_map.late_bound_vars {
483484
let map = rl.late_bound_vars.entry(hir_id.owner).or_default();
@@ -537,7 +538,7 @@ fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId {
537538
fn is_late_bound_map<'tcx>(
538539
tcx: TyCtxt<'tcx>,
539540
def_id: LocalDefId,
540-
) -> Option<(LocalDefId, &'tcx FxHashSet<ItemLocalId>)> {
541+
) -> Option<(LocalDefId, &'tcx FxHashSet<LocalDefId>)> {
541542
match tcx.def_kind(def_id) {
542543
DefKind::AnonConst | DefKind::InlineConst => {
543544
let mut def_id = tcx
@@ -774,8 +775,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
774775
});
775776
}
776777
for (&owner, late_bound) in resolved_lifetimes.late_bound.iter() {
777-
late_bound.iter().for_each(|&local_id| {
778-
self.map.late_bound.insert(hir::HirId { owner, local_id });
778+
late_bound.iter().for_each(|&id| {
779+
let hir_id = self.tcx.local_def_id_to_hir_id(id);
780+
debug_assert_eq!(owner, hir_id.owner);
781+
self.map.late_bound.insert(hir_id);
779782
});
780783
}
781784
for (&owner, late_bound_vars) in

Diff for: compiler/rustc_symbol_mangling/src/lib.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@
9797
extern crate rustc_middle;
9898

9999
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
100-
use rustc_hir::Node;
101100
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
102101
use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
103102
use rustc_middle::ty::query::Providers;
@@ -168,17 +167,14 @@ fn compute_symbol_name<'tcx>(
168167

169168
debug!("symbol_name(def_id={:?}, substs={:?})", def_id, substs);
170169

171-
// FIXME(eddyb) Precompute a custom symbol name based on attributes.
172-
let is_foreign = if let Some(def_id) = def_id.as_local() {
170+
if let Some(def_id) = def_id.as_local() {
173171
if tcx.proc_macro_decls_static(()) == Some(def_id) {
174172
let stable_crate_id = tcx.sess.local_stable_crate_id();
175173
return tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id);
176174
}
177-
matches!(tcx.hir().get_by_def_id(def_id), Node::ForeignItem(_))
178-
} else {
179-
tcx.is_foreign_item(def_id)
180-
};
175+
}
181176

177+
// FIXME(eddyb) Precompute a custom symbol name based on attributes.
182178
let attrs = tcx.codegen_fn_attrs(def_id);
183179

184180
// Foreign items by default use no mangling for their symbol name. There's a
@@ -197,7 +193,7 @@ fn compute_symbol_name<'tcx>(
197193
// show up in the `wasm-import-name` custom attribute in LLVM IR.
198194
//
199195
// [1]: https://bugs.llvm.org/show_bug.cgi?id=44316
200-
if is_foreign
196+
if tcx.is_foreign_item(def_id)
201197
&& (!tcx.sess.target.is_like_wasm
202198
|| !tcx.wasm_import_module_map(def_id.krate).contains_key(&def_id))
203199
{

Diff for: compiler/rustc_ty_utils/src/ty.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -414,12 +414,7 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> {
414414
/// Check if a function is async.
415415
fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
416416
let node = tcx.hir().get_by_def_id(def_id.expect_local());
417-
418-
let fn_kind = node.fn_kind().unwrap_or_else(|| {
419-
bug!("asyncness: expected fn-like node but got `{:?}`", def_id);
420-
});
421-
422-
fn_kind.asyncness()
417+
if let Some(fn_kind) = node.fn_kind() { fn_kind.asyncness() } else { hir::IsAsync::NotAsync }
423418
}
424419

425420
/// Don't call this directly: use ``tcx.conservative_is_privately_uninhabited`` instead.

Diff for: compiler/rustc_typeck/src/collect.rs

+27-8
Original file line numberDiff line numberDiff line change
@@ -1388,6 +1388,7 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
13881388

13891389
fn has_late_bound_regions<'tcx>(
13901390
tcx: TyCtxt<'tcx>,
1391+
def_id: LocalDefId,
13911392
generics: &'tcx hir::Generics<'tcx>,
13921393
decl: &'tcx hir::FnDecl<'tcx>,
13931394
) -> Option<Span> {
@@ -1396,9 +1397,14 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
13961397
outer_index: ty::INNERMOST,
13971398
has_late_bound_regions: None,
13981399
};
1400+
let late_bound_map = tcx.is_late_bound_map(def_id);
1401+
let is_late_bound = |id| {
1402+
let id = tcx.hir().local_def_id(id);
1403+
late_bound_map.map_or(false, |(_, set)| set.contains(&id))
1404+
};
13991405
for param in generics.params {
14001406
if let GenericParamKind::Lifetime { .. } = param.kind {
1401-
if tcx.is_late_bound(param.hir_id) {
1407+
if is_late_bound(param.hir_id) {
14021408
return Some(param.span);
14031409
}
14041410
}
@@ -1410,25 +1416,25 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
14101416
match node {
14111417
Node::TraitItem(item) => match item.kind {
14121418
hir::TraitItemKind::Fn(ref sig, _) => {
1413-
has_late_bound_regions(tcx, &item.generics, sig.decl)
1419+
has_late_bound_regions(tcx, item.def_id, &item.generics, sig.decl)
14141420
}
14151421
_ => None,
14161422
},
14171423
Node::ImplItem(item) => match item.kind {
14181424
hir::ImplItemKind::Fn(ref sig, _) => {
1419-
has_late_bound_regions(tcx, &item.generics, sig.decl)
1425+
has_late_bound_regions(tcx, item.def_id, &item.generics, sig.decl)
14201426
}
14211427
_ => None,
14221428
},
14231429
Node::ForeignItem(item) => match item.kind {
14241430
hir::ForeignItemKind::Fn(fn_decl, _, ref generics) => {
1425-
has_late_bound_regions(tcx, generics, fn_decl)
1431+
has_late_bound_regions(tcx, item.def_id, generics, fn_decl)
14261432
}
14271433
_ => None,
14281434
},
14291435
Node::Item(item) => match item.kind {
14301436
hir::ItemKind::Fn(ref sig, .., ref generics, _) => {
1431-
has_late_bound_regions(tcx, generics, sig.decl)
1437+
has_late_bound_regions(tcx, item.def_id, generics, sig.decl)
14321438
}
14331439
_ => None,
14341440
},
@@ -1677,7 +1683,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
16771683
params.push(opt_self);
16781684
}
16791685

1680-
let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics);
1686+
let early_lifetimes = early_bound_lifetimes_from_generics(tcx, hir_id.owner, ast_generics);
16811687
params.extend(early_lifetimes.enumerate().map(|(i, param)| ty::GenericParamDef {
16821688
name: param.name.ident().name,
16831689
index: own_start + i as u32,
@@ -2034,10 +2040,23 @@ fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity {
20342040
/// `resolve_lifetime::early_bound_lifetimes`.
20352041
fn early_bound_lifetimes_from_generics<'a, 'tcx: 'a>(
20362042
tcx: TyCtxt<'tcx>,
2043+
def_id: LocalDefId,
20372044
generics: &'a hir::Generics<'a>,
20382045
) -> impl Iterator<Item = &'a hir::GenericParam<'a>> + Captures<'tcx> {
2046+
let late_bound_map = if generics.params.is_empty() {
2047+
// This function may be called on `def_id == CRATE_DEF_ID`,
2048+
// which makes `is_late_bound_map` ICE. Don't even try if there
2049+
// is no generic parameter.
2050+
None
2051+
} else {
2052+
tcx.is_late_bound_map(def_id)
2053+
};
2054+
let is_late_bound = move |hir_id| {
2055+
let id = tcx.hir().local_def_id(hir_id);
2056+
late_bound_map.map_or(false, |(_, set)| set.contains(&id))
2057+
};
20392058
generics.params.iter().filter(move |param| match param.kind {
2040-
GenericParamKind::Lifetime { .. } => !tcx.is_late_bound(param.hir_id),
2059+
GenericParamKind::Lifetime { .. } => !is_late_bound(param.hir_id),
20412060
_ => false,
20422061
})
20432062
}
@@ -2221,7 +2240,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
22212240
// well. In the case of parameters declared on a fn or method, we
22222241
// have to be careful to only iterate over early-bound regions.
22232242
let mut index = parent_count + has_own_self as u32;
2224-
for param in early_bound_lifetimes_from_generics(tcx, ast_generics) {
2243+
for param in early_bound_lifetimes_from_generics(tcx, hir_id.owner, ast_generics) {
22252244
let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
22262245
def_id: tcx.hir().local_def_id(param.hir_id).to_def_id(),
22272246
index,

0 commit comments

Comments
 (0)