Skip to content

Commit ba40fe9

Browse files
committed
Compute is_late_bound in a separate query.
The computation is actually much simpler, and can be done by directly fetching the HIR for the `FnDecl` and its generics.
1 parent b1294e8 commit ba40fe9

File tree

6 files changed

+47
-99
lines changed

6 files changed

+47
-99
lines changed

compiler/rustc_borrowck/src/universal_regions.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -830,11 +830,11 @@ fn for_each_late_bound_region_defined_on<'tcx>(
830830
fn_def_id: DefId,
831831
mut f: impl FnMut(ty::Region<'tcx>),
832832
) {
833-
if let Some((owner, late_bounds)) = tcx.is_late_bound_map(fn_def_id.expect_local()) {
833+
if let Some(late_bounds) = tcx.is_late_bound_map(fn_def_id.expect_local()) {
834834
for &region_def_id in late_bounds.iter() {
835835
let name = tcx.item_name(region_def_id.to_def_id());
836836
let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion {
837-
scope: owner.to_def_id(),
837+
scope: fn_def_id,
838838
bound_region: ty::BoundRegionKind::BrNamed(region_def_id.to_def_id(), name),
839839
}));
840840
f(liberated_region);

compiler/rustc_middle/src/hir/map/mod.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,11 @@ impl<'hir> Map<'hir> {
364364
match node.node {
365365
OwnerNode::ImplItem(impl_item) => Some(&impl_item.generics),
366366
OwnerNode::TraitItem(trait_item) => Some(&trait_item.generics),
367-
OwnerNode::Item(Item {
367+
OwnerNode::ForeignItem(ForeignItem {
368+
kind: ForeignItemKind::Fn(_, _, generics),
369+
..
370+
})
371+
| OwnerNode::Item(Item {
368372
kind:
369373
ItemKind::Fn(_, generics, _)
370374
| ItemKind::TyAlias(_, generics)

compiler/rustc_middle/src/query/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1584,7 +1584,7 @@ rustc_queries! {
15841584
Option<&'tcx FxHashMap<ItemLocalId, Region>> {
15851585
desc { "looking up a named region" }
15861586
}
1587-
query is_late_bound_map(_: LocalDefId) -> Option<(LocalDefId, &'tcx FxHashSet<LocalDefId>)> {
1587+
query is_late_bound_map(_: LocalDefId) -> Option<&'tcx FxHashSet<LocalDefId>> {
15881588
desc { "testing if a region is late bound" }
15891589
}
15901590
/// For a given item (like a struct), gets the default lifetimes to be used

compiler/rustc_middle/src/ty/context.rs

+7
Original file line numberDiff line numberDiff line change
@@ -2803,6 +2803,13 @@ impl<'tcx> TyCtxt<'tcx> {
28032803
self.named_region_map(id.owner).and_then(|map| map.get(&id.local_id).cloned())
28042804
}
28052805

2806+
pub fn is_late_bound(self, id: HirId) -> bool {
2807+
self.is_late_bound_map(id.owner).map_or(false, |set| {
2808+
let def_id = self.hir().local_def_id(id);
2809+
set.contains(&def_id)
2810+
})
2811+
}
2812+
28062813
pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> {
28072814
self.mk_bound_variable_kinds(
28082815
self.late_bound_vars_map(id.owner)

compiler/rustc_resolve/src/late/lifetimes.rs

+24-68
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ use rustc_hir::def_id::{DefIdMap, LocalDefId};
1616
use rustc_hir::hir_id::ItemLocalId;
1717
use rustc_hir::intravisit::{self, Visitor};
1818
use rustc_hir::{GenericArg, GenericParam, LifetimeName, Node};
19-
use rustc_hir::{GenericParamKind, HirIdMap, HirIdSet};
19+
use rustc_hir::{GenericParamKind, HirIdMap};
2020
use rustc_middle::hir::map::Map;
2121
use rustc_middle::hir::nested_filter;
2222
use rustc_middle::middle::resolve_lifetime::*;
23-
use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, TyCtxt};
23+
use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
2424
use rustc_middle::{bug, span_bug};
2525
use rustc_span::def_id::DefId;
2626
use rustc_span::symbol::{kw, sym, Ident};
@@ -134,11 +134,6 @@ struct NamedRegionMap {
134134
// `Region` describing how that region is bound
135135
defs: HirIdMap<Region>,
136136

137-
// the set of lifetime def ids that are late-bound; a region can
138-
// be late-bound if (a) it does NOT appear in a where-clause and
139-
// (b) it DOES appear in the arguments.
140-
late_bound: HirIdSet,
141-
142137
// Maps relevant hir items to the bound vars on them. These include:
143138
// - function defs
144139
// - function pointers
@@ -402,15 +397,15 @@ fn resolve_lifetimes_trait_definition(
402397
tcx: TyCtxt<'_>,
403398
local_def_id: LocalDefId,
404399
) -> ResolveLifetimes {
405-
convert_named_region_map(tcx, do_resolve(tcx, local_def_id, true, false))
400+
convert_named_region_map(do_resolve(tcx, local_def_id, true, false))
406401
}
407402

408403
/// Computes the `ResolveLifetimes` map that contains data for an entire `Item`.
409404
/// You should not read the result of this query directly, but rather use
410405
/// `named_region_map`, `is_late_bound_map`, etc.
411406
#[tracing::instrument(level = "debug", skip(tcx))]
412407
fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> ResolveLifetimes {
413-
convert_named_region_map(tcx, do_resolve(tcx, local_def_id, false, false))
408+
convert_named_region_map(do_resolve(tcx, local_def_id, false, false))
414409
}
415410

416411
fn do_resolve(
@@ -422,7 +417,6 @@ fn do_resolve(
422417
let item = tcx.hir().expect_item(local_def_id);
423418
let mut named_region_map = NamedRegionMap {
424419
defs: Default::default(),
425-
late_bound: Default::default(),
426420
late_bound_vars: Default::default(),
427421
scope_for_path: with_scope_for_path.then(|| Default::default()),
428422
};
@@ -439,18 +433,13 @@ fn do_resolve(
439433
named_region_map
440434
}
441435

442-
fn convert_named_region_map(tcx: TyCtxt<'_>, named_region_map: NamedRegionMap) -> ResolveLifetimes {
436+
fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetimes {
443437
let mut rl = ResolveLifetimes::default();
444438

445439
for (hir_id, v) in named_region_map.defs {
446440
let map = rl.defs.entry(hir_id.owner).or_default();
447441
map.insert(hir_id.local_id, v);
448442
}
449-
for hir_id in named_region_map.late_bound {
450-
let map = rl.late_bound.entry(hir_id.owner).or_default();
451-
let def_id = tcx.hir().local_def_id(hir_id);
452-
map.insert(def_id);
453-
}
454443
for (hir_id, v) in named_region_map.late_bound_vars {
455444
let map = rl.late_bound_vars.entry(hir_id.owner).or_default();
456445
map.insert(hir_id.local_id, v);
@@ -506,28 +495,6 @@ fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId {
506495
item
507496
}
508497

509-
fn is_late_bound_map<'tcx>(
510-
tcx: TyCtxt<'tcx>,
511-
def_id: LocalDefId,
512-
) -> Option<(LocalDefId, &'tcx FxHashSet<LocalDefId>)> {
513-
match tcx.def_kind(def_id) {
514-
DefKind::AnonConst | DefKind::InlineConst => {
515-
let mut def_id = tcx.local_parent(def_id);
516-
// We search for the next outer anon const or fn here
517-
// while skipping closures.
518-
//
519-
// Note that for `AnonConst` we still just recurse until we
520-
// find a function body, but who cares :shrug:
521-
while tcx.is_closure(def_id.to_def_id()) {
522-
def_id = tcx.local_parent(def_id);
523-
}
524-
525-
tcx.is_late_bound_map(def_id)
526-
}
527-
_ => resolve_lifetimes_for(tcx, def_id).late_bound.get(&def_id).map(|lt| (def_id, lt)),
528-
}
529-
}
530-
531498
/// In traits, there is an implicit `Self` type parameter which comes before the generics.
532499
/// We have to account for this when computing the index of the other generic parameters.
533500
/// This function returns whether there is such an implicit parameter defined on the given item.
@@ -687,9 +654,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
687654
_ => {}
688655
}
689656
match item.kind {
690-
hir::ItemKind::Fn(ref sig, ref generics, _) => {
657+
hir::ItemKind::Fn(_, ref generics, _) => {
691658
self.missing_named_lifetime_spots.push(generics.into());
692-
self.visit_early_late(None, item.hir_id(), &sig.decl, generics, |this| {
659+
self.visit_early_late(None, item.hir_id(), generics, |this| {
693660
intravisit::walk_item(this, item);
694661
});
695662
self.missing_named_lifetime_spots.pop();
@@ -731,13 +698,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
731698
self.map.defs.insert(hir::HirId { owner, local_id }, *region);
732699
});
733700
}
734-
for (&owner, late_bound) in resolved_lifetimes.late_bound.iter() {
735-
late_bound.iter().for_each(|&id| {
736-
let hir_id = self.tcx.local_def_id_to_hir_id(id);
737-
debug_assert_eq!(owner, hir_id.owner);
738-
self.map.late_bound.insert(hir_id);
739-
});
740-
}
741701
for (&owner, late_bound_vars) in
742702
resolved_lifetimes.late_bound_vars.iter()
743703
{
@@ -807,8 +767,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
807767

808768
fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
809769
match item.kind {
810-
hir::ForeignItemKind::Fn(ref decl, _, ref generics) => {
811-
self.visit_early_late(None, item.hir_id(), decl, generics, |this| {
770+
hir::ForeignItemKind::Fn(_, _, ref generics) => {
771+
self.visit_early_late(None, item.hir_id(), generics, |this| {
812772
intravisit::walk_foreign_item(this, item);
813773
})
814774
}
@@ -1085,13 +1045,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
10851045
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
10861046
use self::hir::TraitItemKind::*;
10871047
match trait_item.kind {
1088-
Fn(ref sig, _) => {
1048+
Fn(_, _) => {
10891049
self.missing_named_lifetime_spots.push((&trait_item.generics).into());
10901050
let tcx = self.tcx;
10911051
self.visit_early_late(
10921052
Some(tcx.hir().get_parent_item(trait_item.hir_id())),
10931053
trait_item.hir_id(),
1094-
&sig.decl,
10951054
&trait_item.generics,
10961055
|this| intravisit::walk_trait_item(this, trait_item),
10971056
);
@@ -1153,13 +1112,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
11531112
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
11541113
use self::hir::ImplItemKind::*;
11551114
match impl_item.kind {
1156-
Fn(ref sig, _) => {
1115+
Fn(..) => {
11571116
self.missing_named_lifetime_spots.push((&impl_item.generics).into());
11581117
let tcx = self.tcx;
11591118
self.visit_early_late(
11601119
Some(tcx.hir().get_parent_item(impl_item.hir_id())),
11611120
impl_item.hir_id(),
1162-
&sig.decl,
11631121
&impl_item.generics,
11641122
|this| intravisit::walk_impl_item(this, impl_item),
11651123
);
@@ -1656,14 +1614,11 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
16561614
&mut self,
16571615
parent_id: Option<LocalDefId>,
16581616
hir_id: hir::HirId,
1659-
decl: &'tcx hir::FnDecl<'tcx>,
16601617
generics: &'tcx hir::Generics<'tcx>,
16611618
walk: F,
16621619
) where
16631620
F: for<'b, 'c> FnOnce(&'b mut LifetimeContext<'c, 'tcx>),
16641621
{
1665-
insert_late_bound_lifetimes(self.tcx, self.map, decl, generics);
1666-
16671622
// Find the start of nested early scopes, e.g., in methods.
16681623
let mut next_early_index = 0;
16691624
if let Some(parent_id) = parent_id {
@@ -1687,7 +1642,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
16871642
.iter()
16881643
.filter_map(|param| match param.kind {
16891644
GenericParamKind::Lifetime { .. } => {
1690-
if self.map.late_bound.contains(&param.hir_id) {
1645+
if self.tcx.is_late_bound(param.hir_id) {
16911646
let late_bound_idx = named_late_bound_vars;
16921647
named_late_bound_vars += 1;
16931648
Some(Region::late(late_bound_idx, self.tcx.hir(), param))
@@ -1708,7 +1663,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
17081663
.iter()
17091664
.filter(|param| {
17101665
matches!(param.kind, GenericParamKind::Lifetime { .. })
1711-
&& self.map.late_bound.contains(&param.hir_id)
1666+
&& self.tcx.is_late_bound(param.hir_id)
17121667
})
17131668
.enumerate()
17141669
.map(|(late_bound_idx, param)| {
@@ -2613,7 +2568,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
26132568
}
26142569

26152570
/// Detects late-bound lifetimes and inserts them into
2616-
/// `map.late_bound`.
2571+
/// `late_bound`.
26172572
///
26182573
/// A region declared on a fn is **late-bound** if:
26192574
/// - it is constrained by an argument type;
@@ -2622,13 +2577,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
26222577
/// "Constrained" basically means that it appears in any type but
26232578
/// not amongst the inputs to a projection. In other words, `<&'a
26242579
/// T as Trait<''b>>::Foo` does not constrain `'a` or `'b`.
2625-
#[tracing::instrument(level = "debug", skip(tcx, map))]
2626-
fn insert_late_bound_lifetimes(
2627-
tcx: TyCtxt<'_>,
2628-
map: &mut NamedRegionMap,
2629-
decl: &hir::FnDecl<'_>,
2630-
generics: &hir::Generics<'_>,
2631-
) {
2580+
fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxHashSet<LocalDefId>> {
2581+
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
2582+
let decl = tcx.hir().fn_decl_by_hir_id(hir_id)?;
2583+
let generics = tcx.hir().get_generics(def_id)?;
2584+
2585+
let mut late_bound = FxHashSet::default();
2586+
26322587
let mut constrained_by_input = ConstrainedCollector::default();
26332588
for arg_ty in decl.inputs {
26342589
constrained_by_input.visit_ty(arg_ty);
@@ -2675,11 +2630,12 @@ fn insert_late_bound_lifetimes(
26752630

26762631
debug!("lifetime {:?} with id {:?} is late-bound", param.name.ident(), param.hir_id);
26772632

2678-
let inserted = map.late_bound.insert(param.hir_id);
2633+
let inserted = late_bound.insert(param_def_id);
26792634
assert!(inserted, "visited lifetime {:?} twice", param.hir_id);
26802635
}
26812636

2682-
return;
2637+
debug!(?late_bound);
2638+
return Some(tcx.arena.alloc(late_bound));
26832639

26842640
#[derive(Default)]
26852641
struct ConstrainedCollector {

compiler/rustc_typeck/src/collect.rs

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

13651365
fn has_late_bound_regions<'tcx>(
13661366
tcx: TyCtxt<'tcx>,
1367-
def_id: LocalDefId,
13681367
generics: &'tcx hir::Generics<'tcx>,
13691368
decl: &'tcx hir::FnDecl<'tcx>,
13701369
) -> Option<Span> {
@@ -1373,14 +1372,9 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
13731372
outer_index: ty::INNERMOST,
13741373
has_late_bound_regions: None,
13751374
};
1376-
let late_bound_map = tcx.is_late_bound_map(def_id);
1377-
let is_late_bound = |id| {
1378-
let id = tcx.hir().local_def_id(id);
1379-
late_bound_map.map_or(false, |(_, set)| set.contains(&id))
1380-
};
13811375
for param in generics.params {
13821376
if let GenericParamKind::Lifetime { .. } = param.kind {
1383-
if is_late_bound(param.hir_id) {
1377+
if tcx.is_late_bound(param.hir_id) {
13841378
return Some(param.span);
13851379
}
13861380
}
@@ -1392,25 +1386,25 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
13921386
match node {
13931387
Node::TraitItem(item) => match item.kind {
13941388
hir::TraitItemKind::Fn(ref sig, _) => {
1395-
has_late_bound_regions(tcx, item.def_id, &item.generics, sig.decl)
1389+
has_late_bound_regions(tcx, &item.generics, sig.decl)
13961390
}
13971391
_ => None,
13981392
},
13991393
Node::ImplItem(item) => match item.kind {
14001394
hir::ImplItemKind::Fn(ref sig, _) => {
1401-
has_late_bound_regions(tcx, item.def_id, &item.generics, sig.decl)
1395+
has_late_bound_regions(tcx, &item.generics, sig.decl)
14021396
}
14031397
_ => None,
14041398
},
14051399
Node::ForeignItem(item) => match item.kind {
14061400
hir::ForeignItemKind::Fn(fn_decl, _, ref generics) => {
1407-
has_late_bound_regions(tcx, item.def_id, generics, fn_decl)
1401+
has_late_bound_regions(tcx, generics, fn_decl)
14081402
}
14091403
_ => None,
14101404
},
14111405
Node::Item(item) => match item.kind {
14121406
hir::ItemKind::Fn(ref sig, .., ref generics, _) => {
1413-
has_late_bound_regions(tcx, item.def_id, generics, sig.decl)
1407+
has_late_bound_regions(tcx, generics, sig.decl)
14141408
}
14151409
_ => None,
14161410
},
@@ -1671,7 +1665,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
16711665
params.push(opt_self);
16721666
}
16731667

1674-
let early_lifetimes = early_bound_lifetimes_from_generics(tcx, hir_id.owner, ast_generics);
1668+
let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics);
16751669
params.extend(early_lifetimes.enumerate().map(|(i, param)| ty::GenericParamDef {
16761670
name: param.name.ident().name,
16771671
index: own_start + i as u32,
@@ -2054,23 +2048,10 @@ fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity {
20542048
/// `resolve_lifetime::early_bound_lifetimes`.
20552049
fn early_bound_lifetimes_from_generics<'a, 'tcx: 'a>(
20562050
tcx: TyCtxt<'tcx>,
2057-
def_id: LocalDefId,
20582051
generics: &'a hir::Generics<'a>,
20592052
) -> impl Iterator<Item = &'a hir::GenericParam<'a>> + Captures<'tcx> {
2060-
let late_bound_map = if generics.params.is_empty() {
2061-
// This function may be called on `def_id == CRATE_DEF_ID`,
2062-
// which makes `is_late_bound_map` ICE. Don't even try if there
2063-
// is no generic parameter.
2064-
None
2065-
} else {
2066-
tcx.is_late_bound_map(def_id)
2067-
};
2068-
let is_late_bound = move |hir_id| {
2069-
let id = tcx.hir().local_def_id(hir_id);
2070-
late_bound_map.map_or(false, |(_, set)| set.contains(&id))
2071-
};
20722053
generics.params.iter().filter(move |param| match param.kind {
2073-
GenericParamKind::Lifetime { .. } => !is_late_bound(param.hir_id),
2054+
GenericParamKind::Lifetime { .. } => !tcx.is_late_bound(param.hir_id),
20742055
_ => false,
20752056
})
20762057
}
@@ -2255,7 +2236,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
22552236
// have to be careful to only iterate over early-bound regions.
22562237
let mut index = parent_count
22572238
+ has_own_self as u32
2258-
+ early_bound_lifetimes_from_generics(tcx, hir_id.owner, ast_generics).count() as u32;
2239+
+ early_bound_lifetimes_from_generics(tcx, ast_generics).count() as u32;
22592240

22602241
// Collect the predicates that were written inline by the user on each
22612242
// type parameter (e.g., `<T: Foo>`).

0 commit comments

Comments
 (0)