Skip to content

Commit cfbd0ee

Browse files
committed
Review comments
1 parent 19ecfcd commit cfbd0ee

File tree

2 files changed

+51
-20
lines changed

2 files changed

+51
-20
lines changed

compiler/rustc_middle/src/query/mod.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -1252,12 +1252,18 @@ rustc_queries! {
12521252
desc { "looking up link arguments for a crate" }
12531253
}
12541254

1255-
/// Lifetime resolution. See `middle::resolve_lifetimes`.
1256-
query resolve_lifetimes_definition(_: LocalDefId) -> ResolveLifetimes {
1255+
/// Does lifetime resolution, but does not descend into trait items. This
1256+
/// should only be used for resolving lifetimes of on trait definitions,
1257+
/// and is used to avoid cycles. Importantly, `resolve_lifetimes` still visits
1258+
/// the same lifetimes and is responsible for diagnostics.
1259+
/// See `rustc_resolve::late::lifetimes for details.
1260+
query resolve_lifetimes_trait_definition(_: LocalDefId) -> ResolveLifetimes {
12571261
storage(ArenaCacheSelector<'tcx>)
1258-
desc { "resolving lifetimes in a definition" }
1262+
desc { "resolving lifetimes for a trait definition" }
12591263
}
1260-
/// Lifetime resolution. See `middle::resolve_lifetimes`.
1264+
/// Does lifetime resolution on items. Importantly, we can't resolve
1265+
/// lifetimes directly on things like trait methods, because of trait params.
1266+
/// See `rustc_resolve::late::lifetimes for details.
12611267
query resolve_lifetimes(_: LocalDefId) -> ResolveLifetimes {
12621268
storage(ArenaCacheSelector<'tcx>)
12631269
desc { "resolving lifetimes" }
@@ -1270,6 +1276,10 @@ rustc_queries! {
12701276
Option<(LocalDefId, &'tcx FxHashSet<ItemLocalId>)> {
12711277
desc { "testing if a region is late bound" }
12721278
}
1279+
/// For a given item (like a struct), gets the default lifetimes to be used
1280+
/// for each paramter if a trait object were to be passed for that parameter.
1281+
/// For example, for `struct Foo<'a, T, U>`, this would be `['static, 'static]`.
1282+
/// For `struct Foo<'a, T: 'a, U>`, this would instead be `['a, 'static]`.
12731283
query object_lifetime_defaults_map(_: LocalDefId)
12741284
-> Option<Vec<ObjectLifetimeDefault>> {
12751285
desc { "looking up lifetime defaults for a region on an item" }

compiler/rustc_resolve/src/late/lifetimes.rs

+37-16
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,10 @@ crate struct LifetimeContext<'a, 'tcx> {
174174

175175
is_in_const_generic: bool,
176176

177-
definition_only: bool,
177+
/// Indicates that we only care about the definition of a trait. This should
178+
/// be false if the `Item` we are resolving lifetimes for is not a trait or
179+
/// we eventually need lifetimes resolve for trait items.
180+
trait_definition_only: bool,
178181

179182
/// List of labels in the function/method currently under analysis.
180183
labels_in_fn: Vec<Ident>,
@@ -319,7 +322,7 @@ const ROOT_SCOPE: ScopeRef<'static> = &Scope::Root;
319322

320323
pub fn provide(providers: &mut ty::query::Providers) {
321324
*providers = ty::query::Providers {
322-
resolve_lifetimes_definition,
325+
resolve_lifetimes_trait_definition,
323326
resolve_lifetimes,
324327

325328
named_region_map: |tcx, id| resolve_lifetimes_for(tcx, id).defs.get(&id),
@@ -339,14 +342,16 @@ pub fn provide(providers: &mut ty::query::Providers) {
339342
/// Like `resolve_lifetimes`, but does not resolve lifetimes for trait items.
340343
/// Also does not generate any diagnostics.
341344
#[tracing::instrument(level = "debug", skip(tcx))]
342-
fn resolve_lifetimes_definition(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> ResolveLifetimes {
345+
fn resolve_lifetimes_trait_definition(
346+
tcx: TyCtxt<'_>,
347+
local_def_id: LocalDefId,
348+
) -> ResolveLifetimes {
343349
do_resolve(tcx, local_def_id, true)
344350
}
345351

346-
/// Computes the `ResolveLifetimes` map that contains data for the
347-
/// entire crate. You should not read the result of this query
348-
/// directly, but rather use `named_region_map`, `is_late_bound_map`,
349-
/// etc.
352+
/// Computes the `ResolveLifetimes` map that contains data for an entire `Item`.
353+
/// You should not read the result of this query directly, but rather use
354+
/// `named_region_map`, `is_late_bound_map`, etc.
350355
#[tracing::instrument(level = "debug", skip(tcx))]
351356
fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> ResolveLifetimes {
352357
do_resolve(tcx, local_def_id, false)
@@ -355,7 +360,7 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> ResolveLifeti
355360
fn do_resolve(
356361
tcx: TyCtxt<'_>,
357362
local_def_id: LocalDefId,
358-
definition_only: bool,
363+
trait_definition_only: bool,
359364
) -> ResolveLifetimes {
360365
let item = tcx.hir().expect_item(tcx.hir().local_def_id_to_hir_id(local_def_id));
361366
let mut named_region_map =
@@ -367,7 +372,7 @@ fn do_resolve(
367372
trait_ref_hack: false,
368373
is_in_fn_syntax: false,
369374
is_in_const_generic: false,
370-
definition_only,
375+
trait_definition_only,
371376
labels_in_fn: vec![],
372377
xcrate_object_lifetime_defaults: Default::default(),
373378
lifetime_uses: &mut Default::default(),
@@ -390,19 +395,30 @@ fn do_resolve(
390395
rl
391396
}
392397

398+
/// Given `any` owner (structs, traits, trait methods, etc.), does lifetime resolution.
399+
/// There are two important things this does.
400+
/// First, we have to resolve lifetimes for
401+
/// the entire *`Item`* that contains this owner, because that's the largest "scope"
402+
/// where we can have relevant lifetimes.
403+
/// Second, if we are asking for lifetimes in a trait *definition*, we use `resolve_lifetimes_trait_definition`
404+
/// instead of `resolve_lifetimes`, which does not descend into the trait items and does not emit diagnostics.
405+
/// This allows us to avoid cycles. Importantly, if we ask for lifetimes for lifetimes that have an owner
406+
/// other than the trait itself (like the trait methods or associated types), then we just use the regular
407+
/// `resolve_lifetimes`.
393408
fn resolve_lifetimes_for<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx ResolveLifetimes {
394409
let item_id = item_for(tcx, def_id);
395410
if item_id == def_id {
396411
let item = tcx.hir().item(hir::ItemId { def_id: item_id });
397412
match item.kind {
398-
hir::ItemKind::Trait(..) => tcx.resolve_lifetimes_definition(item_id),
413+
hir::ItemKind::Trait(..) => tcx.resolve_lifetimes_trait_definition(item_id),
399414
_ => tcx.resolve_lifetimes(item_id),
400415
}
401416
} else {
402417
tcx.resolve_lifetimes(item_id)
403418
}
404419
}
405420

421+
/// Finds the `Item` that contains the given `LocalDefId`
406422
fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId {
407423
let hir_id = tcx.hir().local_def_id_to_hir_id(local_def_id);
408424
match tcx.hir().find(hir_id) {
@@ -470,7 +486,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
470486
fn visit_nested_item(&mut self, _: hir::ItemId) {}
471487

472488
fn visit_trait_item_ref(&mut self, ii: &'tcx hir::TraitItemRef) {
473-
if !self.definition_only {
489+
if !self.trait_definition_only {
474490
intravisit::walk_trait_item_ref(self, ii)
475491
}
476492
}
@@ -513,6 +529,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
513529
// Opaque types are visited when we visit the
514530
// `TyKind::OpaqueDef`, so that they have the lifetimes from
515531
// their parent opaque_ty in scope.
532+
//
533+
// The core idea here is that since OpaqueTys are generated with the impl Trait as
534+
// their owner, we can keep going until we find the Item that owns that. We then
535+
// conservatively add all resolved lifetimes. Otherwise we run into problems in
536+
// cases like `type Foo<'a> = impl Bar<As = impl Baz + 'a>`.
516537
for (_hir_id, node) in
517538
self.tcx.hir().parent_iter(self.tcx.hir().local_def_id_to_hir_id(item.def_id))
518539
{
@@ -760,7 +781,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
760781
};
761782

762783
if !parent_is_item {
763-
if !self.definition_only {
784+
if !self.trait_definition_only {
764785
struct_span_err!(
765786
self.tcx.sess,
766787
lifetime.span,
@@ -1007,7 +1028,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
10071028
}
10081029

10091030
fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
1010-
if !self.definition_only {
1031+
if !self.trait_definition_only {
10111032
check_mixed_explicit_and_in_band_defs(self.tcx, &generics.params);
10121033
}
10131034
for param in generics.params {
@@ -1501,7 +1522,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
15011522
trait_ref_hack: self.trait_ref_hack,
15021523
is_in_fn_syntax: self.is_in_fn_syntax,
15031524
is_in_const_generic: self.is_in_const_generic,
1504-
definition_only: self.definition_only,
1525+
trait_definition_only: self.trait_definition_only,
15051526
labels_in_fn,
15061527
xcrate_object_lifetime_defaults,
15071528
lifetime_uses,
@@ -1511,7 +1532,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
15111532
{
15121533
let _enter = span.enter();
15131534
f(self.scope, &mut this);
1514-
if !self.definition_only {
1535+
if !self.trait_definition_only {
15151536
this.check_uses_for_lifetimes_defined_by_scope();
15161537
}
15171538
}
@@ -1973,7 +1994,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
19731994
}
19741995

19751996
// Check for fn-syntax conflicts with in-band lifetime definitions
1976-
if !self.definition_only && self.is_in_fn_syntax {
1997+
if !self.trait_definition_only && self.is_in_fn_syntax {
19771998
match def {
19781999
Region::EarlyBound(_, _, LifetimeDefOrigin::InBand)
19792000
| Region::LateBound(_, _, LifetimeDefOrigin::InBand) => {

0 commit comments

Comments
 (0)