Skip to content

Commit a736acc

Browse files
authored
Rollup merge of #97312 - cjgillot:no-path-in-scope, r=compiler-errors
Compute lifetimes in scope at diagnostic time The set of available lifetimes is currently computed during lifetime resolution on HIR. It is only used for one diagnostic. In this PR, HIR lifetime resolution just reports whether elided lifetimes are well-defined at the place of use. The diagnostic code is responsible for building a list of lifetime names if elision is not allowed. This will allow to remove lifetime resolution on HIR eventually.
2 parents e70c60d + f71ad2f commit a736acc

File tree

15 files changed

+127
-206
lines changed

15 files changed

+127
-206
lines changed

compiler/rustc_ast_lowering/src/index.rs

+7
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,13 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
313313
});
314314
}
315315

316+
fn visit_assoc_type_binding(&mut self, type_binding: &'hir TypeBinding<'hir>) {
317+
self.insert(type_binding.span, type_binding.hir_id, Node::TypeBinding(type_binding));
318+
self.with_parent(type_binding.hir_id, |this| {
319+
intravisit::walk_assoc_type_binding(this, type_binding)
320+
})
321+
}
322+
316323
fn visit_trait_item_ref(&mut self, ii: &'hir TraitItemRef) {
317324
// Do not visit the duplicate information in TraitItemRef. We want to
318325
// map the actual nodes, not the duplicate ones in the *Ref.

compiler/rustc_hir/src/hir.rs

+2
Original file line numberDiff line numberDiff line change
@@ -3302,6 +3302,7 @@ pub enum Node<'hir> {
33023302
Stmt(&'hir Stmt<'hir>),
33033303
PathSegment(&'hir PathSegment<'hir>),
33043304
Ty(&'hir Ty<'hir>),
3305+
TypeBinding(&'hir TypeBinding<'hir>),
33053306
TraitRef(&'hir TraitRef<'hir>),
33063307
Binding(&'hir Pat<'hir>),
33073308
Pat(&'hir Pat<'hir>),
@@ -3347,6 +3348,7 @@ impl<'hir> Node<'hir> {
33473348
| Node::PathSegment(PathSegment { ident, .. }) => Some(*ident),
33483349
Node::Lifetime(lt) => Some(lt.name.ident()),
33493350
Node::GenericParam(p) => Some(p.name.ident()),
3351+
Node::TypeBinding(b) => Some(b.ident),
33503352
Node::Param(..)
33513353
| Node::AnonConst(..)
33523354
| Node::Expr(..)

compiler/rustc_hir_pretty/src/lib.rs

+20-15
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ impl<'a> State<'a> {
8585
Node::Stmt(a) => self.print_stmt(&a),
8686
Node::PathSegment(a) => self.print_path_segment(&a),
8787
Node::Ty(a) => self.print_type(&a),
88+
Node::TypeBinding(a) => self.print_type_binding(&a),
8889
Node::TraitRef(a) => self.print_trait_ref(&a),
8990
Node::Binding(a) | Node::Pat(a) => self.print_pat(&a),
9091
Node::Arm(a) => self.print_arm(&a),
@@ -1703,21 +1704,7 @@ impl<'a> State<'a> {
17031704

17041705
for binding in generic_args.bindings.iter() {
17051706
start_or_comma(self);
1706-
self.print_ident(binding.ident);
1707-
self.print_generic_args(binding.gen_args, false, false);
1708-
self.space();
1709-
match generic_args.bindings[0].kind {
1710-
hir::TypeBindingKind::Equality { ref term } => {
1711-
self.word_space("=");
1712-
match term {
1713-
Term::Ty(ref ty) => self.print_type(ty),
1714-
Term::Const(ref c) => self.print_anon_const(c),
1715-
}
1716-
}
1717-
hir::TypeBindingKind::Constraint { bounds } => {
1718-
self.print_bounds(":", bounds);
1719-
}
1720-
}
1707+
self.print_type_binding(binding);
17211708
}
17221709

17231710
if !empty.get() {
@@ -1726,6 +1713,24 @@ impl<'a> State<'a> {
17261713
}
17271714
}
17281715

1716+
pub fn print_type_binding(&mut self, binding: &hir::TypeBinding<'_>) {
1717+
self.print_ident(binding.ident);
1718+
self.print_generic_args(binding.gen_args, false, false);
1719+
self.space();
1720+
match binding.kind {
1721+
hir::TypeBindingKind::Equality { ref term } => {
1722+
self.word_space("=");
1723+
match term {
1724+
Term::Ty(ref ty) => self.print_type(ty),
1725+
Term::Const(ref c) => self.print_anon_const(c),
1726+
}
1727+
}
1728+
hir::TypeBindingKind::Constraint { bounds } => {
1729+
self.print_bounds(":", bounds);
1730+
}
1731+
}
1732+
}
1733+
17291734
pub fn print_pat(&mut self, pat: &hir::Pat<'_>) {
17301735
self.maybe_print_comment(pat.span.lo());
17311736
self.ann.pre(self, AnnNode::Pat(pat));

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ impl<'hir> Map<'hir> {
298298
Node::Stmt(_)
299299
| Node::PathSegment(_)
300300
| Node::Ty(_)
301+
| Node::TypeBinding(_)
301302
| Node::Infer(_)
302303
| Node::TraitRef(_)
303304
| Node::Pat(_)
@@ -323,7 +324,8 @@ impl<'hir> Map<'hir> {
323324
}
324325

325326
pub fn get_parent_node(self, hir_id: HirId) -> HirId {
326-
self.find_parent_node(hir_id).unwrap()
327+
self.find_parent_node(hir_id)
328+
.unwrap_or_else(|| bug!("No parent for node {:?}", self.node_to_string(hir_id)))
327329
}
328330

329331
/// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found.
@@ -973,6 +975,7 @@ impl<'hir> Map<'hir> {
973975
.with_hi(seg.args.map_or_else(|| ident_span.hi(), |args| args.span_ext.hi()))
974976
}
975977
Node::Ty(ty) => ty.span,
978+
Node::TypeBinding(tb) => tb.span,
976979
Node::TraitRef(tr) => tr.path.span,
977980
Node::Binding(pat) => pat.span,
978981
Node::Pat(pat) => pat.span,
@@ -1205,6 +1208,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
12051208
Some(Node::Stmt(_)) => node_str("stmt"),
12061209
Some(Node::PathSegment(_)) => node_str("path segment"),
12071210
Some(Node::Ty(_)) => node_str("type"),
1211+
Some(Node::TypeBinding(_)) => node_str("type binding"),
12081212
Some(Node::TraitRef(_)) => node_str("trait ref"),
12091213
Some(Node::Binding(_)) => node_str("local"),
12101214
Some(Node::Pat(_)) => node_str("pat"),

compiler/rustc_middle/src/middle/resolve_lifetime.rs

-14
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,6 @@ pub enum Region {
1616
Free(DefId, /* lifetime decl */ DefId),
1717
}
1818

19-
/// This is used in diagnostics to improve suggestions for missing generic arguments.
20-
/// It gives information on the type of lifetimes that are in scope for a particular `PathSegment`,
21-
/// so that we can e.g. suggest elided-lifetimes-in-paths of the form <'_, '_> e.g.
22-
#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)]
23-
pub enum LifetimeScopeForPath {
24-
/// Contains all lifetime names that are in scope and could possibly be used in generics
25-
/// arguments of path.
26-
NonElided(Vec<LocalDefId>),
27-
28-
/// Information that allows us to suggest args of the form `<'_>` in case
29-
/// no generic arguments were provided for a path.
30-
Elided,
31-
}
32-
3319
/// A set containing, at most, one known element.
3420
/// If two distinct values are inserted into a set, then it
3521
/// becomes `Many`, which can be used to detect ambiguities.

compiler/rustc_middle/src/query/mod.rs

-5
Original file line numberDiff line numberDiff line change
@@ -1599,11 +1599,6 @@ rustc_queries! {
15991599
desc { "looking up late bound vars" }
16001600
}
16011601

1602-
query lifetime_scope_map(_: LocalDefId) -> Option<FxHashMap<ItemLocalId, LifetimeScopeForPath>> {
1603-
storage(ArenaCacheSelector<'tcx>)
1604-
desc { "finds the lifetime scope for an HirId of a PathSegment" }
1605-
}
1606-
16071602
query visibility(def_id: DefId) -> ty::Visibility {
16081603
desc { |tcx| "computing visibility of `{}`", tcx.def_path_str(def_id) }
16091604
separate_provide_extern

compiler/rustc_middle/src/ty/context.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::hir::place::Place as HirPlace;
66
use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
77
use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource};
88
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
9-
use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath};
9+
use crate::middle::resolve_lifetime;
1010
use crate::middle::stability;
1111
use crate::mir::interpret::{self, Allocation, ConstAllocation, ConstValue, Scalar};
1212
use crate::mir::{
@@ -2821,10 +2821,6 @@ impl<'tcx> TyCtxt<'tcx> {
28212821
)
28222822
}
28232823

2824-
pub fn lifetime_scope(self, id: HirId) -> Option<&'tcx LifetimeScopeForPath> {
2825-
self.lifetime_scope_map(id.owner).as_ref().and_then(|map| map.get(&id.local_id))
2826-
}
2827-
28282824
/// Whether the `def_id` counts as const fn in the current crate, considering all active
28292825
/// feature gates
28302826
pub fn is_const_fn(self, def_id: DefId) -> bool {

compiler/rustc_middle/src/ty/query.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
66
use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
77
use crate::middle::lib_features::LibFeatures;
88
use crate::middle::privacy::AccessLevels;
9-
use crate::middle::resolve_lifetime::{
10-
LifetimeScopeForPath, ObjectLifetimeDefault, Region, ResolveLifetimes,
11-
};
9+
use crate::middle::resolve_lifetime::{ObjectLifetimeDefault, Region, ResolveLifetimes};
1210
use crate::middle::stability::{self, DeprecationEntry};
1311
use crate::mir;
1412
use crate::mir::interpret::GlobalId;

compiler/rustc_resolve/src/late/lifetimes.rs

+8-97
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@
88
99
use crate::late::diagnostics::{ForLifetimeSpanType, MissingLifetimeSpot};
1010
use rustc_ast::walk_list;
11-
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
11+
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
1212
use rustc_errors::struct_span_err;
1313
use rustc_hir as hir;
1414
use rustc_hir::def::{DefKind, Res};
1515
use rustc_hir::def_id::{DefIdMap, LocalDefId};
16-
use rustc_hir::hir_id::ItemLocalId;
1716
use rustc_hir::intravisit::{self, Visitor};
1817
use rustc_hir::{GenericArg, GenericParam, LifetimeName, Node};
1918
use rustc_hir::{GenericParamKind, HirIdMap};
@@ -141,9 +140,6 @@ struct NamedRegionMap {
141140
// - trait refs
142141
// - bound types (like `T` in `for<'a> T<'a>: Foo`)
143142
late_bound_vars: HirIdMap<Vec<ty::BoundVariableKind>>,
144-
145-
// maps `PathSegment` `HirId`s to lifetime scopes.
146-
scope_for_path: Option<FxHashMap<LocalDefId, FxHashMap<ItemLocalId, LifetimeScopeForPath>>>,
147143
}
148144

149145
pub(crate) struct LifetimeContext<'a, 'tcx> {
@@ -362,10 +358,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
362358
_ => None,
363359
},
364360
late_bound_vars_map: |tcx, id| resolve_lifetimes_for(tcx, id).late_bound_vars.get(&id),
365-
lifetime_scope_map: |tcx, id| {
366-
let item_id = item_for(tcx, id);
367-
do_resolve(tcx, item_id, false, true).scope_for_path.unwrap().remove(&id)
368-
},
369361

370362
..*providers
371363
};
@@ -406,29 +398,25 @@ fn resolve_lifetimes_trait_definition(
406398
tcx: TyCtxt<'_>,
407399
local_def_id: LocalDefId,
408400
) -> ResolveLifetimes {
409-
convert_named_region_map(do_resolve(tcx, local_def_id, true, false))
401+
convert_named_region_map(do_resolve(tcx, local_def_id, true))
410402
}
411403

412404
/// Computes the `ResolveLifetimes` map that contains data for an entire `Item`.
413405
/// You should not read the result of this query directly, but rather use
414406
/// `named_region_map`, `is_late_bound_map`, etc.
415407
#[tracing::instrument(level = "debug", skip(tcx))]
416408
fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> ResolveLifetimes {
417-
convert_named_region_map(do_resolve(tcx, local_def_id, false, false))
409+
convert_named_region_map(do_resolve(tcx, local_def_id, false))
418410
}
419411

420412
fn do_resolve(
421413
tcx: TyCtxt<'_>,
422414
local_def_id: LocalDefId,
423415
trait_definition_only: bool,
424-
with_scope_for_path: bool,
425416
) -> NamedRegionMap {
426417
let item = tcx.hir().expect_item(local_def_id);
427-
let mut named_region_map = NamedRegionMap {
428-
defs: Default::default(),
429-
late_bound_vars: Default::default(),
430-
scope_for_path: with_scope_for_path.then(|| Default::default()),
431-
};
418+
let mut named_region_map =
419+
NamedRegionMap { defs: Default::default(), late_bound_vars: Default::default() };
432420
let mut visitor = LifetimeContext {
433421
tcx,
434422
map: &mut named_region_map,
@@ -524,38 +512,6 @@ fn late_region_as_bound_region<'tcx>(tcx: TyCtxt<'tcx>, region: &Region) -> ty::
524512
}
525513
}
526514

527-
#[tracing::instrument(level = "debug")]
528-
fn get_lifetime_scopes_for_path(mut scope: &Scope<'_>) -> LifetimeScopeForPath {
529-
let mut available_lifetimes = vec![];
530-
loop {
531-
match scope {
532-
Scope::Binder { lifetimes, s, .. } => {
533-
available_lifetimes.extend(lifetimes.keys());
534-
scope = s;
535-
}
536-
Scope::Body { s, .. } => {
537-
scope = s;
538-
}
539-
Scope::Elision { elide, s } => {
540-
if let Elide::Exact(_) = elide {
541-
return LifetimeScopeForPath::Elided;
542-
} else {
543-
scope = s;
544-
}
545-
}
546-
Scope::ObjectLifetimeDefault { s, .. } => {
547-
scope = s;
548-
}
549-
Scope::Root => {
550-
return LifetimeScopeForPath::NonElided(available_lifetimes);
551-
}
552-
Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s, .. } => {
553-
scope = s;
554-
}
555-
}
556-
}
557-
}
558-
559515
impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
560516
/// Returns the binders in scope and the type of `Binder` that should be created for a poly trait ref.
561517
fn poly_trait_ref_binder_info(&mut self) -> (Vec<ty::BoundVariableKind>, BinderScopeType) {
@@ -1202,53 +1158,15 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
12021158
}
12031159
}
12041160

1205-
fn visit_assoc_type_binding(&mut self, type_binding: &'tcx hir::TypeBinding<'_>) {
1206-
let scope = self.scope;
1207-
if let Some(scope_for_path) = self.map.scope_for_path.as_mut() {
1208-
// We add lifetime scope information for `Ident`s in associated type bindings and use
1209-
// the `HirId` of the type binding as the key in `LifetimeMap`
1210-
let lifetime_scope = get_lifetime_scopes_for_path(scope);
1211-
let map = scope_for_path.entry(type_binding.hir_id.owner).or_default();
1212-
map.insert(type_binding.hir_id.local_id, lifetime_scope);
1213-
}
1214-
hir::intravisit::walk_assoc_type_binding(self, type_binding);
1215-
}
1216-
12171161
fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, _: hir::HirId) {
12181162
for (i, segment) in path.segments.iter().enumerate() {
12191163
let depth = path.segments.len() - i - 1;
12201164
if let Some(ref args) = segment.args {
12211165
self.visit_segment_args(path.res, depth, args);
12221166
}
1223-
1224-
let scope = self.scope;
1225-
if let Some(scope_for_path) = self.map.scope_for_path.as_mut() {
1226-
// Add lifetime scope information to path segment. Note we cannot call `visit_path_segment`
1227-
// here because that call would yield to resolution problems due to `walk_path_segment`
1228-
// being called, which processes the path segments generic args, which we have already
1229-
// processed using `visit_segment_args`.
1230-
let lifetime_scope = get_lifetime_scopes_for_path(scope);
1231-
if let Some(hir_id) = segment.hir_id {
1232-
let map = scope_for_path.entry(hir_id.owner).or_default();
1233-
map.insert(hir_id.local_id, lifetime_scope);
1234-
}
1235-
}
12361167
}
12371168
}
12381169

1239-
fn visit_path_segment(&mut self, path_span: Span, path_segment: &'tcx hir::PathSegment<'tcx>) {
1240-
let scope = self.scope;
1241-
if let Some(scope_for_path) = self.map.scope_for_path.as_mut() {
1242-
let lifetime_scope = get_lifetime_scopes_for_path(scope);
1243-
if let Some(hir_id) = path_segment.hir_id {
1244-
let map = scope_for_path.entry(hir_id.owner).or_default();
1245-
map.insert(hir_id.local_id, lifetime_scope);
1246-
}
1247-
}
1248-
1249-
intravisit::walk_path_segment(self, path_span, path_segment);
1250-
}
1251-
12521170
fn visit_fn_decl(&mut self, fd: &'tcx hir::FnDecl<'tcx>) {
12531171
let output = match fd.output {
12541172
hir::FnRetTy::DefaultReturn(_) => None,
@@ -2227,6 +2145,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
22272145

22282146
// Foreign functions, `fn(...) -> R` and `Trait(...) -> R` (both types and bounds).
22292147
Node::ForeignItem(_) | Node::Ty(_) | Node::TraitRef(_) => None,
2148+
2149+
Node::TypeBinding(_) if let Node::TraitRef(_) = self.tcx.hir().get(self.tcx.hir().get_parent_node(parent)) => None,
2150+
22302151
// Everything else (only closures?) doesn't
22312152
// actually enjoy elision in return types.
22322153
_ => {
@@ -2548,16 +2469,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
25482469
}
25492470
};
25502471

2551-
// If we specifically need the `scope_for_path` map, then we're in the
2552-
// diagnostic pass and we don't want to emit more errors.
2553-
if self.map.scope_for_path.is_some() {
2554-
self.tcx.sess.delay_span_bug(
2555-
rustc_span::DUMMY_SP,
2556-
"Encountered unexpected errors during diagnostics related part",
2557-
);
2558-
return;
2559-
}
2560-
25612472
let mut spans: Vec<_> = lifetime_refs.iter().map(|lt| lt.span).collect();
25622473
spans.sort();
25632474
let mut spans_dedup = spans.clone();

compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs

+1
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
249249
| hir::Node::Stmt(..)
250250
| hir::Node::PathSegment(..)
251251
| hir::Node::Ty(..)
252+
| hir::Node::TypeBinding(..)
252253
| hir::Node::TraitRef(..)
253254
| hir::Node::Binding(..)
254255
| hir::Node::Pat(..)

0 commit comments

Comments
 (0)