From 69d818333755d4b836a28a4498f2caad71c2d014 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 30 Mar 2022 00:17:41 +0200 Subject: [PATCH] Store LocalDefId in is_late_bound_map. This allows to avoid looking at HIR from borrowck. --- .../rustc_borrowck/src/universal_regions.rs | 8 ++--- .../src/middle/resolve_lifetime.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 3 +- compiler/rustc_middle/src/ty/context.rs | 5 --- compiler/rustc_resolve/src/late/lifetimes.rs | 17 +++++---- compiler/rustc_typeck/src/collect.rs | 35 ++++++++++++++----- 6 files changed, 42 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 28a566ca408..e26adba0d30 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -828,13 +828,11 @@ fn for_each_late_bound_region_defined_on<'tcx>( mut f: impl FnMut(ty::Region<'tcx>), ) { if let Some((owner, late_bounds)) = tcx.is_late_bound_map(fn_def_id.expect_local()) { - for &late_bound in late_bounds.iter() { - let region_def_id = - tcx.hir().local_def_id(HirId { owner, local_id: late_bound }).to_def_id(); - let name = tcx.item_name(region_def_id); + for ®ion_def_id in late_bounds.iter() { + let name = tcx.item_name(region_def_id.to_def_id()); let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion { scope: owner.to_def_id(), - bound_region: ty::BoundRegionKind::BrNamed(region_def_id, name), + bound_region: ty::BoundRegionKind::BrNamed(region_def_id.to_def_id(), name), })); f(liberated_region); } diff --git a/compiler/rustc_middle/src/middle/resolve_lifetime.rs b/compiler/rustc_middle/src/middle/resolve_lifetime.rs index bc50730ab8b..70586cefaee 100644 --- a/compiler/rustc_middle/src/middle/resolve_lifetime.rs +++ b/compiler/rustc_middle/src/middle/resolve_lifetime.rs @@ -64,7 +64,7 @@ pub struct ResolveLifetimes { /// Set of lifetime def ids that are late-bound; a region can /// be late-bound if (a) it does NOT appear in a where-clause and /// (b) it DOES appear in the arguments. - pub late_bound: FxHashMap>, + pub late_bound: FxHashMap>, pub late_bound_vars: FxHashMap>>, } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index bbe1d367b77..f38ade1076e 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1502,8 +1502,7 @@ rustc_queries! { Option<&'tcx FxHashMap> { desc { "looking up a named region" } } - query is_late_bound_map(_: LocalDefId) -> - Option<(LocalDefId, &'tcx FxHashSet)> { + query is_late_bound_map(_: LocalDefId) -> Option<(LocalDefId, &'tcx FxHashSet)> { desc { "testing if a region is late bound" } } /// For a given item (like a struct), gets the default lifetimes to be used diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index a26de409b3c..5244aaaec0a 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2772,11 +2772,6 @@ impl<'tcx> TyCtxt<'tcx> { self.named_region_map(id.owner).and_then(|map| map.get(&id.local_id).cloned()) } - pub fn is_late_bound(self, id: HirId) -> bool { - self.is_late_bound_map(id.owner) - .map_or(false, |(owner, set)| owner == id.owner && set.contains(&id.local_id)) - } - pub fn late_bound_vars(self, id: HirId) -> &'tcx List { self.mk_bound_variable_kinds( self.late_bound_vars_map(id.owner) diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 1460b5efbb0..2bf01146fae 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -427,7 +427,7 @@ fn resolve_lifetimes_trait_definition( tcx: TyCtxt<'_>, local_def_id: LocalDefId, ) -> ResolveLifetimes { - convert_named_region_map(do_resolve(tcx, local_def_id, true, false)) + convert_named_region_map(tcx, do_resolve(tcx, local_def_id, true, false)) } /// Computes the `ResolveLifetimes` map that contains data for an entire `Item`. @@ -435,7 +435,7 @@ fn resolve_lifetimes_trait_definition( /// `named_region_map`, `is_late_bound_map`, etc. #[tracing::instrument(level = "debug", skip(tcx))] fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> ResolveLifetimes { - convert_named_region_map(do_resolve(tcx, local_def_id, false, false)) + convert_named_region_map(tcx, do_resolve(tcx, local_def_id, false, false)) } fn do_resolve( @@ -468,7 +468,7 @@ fn do_resolve( named_region_map } -fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetimes { +fn convert_named_region_map(tcx: TyCtxt<'_>, named_region_map: NamedRegionMap) -> ResolveLifetimes { let mut rl = ResolveLifetimes::default(); for (hir_id, v) in named_region_map.defs { @@ -477,7 +477,8 @@ fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetime } for hir_id in named_region_map.late_bound { let map = rl.late_bound.entry(hir_id.owner).or_default(); - map.insert(hir_id.local_id); + let def_id = tcx.hir().local_def_id(hir_id); + map.insert(def_id); } for (hir_id, v) in named_region_map.late_bound_vars { 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 { fn is_late_bound_map<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, -) -> Option<(LocalDefId, &'tcx FxHashSet)> { +) -> Option<(LocalDefId, &'tcx FxHashSet)> { match tcx.def_kind(def_id) { DefKind::AnonConst | DefKind::InlineConst => { let mut def_id = tcx @@ -774,8 +775,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }); } for (&owner, late_bound) in resolved_lifetimes.late_bound.iter() { - late_bound.iter().for_each(|&local_id| { - self.map.late_bound.insert(hir::HirId { owner, local_id }); + late_bound.iter().for_each(|&id| { + let hir_id = self.tcx.local_def_id_to_hir_id(id); + debug_assert_eq!(owner, hir_id.owner); + self.map.late_bound.insert(hir_id); }); } for (&owner, late_bound_vars) in diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 026151ce7df..153ab8d95fd 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1388,6 +1388,7 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option( tcx: TyCtxt<'tcx>, + def_id: LocalDefId, generics: &'tcx hir::Generics<'tcx>, decl: &'tcx hir::FnDecl<'tcx>, ) -> Option { @@ -1396,9 +1397,14 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option match item.kind { hir::TraitItemKind::Fn(ref sig, _) => { - has_late_bound_regions(tcx, &item.generics, sig.decl) + has_late_bound_regions(tcx, item.def_id, &item.generics, sig.decl) } _ => None, }, Node::ImplItem(item) => match item.kind { hir::ImplItemKind::Fn(ref sig, _) => { - has_late_bound_regions(tcx, &item.generics, sig.decl) + has_late_bound_regions(tcx, item.def_id, &item.generics, sig.decl) } _ => None, }, Node::ForeignItem(item) => match item.kind { hir::ForeignItemKind::Fn(fn_decl, _, ref generics) => { - has_late_bound_regions(tcx, generics, fn_decl) + has_late_bound_regions(tcx, item.def_id, generics, fn_decl) } _ => None, }, Node::Item(item) => match item.kind { hir::ItemKind::Fn(ref sig, .., ref generics, _) => { - has_late_bound_regions(tcx, generics, sig.decl) + has_late_bound_regions(tcx, item.def_id, generics, sig.decl) } _ => None, }, @@ -1677,7 +1683,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { params.push(opt_self); } - let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics); + let early_lifetimes = early_bound_lifetimes_from_generics(tcx, hir_id.owner, ast_generics); params.extend(early_lifetimes.enumerate().map(|(i, param)| ty::GenericParamDef { name: param.name.ident().name, index: own_start + i as u32, @@ -2034,10 +2040,23 @@ fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity { /// `resolve_lifetime::early_bound_lifetimes`. fn early_bound_lifetimes_from_generics<'a, 'tcx: 'a>( tcx: TyCtxt<'tcx>, + def_id: LocalDefId, generics: &'a hir::Generics<'a>, ) -> impl Iterator> + Captures<'tcx> { + let late_bound_map = if generics.params.is_empty() { + // This function may be called on `def_id == CRATE_DEF_ID`, + // which makes `is_late_bound_map` ICE. Don't even try if there + // is no generic parameter. + None + } else { + tcx.is_late_bound_map(def_id) + }; + let is_late_bound = move |hir_id| { + let id = tcx.hir().local_def_id(hir_id); + late_bound_map.map_or(false, |(_, set)| set.contains(&id)) + }; generics.params.iter().filter(move |param| match param.kind { - GenericParamKind::Lifetime { .. } => !tcx.is_late_bound(param.hir_id), + GenericParamKind::Lifetime { .. } => !is_late_bound(param.hir_id), _ => false, }) } @@ -2221,7 +2240,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP // well. In the case of parameters declared on a fn or method, we // have to be careful to only iterate over early-bound regions. let mut index = parent_count + has_own_self as u32; - for param in early_bound_lifetimes_from_generics(tcx, ast_generics) { + for param in early_bound_lifetimes_from_generics(tcx, hir_id.owner, ast_generics) { let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { def_id: tcx.hir().local_def_id(param.hir_id).to_def_id(), index,