]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
New upstream version 1.70.0+dfsg1
[rustc.git] / compiler / rustc_hir_analysis / src / collect / resolve_bound_vars.rs
CommitLineData
064997fb 1//! Resolution of early vs late bound lifetimes.
dfeec247 2//!
9c376795 3//! Name resolution for lifetimes is performed on the AST and embedded into HIR. From this
064997fb 4//! information, typechecking needs to transform the lifetime parameters into bound lifetimes.
9c376795
FG
5//! Lifetimes can be early-bound or late-bound. Construction of typechecking terms needs to visit
6//! the types in HIR to identify late-bound lifetimes and assign their Debruijn indices. This file
064997fb 7//! is also responsible for assigning their semantics to implicit lifetimes in trait objects.
dfeec247 8
74b04a01 9use rustc_ast::walk_list;
923072b8
FG
10use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
11use rustc_errors::struct_span_err;
dfeec247
XL
12use rustc_hir as hir;
13use rustc_hir::def::{DefKind, Res};
f2b60f7d 14use rustc_hir::def_id::LocalDefId;
5099ac24 15use rustc_hir::intravisit::{self, Visitor};
064997fb
FG
16use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeName, Node};
17use rustc_middle::bug;
5099ac24 18use rustc_middle::hir::nested_filter;
9ffffee4 19use rustc_middle::middle::resolve_bound_vars::*;
353b0b11 20use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
9ffffee4 21use rustc_session::lint;
17df50a5 22use rustc_span::def_id::DefId;
064997fb 23use rustc_span::symbol::{sym, Ident};
dfeec247 24use rustc_span::Span;
cdc7bbd5 25use std::fmt;
dfeec247 26
9ffffee4
FG
27use crate::errors;
28
dfeec247 29trait RegionExt {
9ffffee4 30 fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg);
dfeec247 31
9ffffee4 32 fn late(index: u32, param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg);
dfeec247 33
dfeec247
XL
34 fn id(&self) -> Option<DefId>;
35
9ffffee4 36 fn shifted(self, amount: u32) -> ResolvedArg;
dfeec247
XL
37}
38
9ffffee4
FG
39impl RegionExt for ResolvedArg {
40 fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) {
41 debug!("ResolvedArg::early: def_id={:?}", param.def_id);
42 (param.def_id, ResolvedArg::EarlyBound(param.def_id.to_def_id()))
dfeec247
XL
43 }
44
9ffffee4 45 fn late(idx: u32, param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) {
dfeec247 46 let depth = ty::INNERMOST;
dfeec247 47 debug!(
9ffffee4 48 "ResolvedArg::late: idx={:?}, param={:?} depth={:?} def_id={:?}",
487cf647 49 idx, param, depth, param.def_id,
dfeec247 50 );
9ffffee4 51 (param.def_id, ResolvedArg::LateBound(depth, idx, param.def_id.to_def_id()))
dfeec247
XL
52 }
53
dfeec247
XL
54 fn id(&self) -> Option<DefId> {
55 match *self {
9ffffee4 56 ResolvedArg::StaticLifetime | ResolvedArg::Error(_) => None,
dfeec247 57
9ffffee4
FG
58 ResolvedArg::EarlyBound(id)
59 | ResolvedArg::LateBound(_, _, id)
60 | ResolvedArg::Free(_, id) => Some(id),
dfeec247
XL
61 }
62 }
63
9ffffee4 64 fn shifted(self, amount: u32) -> ResolvedArg {
dfeec247 65 match self {
9ffffee4
FG
66 ResolvedArg::LateBound(debruijn, idx, id) => {
67 ResolvedArg::LateBound(debruijn.shifted_in(amount), idx, id)
dfeec247 68 }
dfeec247
XL
69 _ => self,
70 }
71 }
dfeec247
XL
72}
73
9ffffee4 74/// Maps the id of each bound variable reference to the variable decl
dfeec247
XL
75/// that it corresponds to.
76///
9ffffee4 77/// FIXME. This struct gets converted to a `ResolveBoundVars` for
9c376795 78/// actual use. It has the same data, but indexed by `LocalDefId`. This
dfeec247 79/// is silly.
cdc7bbd5 80#[derive(Debug, Default)]
9ffffee4
FG
81struct NamedVarMap {
82 // maps from every use of a named (not anonymous) bound var to a
83 // `ResolvedArg` describing how that variable is bound
84 defs: HirIdMap<ResolvedArg>,
dfeec247 85
cdc7bbd5
XL
86 // Maps relevant hir items to the bound vars on them. These include:
87 // - function defs
88 // - function pointers
89 // - closures
90 // - trait refs
91 // - bound types (like `T` in `for<'a> T<'a>: Foo`)
92 late_bound_vars: HirIdMap<Vec<ty::BoundVariableKind>>,
dfeec247
XL
93}
94
9ffffee4 95struct BoundVarContext<'a, 'tcx> {
2b03887a 96 tcx: TyCtxt<'tcx>,
9ffffee4 97 map: &'a mut NamedVarMap,
dfeec247 98 scope: ScopeRef<'a>,
dfeec247
XL
99}
100
101#[derive(Debug)]
102enum Scope<'a> {
103 /// Declares lifetimes, and each can be early-bound or late-bound.
104 /// The `DebruijnIndex` of late-bound lifetimes starts at `1` and
105 /// it should be shifted by the number of `Binder`s in between the
106 /// declaration `Binder` and the location it's referenced from.
107 Binder {
17df50a5
XL
108 /// We use an IndexMap here because we want these lifetimes in order
109 /// for diagnostics.
9ffffee4 110 bound_vars: FxIndexMap<LocalDefId, ResolvedArg>,
dfeec247 111
cdc7bbd5
XL
112 scope_type: BinderScopeType,
113
114 /// The late bound vars for a given item are stored by `HirId` to be
115 /// queried later. However, if we enter an elision scope, we have to
116 /// later append the elided bound vars to the list and need to know what
117 /// to append to.
118 hir_id: hir::HirId,
119
dfeec247 120 s: ScopeRef<'a>,
5e7ed085 121
04454e1e
FG
122 /// If this binder comes from a where clause, specify how it was created.
123 /// This is used to diagnose inaccessible lifetimes in APIT:
124 /// ```ignore (illustrative)
125 /// fn foo(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
126 /// ```
127 where_bound_origin: Option<hir::PredicateOrigin>,
dfeec247
XL
128 },
129
130 /// Lifetimes introduced by a fn are scoped to the call-site for that fn,
131 /// if this is a fn body, otherwise the original definitions are used.
132 /// Unspecified lifetimes are inferred, unless an elision scope is nested,
133 /// e.g., `(&T, fn(&T) -> &T);` becomes `(&'_ T, for<'a> fn(&'a T) -> &'a T)`.
134 Body {
135 id: hir::BodyId,
136 s: ScopeRef<'a>,
137 },
138
139 /// A scope which either determines unspecified lifetimes or errors
064997fb 140 /// on them (e.g., due to ambiguity).
dfeec247 141 Elision {
dfeec247
XL
142 s: ScopeRef<'a>,
143 },
144
145 /// Use a specific lifetime (if `Some`) or leave it unset (to be
146 /// inferred in a function body or potentially error outside one),
147 /// for the default choice of lifetime in a trait object type.
148 ObjectLifetimeDefault {
9ffffee4 149 lifetime: Option<ResolvedArg>,
dfeec247
XL
150 s: ScopeRef<'a>,
151 },
152
5e7ed085 153 /// When we have nested trait refs, we concatenate late bound vars for inner
cdc7bbd5
XL
154 /// trait refs from outer ones. But we also need to include any HRTB
155 /// lifetimes encountered when identifying the trait that an associated type
156 /// is declared on.
157 Supertrait {
9ffffee4 158 bound_vars: Vec<ty::BoundVariableKind>,
cdc7bbd5
XL
159 s: ScopeRef<'a>,
160 },
161
162 TraitRefBoundary {
163 s: ScopeRef<'a>,
164 },
165
9ffffee4
FG
166 /// Disallows capturing non-lifetime binders from parent scopes.
167 ///
168 /// This is necessary for something like `for<T> [(); { /* references T */ }]:`,
169 /// since we don't do something more correct like replacing any captured
170 /// late-bound vars with early-bound params in the const's own generics.
171 AnonConstBoundary {
172 s: ScopeRef<'a>,
173 },
174
487cf647
FG
175 Root {
176 opt_parent_item: Option<LocalDefId>,
177 },
dfeec247
XL
178}
179
cdc7bbd5
XL
180#[derive(Copy, Clone, Debug)]
181enum BinderScopeType {
182 /// Any non-concatenating binder scopes.
183 Normal,
184 /// Within a syntactic trait ref, there may be multiple poly trait refs that
5e7ed085
FG
185 /// are nested (under the `associated_type_bounds` feature). The binders of
186 /// the inner poly trait refs are extended from the outer poly trait refs
cdc7bbd5
XL
187 /// and don't increase the late bound depth. If you had
188 /// `T: for<'a> Foo<Bar: for<'b> Baz<'a, 'b>>`, then the `for<'b>` scope
189 /// would be `Concatenating`. This also used in trait refs in where clauses
190 /// where we have two binders `for<> T: for<> Foo` (I've intentionally left
191 /// out any lifetimes because they aren't needed to show the two scopes).
192 /// The inner `for<>` has a scope of `Concatenating`.
193 Concatenating,
194}
195
196// A helper struct for debugging scopes without printing parent scopes
197struct TruncatedScopeDebug<'a>(&'a Scope<'a>);
198
199impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
200 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
201 match self.0 {
9ffffee4 202 Scope::Binder { bound_vars, scope_type, hir_id, where_bound_origin, s: _ } => f
cdc7bbd5 203 .debug_struct("Binder")
9ffffee4 204 .field("bound_vars", bound_vars)
cdc7bbd5
XL
205 .field("scope_type", scope_type)
206 .field("hir_id", hir_id)
04454e1e
FG
207 .field("where_bound_origin", where_bound_origin)
208 .field("s", &"..")
cdc7bbd5
XL
209 .finish(),
210 Scope::Body { id, s: _ } => {
211 f.debug_struct("Body").field("id", id).field("s", &"..").finish()
212 }
064997fb 213 Scope::Elision { s: _ } => f.debug_struct("Elision").field("s", &"..").finish(),
cdc7bbd5
XL
214 Scope::ObjectLifetimeDefault { lifetime, s: _ } => f
215 .debug_struct("ObjectLifetimeDefault")
216 .field("lifetime", lifetime)
217 .field("s", &"..")
218 .finish(),
9ffffee4 219 Scope::Supertrait { bound_vars, s: _ } => f
cdc7bbd5 220 .debug_struct("Supertrait")
9ffffee4 221 .field("bound_vars", bound_vars)
cdc7bbd5
XL
222 .field("s", &"..")
223 .finish(),
224 Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
9ffffee4 225 Scope::AnonConstBoundary { s: _ } => f.debug_struct("AnonConstBoundary").finish(),
487cf647
FG
226 Scope::Root { opt_parent_item } => {
227 f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish()
228 }
cdc7bbd5
XL
229 }
230 }
231}
232
dfeec247
XL
233type ScopeRef<'a> = &'a Scope<'a>;
234
2b03887a 235pub(crate) fn provide(providers: &mut ty::query::Providers) {
dfeec247 236 *providers = ty::query::Providers {
9ffffee4 237 resolve_bound_vars,
dfeec247 238
9ffffee4 239 named_variable_map: |tcx, id| tcx.resolve_bound_vars(id).defs.get(&id),
5869c6ff 240 is_late_bound_map,
f2b60f7d 241 object_lifetime_default,
9ffffee4 242 late_bound_vars_map: |tcx, id| tcx.resolve_bound_vars(id).late_bound_vars.get(&id),
dfeec247
XL
243
244 ..*providers
245 };
dfeec247
XL
246}
247
9ffffee4 248/// Computes the `ResolveBoundVars` map that contains data for an entire `Item`.
cdc7bbd5 249/// You should not read the result of this query directly, but rather use
9ffffee4 250/// `named_variable_map`, `is_late_bound_map`, etc.
f2b60f7d 251#[instrument(level = "debug", skip(tcx))]
9ffffee4
FG
252fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars {
253 let mut named_variable_map =
254 NamedVarMap { defs: Default::default(), late_bound_vars: Default::default() };
255 let mut visitor = BoundVarContext {
cdc7bbd5 256 tcx,
9ffffee4 257 map: &mut named_variable_map,
487cf647 258 scope: &Scope::Root { opt_parent_item: None },
cdc7bbd5 259 };
487cf647
FG
260 match tcx.hir().owner(local_def_id) {
261 hir::OwnerNode::Item(item) => visitor.visit_item(item),
262 hir::OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item),
263 hir::OwnerNode::TraitItem(item) => {
264 let scope =
265 Scope::Root { opt_parent_item: Some(tcx.local_parent(item.owner_id.def_id)) };
266 visitor.scope = &scope;
267 visitor.visit_trait_item(item)
268 }
269 hir::OwnerNode::ImplItem(item) => {
270 let scope =
271 Scope::Root { opt_parent_item: Some(tcx.local_parent(item.owner_id.def_id)) };
272 visitor.scope = &scope;
273 visitor.visit_impl_item(item)
274 }
275 hir::OwnerNode::Crate(_) => {}
276 }
17df50a5 277
9ffffee4 278 let mut rl = ResolveBoundVars::default();
dfeec247 279
9ffffee4 280 for (hir_id, v) in named_variable_map.defs {
ba9703b0 281 let map = rl.defs.entry(hir_id.owner).or_default();
dfeec247
XL
282 map.insert(hir_id.local_id, v);
283 }
9ffffee4 284 for (hir_id, v) in named_variable_map.late_bound_vars {
cdc7bbd5 285 let map = rl.late_bound_vars.entry(hir_id.owner).or_default();
dfeec247
XL
286 map.insert(hir_id.local_id, v);
287 }
288
cdc7bbd5 289 debug!(?rl.defs);
2b03887a 290 debug!(?rl.late_bound_vars);
f9f354fc 291 rl
dfeec247
XL
292}
293
9ffffee4
FG
294fn late_arg_as_bound_arg<'tcx>(
295 tcx: TyCtxt<'tcx>,
296 arg: &ResolvedArg,
297 param: &GenericParam<'tcx>,
298) -> ty::BoundVariableKind {
299 match arg {
300 ResolvedArg::LateBound(_, _, def_id) => {
cdc7bbd5 301 let name = tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local()));
9ffffee4
FG
302 match param.kind {
303 GenericParamKind::Lifetime { .. } => {
304 ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name))
305 }
306 GenericParamKind::Type { .. } => {
307 ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(*def_id, name))
308 }
309 GenericParamKind::Const { .. } => ty::BoundVariableKind::Const,
310 }
cdc7bbd5 311 }
9ffffee4 312 _ => bug!("{:?} is not a late argument", arg),
cdc7bbd5
XL
313 }
314}
315
9ffffee4 316impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
cdc7bbd5
XL
317 /// Returns the binders in scope and the type of `Binder` that should be created for a poly trait ref.
318 fn poly_trait_ref_binder_info(&mut self) -> (Vec<ty::BoundVariableKind>, BinderScopeType) {
319 let mut scope = self.scope;
9ffffee4 320 let mut supertrait_bound_vars = vec![];
cdc7bbd5
XL
321 loop {
322 match scope {
487cf647 323 Scope::Body { .. } | Scope::Root { .. } => {
cdc7bbd5
XL
324 break (vec![], BinderScopeType::Normal);
325 }
326
9ffffee4
FG
327 Scope::Elision { s, .. }
328 | Scope::ObjectLifetimeDefault { s, .. }
329 | Scope::AnonConstBoundary { s } => {
cdc7bbd5
XL
330 scope = s;
331 }
332
9ffffee4
FG
333 Scope::Supertrait { s, bound_vars } => {
334 supertrait_bound_vars = bound_vars.clone();
cdc7bbd5
XL
335 scope = s;
336 }
337
338 Scope::TraitRefBoundary { .. } => {
339 // We should only see super trait lifetimes if there is a `Binder` above
9ffffee4 340 assert!(supertrait_bound_vars.is_empty());
cdc7bbd5
XL
341 break (vec![], BinderScopeType::Normal);
342 }
343
344 Scope::Binder { hir_id, .. } => {
345 // Nested poly trait refs have the binders concatenated
346 let mut full_binders =
347 self.map.late_bound_vars.entry(*hir_id).or_default().clone();
9ffffee4 348 full_binders.extend(supertrait_bound_vars.into_iter());
cdc7bbd5
XL
349 break (full_binders, BinderScopeType::Concatenating);
350 }
351 }
352 }
353 }
9ffffee4
FG
354
355 fn visit_poly_trait_ref_inner(
356 &mut self,
357 trait_ref: &'tcx hir::PolyTraitRef<'tcx>,
358 non_lifetime_binder_allowed: NonLifetimeBinderAllowed,
359 ) {
360 debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref);
361
362 let (mut binders, scope_type) = self.poly_trait_ref_binder_info();
363
364 let initial_bound_vars = binders.len() as u32;
365 let mut bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = FxIndexMap::default();
366 let binders_iter =
367 trait_ref.bound_generic_params.iter().enumerate().map(|(late_bound_idx, param)| {
368 let pair = ResolvedArg::late(initial_bound_vars + late_bound_idx as u32, param);
369 let r = late_arg_as_bound_arg(self.tcx, &pair.1, param);
370 bound_vars.insert(pair.0, pair.1);
371 r
372 });
373 binders.extend(binders_iter);
374
375 if let NonLifetimeBinderAllowed::Deny(where_) = non_lifetime_binder_allowed {
376 deny_non_region_late_bound(self.tcx, &mut bound_vars, where_);
377 }
378
379 debug!(?binders);
380 self.record_late_bound_vars(trait_ref.trait_ref.hir_ref_id, binders);
381
382 // Always introduce a scope here, even if this is in a where clause and
383 // we introduced the binders around the bounded Ty. In that case, we
384 // just reuse the concatenation functionality also present in nested trait
385 // refs.
386 let scope = Scope::Binder {
387 hir_id: trait_ref.trait_ref.hir_ref_id,
388 bound_vars,
389 s: self.scope,
390 scope_type,
391 where_bound_origin: None,
392 };
393 self.with(scope, |this| {
394 walk_list!(this, visit_generic_param, trait_ref.bound_generic_params);
395 this.visit_trait_ref(&trait_ref.trait_ref);
396 });
397 }
398}
399
400enum NonLifetimeBinderAllowed {
401 Deny(&'static str),
402 Allow,
cdc7bbd5 403}
9ffffee4
FG
404
405impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
487cf647 406 type NestedFilter = nested_filter::OnlyBodies;
dfeec247 407
5099ac24
FG
408 fn nested_visit_map(&mut self) -> Self::Map {
409 self.tcx.hir()
dfeec247
XL
410 }
411
dfeec247 412 fn visit_nested_body(&mut self, body: hir::BodyId) {
dfeec247 413 let body = self.tcx.hir().body(body);
923072b8 414 self.with(Scope::Body { id: body.id(), s: self.scope }, |this| {
dfeec247
XL
415 this.visit_body(body);
416 });
dfeec247
XL
417 }
418
923072b8 419 fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
064997fb
FG
420 if let hir::ExprKind::Closure(hir::Closure {
421 binder, bound_generic_params, fn_decl, ..
422 }) = e.kind
423 {
424 if let &hir::ClosureBinder::For { span: for_sp, .. } = binder {
425 fn span_of_infer(ty: &hir::Ty<'_>) -> Option<Span> {
426 struct V(Option<Span>);
427
428 impl<'v> Visitor<'v> for V {
429 fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
430 match t.kind {
431 _ if self.0.is_some() => (),
432 hir::TyKind::Infer => {
433 self.0 = Some(t.span);
434 }
435 _ => intravisit::walk_ty(self, t),
436 }
437 }
438 }
439
440 let mut v = V(None);
441 v.visit_ty(ty);
442 v.0
443 }
444
445 let infer_in_rt_sp = match fn_decl.output {
446 hir::FnRetTy::DefaultReturn(sp) => Some(sp),
447 hir::FnRetTy::Return(ty) => span_of_infer(ty),
448 };
449
450 let infer_spans = fn_decl
451 .inputs
452 .into_iter()
453 .filter_map(span_of_infer)
454 .chain(infer_in_rt_sp)
455 .collect::<Vec<_>>();
456
457 if !infer_spans.is_empty() {
458 self.tcx.sess
459 .struct_span_err(
460 infer_spans,
461 "implicit types in closure signatures are forbidden when `for<...>` is present",
462 )
463 .span_label(for_sp, "`for<...>` is here")
464 .emit();
465 }
466 }
467
9ffffee4 468 let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
923072b8
FG
469 bound_generic_params
470 .iter()
923072b8
FG
471 .enumerate()
472 .map(|(late_bound_idx, param)| {
9ffffee4
FG
473 let pair = ResolvedArg::late(late_bound_idx as u32, param);
474 let r = late_arg_as_bound_arg(self.tcx, &pair.1, param);
923072b8
FG
475 (pair, r)
476 })
477 .unzip();
064997fb 478
9ffffee4
FG
479 deny_non_region_late_bound(self.tcx, &mut bound_vars, "closures");
480
2b03887a 481 self.record_late_bound_vars(e.hir_id, binders);
923072b8
FG
482 let scope = Scope::Binder {
483 hir_id: e.hir_id,
9ffffee4 484 bound_vars,
923072b8 485 s: self.scope,
923072b8 486 scope_type: BinderScopeType::Normal,
923072b8
FG
487 where_bound_origin: None,
488 };
064997fb 489
923072b8
FG
490 self.with(scope, |this| {
491 // a closure has no bounds, so everything
492 // contained within is scoped within its binder.
493 intravisit::walk_expr(this, e)
494 });
495 } else {
496 intravisit::walk_expr(self, e)
cdc7bbd5
XL
497 }
498 }
499
f2b60f7d 500 #[instrument(level = "debug", skip(self))]
dfeec247 501 fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
cdc7bbd5
XL
502 match &item.kind {
503 hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => {
504 if let Some(of_trait) = of_trait {
2b03887a 505 self.record_late_bound_vars(of_trait.hir_ref_id, Vec::default());
cdc7bbd5
XL
506 }
507 }
508 _ => {}
509 }
dfeec247 510 match item.kind {
9c376795 511 hir::ItemKind::Fn(_, generics, _) => {
f2b60f7d 512 self.visit_early_late(item.hir_id(), generics, |this| {
dfeec247
XL
513 intravisit::walk_item(this, item);
514 });
dfeec247
XL
515 }
516
517 hir::ItemKind::ExternCrate(_)
518 | hir::ItemKind::Use(..)
94222f64 519 | hir::ItemKind::Macro(..)
dfeec247 520 | hir::ItemKind::Mod(..)
fc512014 521 | hir::ItemKind::ForeignMod { .. }
dfeec247
XL
522 | hir::ItemKind::GlobalAsm(..) => {
523 // These sorts of items have no lifetime parameters at all.
524 intravisit::walk_item(self, item);
525 }
526 hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => {
527 // No lifetime parameters, but implied 'static.
064997fb
FG
528 self.with(Scope::Elision { s: self.scope }, |this| {
529 intravisit::walk_item(this, item)
530 });
dfeec247 531 }
487cf647
FG
532 hir::ItemKind::OpaqueTy(hir::OpaqueTy {
533 origin: hir::OpaqueTyOrigin::TyAlias, ..
534 }) => {
f035d41b
XL
535 // Opaque types are visited when we visit the
536 // `TyKind::OpaqueDef`, so that they have the lifetimes from
537 // their parent opaque_ty in scope.
cdc7bbd5
XL
538 //
539 // The core idea here is that since OpaqueTys are generated with the impl Trait as
540 // their owner, we can keep going until we find the Item that owns that. We then
541 // conservatively add all resolved lifetimes. Otherwise we run into problems in
542 // cases like `type Foo<'a> = impl Bar<As = impl Baz + 'a>`.
487cf647 543 let parent_item = self.tcx.hir().get_parent_item(item.hir_id());
9ffffee4
FG
544 let resolved_lifetimes: &ResolveBoundVars =
545 self.tcx.resolve_bound_vars(parent_item);
487cf647
FG
546 // We need to add *all* deps, since opaque tys may want them from *us*
547 for (&owner, defs) in resolved_lifetimes.defs.iter() {
548 defs.iter().for_each(|(&local_id, region)| {
549 self.map.defs.insert(hir::HirId { owner, local_id }, *region);
550 });
551 }
552 for (&owner, late_bound_vars) in resolved_lifetimes.late_bound_vars.iter() {
553 late_bound_vars.iter().for_each(|(&local_id, late_bound_vars)| {
554 self.record_late_bound_vars(
555 hir::HirId { owner, local_id },
556 late_bound_vars.clone(),
557 );
558 });
559 }
560 }
561 hir::ItemKind::OpaqueTy(hir::OpaqueTy {
9ffffee4 562 origin: hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent),
487cf647
FG
563 generics,
564 ..
565 }) => {
566 // We want to start our early-bound indices at the end of the parent scope,
567 // not including any parent `impl Trait`s.
9ffffee4 568 let mut bound_vars = FxIndexMap::default();
487cf647
FG
569 debug!(?generics.params);
570 for param in generics.params {
9ffffee4
FG
571 let (def_id, reg) = ResolvedArg::early(&param);
572 bound_vars.insert(def_id, reg);
cdc7bbd5 573 }
487cf647 574
9ffffee4 575 let scope = Scope::Root { opt_parent_item: Some(parent) };
487cf647 576 self.with(scope, |this| {
9ffffee4
FG
577 let scope = Scope::Binder {
578 hir_id: item.hir_id(),
579 bound_vars,
580 s: this.scope,
581 scope_type: BinderScopeType::Normal,
582 where_bound_origin: None,
583 };
584 this.with(scope, |this| {
585 let scope = Scope::TraitRefBoundary { s: this.scope };
586 this.with(scope, |this| intravisit::walk_item(this, item))
587 });
588 })
dfeec247 589 }
9c376795
FG
590 hir::ItemKind::TyAlias(_, generics)
591 | hir::ItemKind::Enum(_, generics)
592 | hir::ItemKind::Struct(_, generics)
593 | hir::ItemKind::Union(_, generics)
594 | hir::ItemKind::Trait(_, _, generics, ..)
595 | hir::ItemKind::TraitAlias(generics, ..)
596 | hir::ItemKind::Impl(&hir::Impl { generics, .. }) => {
dfeec247 597 // These kinds of items have only early-bound lifetime parameters.
9ffffee4 598 let bound_vars = generics.params.iter().map(ResolvedArg::early).collect();
2b03887a 599 self.record_late_bound_vars(item.hir_id(), vec![]);
dfeec247 600 let scope = Scope::Binder {
cdc7bbd5 601 hir_id: item.hir_id(),
9ffffee4 602 bound_vars,
cdc7bbd5 603 scope_type: BinderScopeType::Normal,
487cf647 604 s: self.scope,
04454e1e 605 where_bound_origin: None,
dfeec247 606 };
923072b8 607 self.with(scope, |this| {
cdc7bbd5 608 let scope = Scope::TraitRefBoundary { s: this.scope };
923072b8 609 this.with(scope, |this| {
cdc7bbd5
XL
610 intravisit::walk_item(this, item);
611 });
dfeec247 612 });
dfeec247
XL
613 }
614 }
615 }
616
617 fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
618 match item.kind {
9c376795 619 hir::ForeignItemKind::Fn(_, _, generics) => {
f2b60f7d 620 self.visit_early_late(item.hir_id(), generics, |this| {
dfeec247
XL
621 intravisit::walk_foreign_item(this, item);
622 })
623 }
624 hir::ForeignItemKind::Static(..) => {
625 intravisit::walk_foreign_item(self, item);
626 }
627 hir::ForeignItemKind::Type => {
628 intravisit::walk_foreign_item(self, item);
629 }
630 }
631 }
632
f2b60f7d 633 #[instrument(level = "debug", skip(self))]
dfeec247 634 fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
dfeec247 635 match ty.kind {
9c376795 636 hir::TyKind::BareFn(c) => {
9ffffee4 637 let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) = c
cdc7bbd5
XL
638 .generic_params
639 .iter()
cdc7bbd5
XL
640 .enumerate()
641 .map(|(late_bound_idx, param)| {
9ffffee4
FG
642 let pair = ResolvedArg::late(late_bound_idx as u32, param);
643 let r = late_arg_as_bound_arg(self.tcx, &pair.1, param);
cdc7bbd5
XL
644 (pair, r)
645 })
646 .unzip();
9ffffee4
FG
647
648 deny_non_region_late_bound(self.tcx, &mut bound_vars, "function pointer types");
649
2b03887a 650 self.record_late_bound_vars(ty.hir_id, binders);
dfeec247 651 let scope = Scope::Binder {
cdc7bbd5 652 hir_id: ty.hir_id,
9ffffee4 653 bound_vars,
dfeec247 654 s: self.scope,
cdc7bbd5 655 scope_type: BinderScopeType::Normal,
04454e1e 656 where_bound_origin: None,
dfeec247 657 };
923072b8 658 self.with(scope, |this| {
dfeec247
XL
659 // a bare fn has no bounds, so everything
660 // contained within is scoped within its binder.
dfeec247
XL
661 intravisit::walk_ty(this, ty);
662 });
dfeec247 663 }
9c376795 664 hir::TyKind::TraitObject(bounds, lifetime, _) => {
cdc7bbd5
XL
665 debug!(?bounds, ?lifetime, "TraitObject");
666 let scope = Scope::TraitRefBoundary { s: self.scope };
923072b8 667 self.with(scope, |this| {
cdc7bbd5 668 for bound in bounds {
9ffffee4
FG
669 this.visit_poly_trait_ref_inner(
670 bound,
671 NonLifetimeBinderAllowed::Deny("trait object types"),
672 );
cdc7bbd5
XL
673 }
674 });
487cf647 675 match lifetime.res {
dfeec247
XL
676 LifetimeName::ImplicitObjectLifetimeDefault => {
677 // If the user does not write *anything*, we
678 // use the object lifetime defaulting
679 // rules. So e.g., `Box<dyn Debug>` becomes
680 // `Box<dyn Debug + 'static>`.
681 self.resolve_object_lifetime_default(lifetime)
682 }
064997fb 683 LifetimeName::Infer => {
dfeec247
XL
684 // If the user writes `'_`, we use the *ordinary* elision
685 // rules. So the `'_` in e.g., `Box<dyn Debug + '_>` will be
686 // resolved the same as the `'_` in `&'_ Foo`.
687 //
688 // cc #48468
dfeec247 689 }
923072b8 690 LifetimeName::Param(..) | LifetimeName::Static => {
dfeec247
XL
691 // If the user wrote an explicit name, use that.
692 self.visit_lifetime(lifetime);
693 }
694 LifetimeName::Error => {}
695 }
696 }
9c376795 697 hir::TyKind::Ref(lifetime_ref, ref mt) => {
dfeec247
XL
698 self.visit_lifetime(lifetime_ref);
699 let scope = Scope::ObjectLifetimeDefault {
700 lifetime: self.map.defs.get(&lifetime_ref.hir_id).cloned(),
701 s: self.scope,
702 };
923072b8 703 self.with(scope, |this| this.visit_ty(&mt.ty));
dfeec247 704 }
f2b60f7d 705 hir::TyKind::OpaqueDef(item_id, lifetimes, _in_trait) => {
dfeec247
XL
706 // Resolve the lifetimes in the bounds to the lifetime defs in the generics.
707 // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
708 // `type MyAnonTy<'b> = impl MyTrait<'b>;`
709 // ^ ^ this gets resolved in the scope of
710 // the opaque_ty generics
6a06907d 711 let opaque_ty = self.tcx.hir().item(item_id);
9c376795 712 match &opaque_ty.kind {
a2a8927a
XL
713 hir::ItemKind::OpaqueTy(hir::OpaqueTy {
714 origin: hir::OpaqueTyOrigin::TyAlias,
715 ..
716 }) => {
dfeec247 717 intravisit::walk_ty(self, ty);
f035d41b
XL
718
719 // Elided lifetimes are not allowed in non-return
720 // position impl Trait
cdc7bbd5 721 let scope = Scope::TraitRefBoundary { s: self.scope };
923072b8 722 self.with(scope, |this| {
064997fb 723 let scope = Scope::Elision { s: this.scope };
923072b8 724 this.with(scope, |this| {
cdc7bbd5
XL
725 intravisit::walk_item(this, opaque_ty);
726 })
f035d41b
XL
727 });
728
dfeec247
XL
729 return;
730 }
f035d41b 731 hir::ItemKind::OpaqueTy(hir::OpaqueTy {
a2a8927a 732 origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..),
f035d41b 733 ..
487cf647 734 }) => {}
9c376795 735 i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
dfeec247
XL
736 };
737
738 // Resolve the lifetimes that are applied to the opaque type.
739 // These are resolved in the current scope.
740 // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
741 // `fn foo<'a>() -> MyAnonTy<'a> { ... }`
742 // ^ ^this gets resolved in the current scope
743 for lifetime in lifetimes {
5099ac24
FG
744 let hir::GenericArg::Lifetime(lifetime) = lifetime else {
745 continue
746 };
747 self.visit_lifetime(lifetime);
748
749 // Check for predicates like `impl for<'a> Trait<impl OtherTrait<'a>>`
750 // and ban them. Type variables instantiated inside binders aren't
751 // well-supported at the moment, so this doesn't work.
752 // In the future, this should be fixed and this error should be removed.
753 let def = self.map.defs.get(&lifetime.hir_id).cloned();
9ffffee4 754 let Some(ResolvedArg::LateBound(_, _, def_id)) = def else {
5099ac24
FG
755 continue
756 };
757 let Some(def_id) = def_id.as_local() else {
758 continue
759 };
760 let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
761 // Ensure that the parent of the def is an item, not HRTB
9c376795 762 let parent_id = self.tcx.hir().parent_id(hir_id);
5099ac24 763 if !parent_id.is_owner() {
487cf647
FG
764 struct_span_err!(
765 self.tcx.sess,
766 lifetime.ident.span,
767 E0657,
768 "`impl Trait` can only capture lifetimes bound at the fn or impl level"
769 )
770 .emit();
5099ac24 771 self.uninsert_lifetime_on_error(lifetime, def.unwrap());
dfeec247 772 }
5e7ed085
FG
773 if let hir::Node::Item(hir::Item {
774 kind: hir::ItemKind::OpaqueTy { .. }, ..
775 }) = self.tcx.hir().get(parent_id)
776 {
487cf647
FG
777 let mut err = self.tcx.sess.struct_span_err(
778 lifetime.ident.span,
779 "higher kinded lifetime bounds on nested opaque types are not supported yet",
780 );
781 err.span_note(self.tcx.def_span(def_id), "lifetime declared here");
782 err.emit();
5e7ed085
FG
783 self.uninsert_lifetime_on_error(lifetime, def.unwrap());
784 }
dfeec247 785 }
dfeec247
XL
786 }
787 _ => intravisit::walk_ty(self, ty),
788 }
789 }
790
f2b60f7d 791 #[instrument(level = "debug", skip(self))]
dfeec247
XL
792 fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
793 use self::hir::TraitItemKind::*;
dfeec247 794 match trait_item.kind {
923072b8 795 Fn(_, _) => {
f2b60f7d
FG
796 self.visit_early_late(trait_item.hir_id(), &trait_item.generics, |this| {
797 intravisit::walk_trait_item(this, trait_item)
798 });
dfeec247 799 }
9c376795 800 Type(bounds, ty) => {
dfeec247 801 let generics = &trait_item.generics;
9ffffee4 802 let bound_vars = generics.params.iter().map(ResolvedArg::early).collect();
2b03887a 803 self.record_late_bound_vars(trait_item.hir_id(), vec![]);
dfeec247 804 let scope = Scope::Binder {
cdc7bbd5 805 hir_id: trait_item.hir_id(),
9ffffee4 806 bound_vars,
dfeec247 807 s: self.scope,
cdc7bbd5 808 scope_type: BinderScopeType::Normal,
04454e1e 809 where_bound_origin: None,
dfeec247 810 };
923072b8 811 self.with(scope, |this| {
cdc7bbd5 812 let scope = Scope::TraitRefBoundary { s: this.scope };
923072b8 813 this.with(scope, |this| {
cdc7bbd5
XL
814 this.visit_generics(generics);
815 for bound in bounds {
816 this.visit_param_bound(bound);
817 }
818 if let Some(ty) = ty {
819 this.visit_ty(ty);
820 }
821 })
dfeec247
XL
822 });
823 }
824 Const(_, _) => {
825 // Only methods and types support generics.
826 assert!(trait_item.generics.params.is_empty());
827 intravisit::walk_trait_item(self, trait_item);
828 }
829 }
dfeec247
XL
830 }
831
f2b60f7d 832 #[instrument(level = "debug", skip(self))]
dfeec247
XL
833 fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
834 use self::hir::ImplItemKind::*;
dfeec247 835 match impl_item.kind {
f2b60f7d
FG
836 Fn(..) => self.visit_early_late(impl_item.hir_id(), &impl_item.generics, |this| {
837 intravisit::walk_impl_item(this, impl_item)
838 }),
9c376795 839 Type(ty) => {
dfeec247 840 let generics = &impl_item.generics;
9ffffee4
FG
841 let bound_vars: FxIndexMap<LocalDefId, ResolvedArg> =
842 generics.params.iter().map(ResolvedArg::early).collect();
2b03887a 843 self.record_late_bound_vars(impl_item.hir_id(), vec![]);
dfeec247 844 let scope = Scope::Binder {
2b03887a 845 hir_id: impl_item.hir_id(),
9ffffee4 846 bound_vars,
dfeec247 847 s: self.scope,
cdc7bbd5 848 scope_type: BinderScopeType::Normal,
04454e1e 849 where_bound_origin: None,
dfeec247 850 };
923072b8 851 self.with(scope, |this| {
cdc7bbd5 852 let scope = Scope::TraitRefBoundary { s: this.scope };
923072b8 853 this.with(scope, |this| {
cdc7bbd5
XL
854 this.visit_generics(generics);
855 this.visit_ty(ty);
856 })
dfeec247
XL
857 });
858 }
dfeec247
XL
859 Const(_, _) => {
860 // Only methods and types support generics.
861 assert!(impl_item.generics.params.is_empty());
862 intravisit::walk_impl_item(self, impl_item);
863 }
864 }
dfeec247
XL
865 }
866
f2b60f7d 867 #[instrument(level = "debug", skip(self))]
dfeec247 868 fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
487cf647 869 match lifetime_ref.res {
9ffffee4
FG
870 hir::LifetimeName::Static => {
871 self.insert_lifetime(lifetime_ref, ResolvedArg::StaticLifetime)
872 }
487cf647 873 hir::LifetimeName::Param(param_def_id) => {
923072b8
FG
874 self.resolve_lifetime_ref(param_def_id, lifetime_ref)
875 }
876 // If we've already reported an error, just ignore `lifetime_ref`.
877 hir::LifetimeName::Error => {}
064997fb
FG
878 // Those will be resolved by typechecking.
879 hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Infer => {}
17df50a5 880 }
17df50a5
XL
881 }
882
9ffffee4 883 fn visit_path(&mut self, path: &hir::Path<'tcx>, hir_id: hir::HirId) {
dfeec247
XL
884 for (i, segment) in path.segments.iter().enumerate() {
885 let depth = path.segments.len() - i - 1;
9c376795 886 if let Some(args) = segment.args {
dfeec247
XL
887 self.visit_segment_args(path.res, depth, args);
888 }
17df50a5 889 }
9ffffee4
FG
890 if let Res::Def(DefKind::TyParam | DefKind::ConstParam, param_def_id) = path.res {
891 self.resolve_type_ref(param_def_id.expect_local(), hir_id);
892 }
17df50a5
XL
893 }
894
064997fb
FG
895 fn visit_fn(
896 &mut self,
897 fk: intravisit::FnKind<'tcx>,
898 fd: &'tcx hir::FnDecl<'tcx>,
899 body_id: hir::BodyId,
900 _: Span,
9ffffee4 901 _: LocalDefId,
064997fb 902 ) {
dfeec247 903 let output = match fd.output {
74b04a01 904 hir::FnRetTy::DefaultReturn(_) => None,
9c376795 905 hir::FnRetTy::Return(ty) => Some(ty),
dfeec247 906 };
064997fb
FG
907 self.visit_fn_like_elision(&fd.inputs, output, matches!(fk, intravisit::FnKind::Closure));
908 intravisit::walk_fn_kind(self, fk);
909 self.visit_nested_body(body_id)
dfeec247
XL
910 }
911
912 fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
cdc7bbd5 913 let scope = Scope::TraitRefBoundary { s: self.scope };
923072b8 914 self.with(scope, |this| {
cdc7bbd5
XL
915 for param in generics.params {
916 match param.kind {
917 GenericParamKind::Lifetime { .. } => {}
9c376795
FG
918 GenericParamKind::Type { default, .. } => {
919 if let Some(ty) = default {
920 this.visit_ty(ty);
cdc7bbd5
XL
921 }
922 }
9c376795
FG
923 GenericParamKind::Const { ty, default } => {
924 this.visit_ty(ty);
a2a8927a
XL
925 if let Some(default) = default {
926 this.visit_body(this.tcx.hir().body(default.body));
927 }
dfeec247
XL
928 }
929 }
cdc7bbd5 930 }
04454e1e 931 for predicate in generics.predicates {
cdc7bbd5
XL
932 match predicate {
933 &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
2b03887a 934 hir_id,
9c376795 935 bounded_ty,
cdc7bbd5 936 bounds,
9c376795 937 bound_generic_params,
04454e1e 938 origin,
cdc7bbd5
XL
939 ..
940 }) => {
9ffffee4 941 let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
cdc7bbd5
XL
942 bound_generic_params
943 .iter()
cdc7bbd5
XL
944 .enumerate()
945 .map(|(late_bound_idx, param)| {
9ffffee4
FG
946 let pair = ResolvedArg::late(late_bound_idx as u32, param);
947 let r = late_arg_as_bound_arg(this.tcx, &pair.1, param);
948 (pair, r)
cdc7bbd5 949 })
9ffffee4 950 .unzip();
2b03887a 951 this.record_late_bound_vars(hir_id, binders.clone());
cdc7bbd5
XL
952 // Even if there are no lifetimes defined here, we still wrap it in a binder
953 // scope. If there happens to be a nested poly trait ref (an error), that
954 // will be `Concatenating` anyways, so we don't have to worry about the depth
955 // being wrong.
dfeec247 956 let scope = Scope::Binder {
2b03887a 957 hir_id,
9ffffee4 958 bound_vars,
cdc7bbd5 959 s: this.scope,
cdc7bbd5 960 scope_type: BinderScopeType::Normal,
04454e1e 961 where_bound_origin: Some(origin),
dfeec247 962 };
923072b8 963 this.with(scope, |this| {
dfeec247
XL
964 this.visit_ty(&bounded_ty);
965 walk_list!(this, visit_param_bound, bounds);
cdc7bbd5
XL
966 })
967 }
968 &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
9c376795 969 lifetime,
cdc7bbd5
XL
970 bounds,
971 ..
972 }) => {
973 this.visit_lifetime(lifetime);
974 walk_list!(this, visit_param_bound, bounds);
04454e1e 975
487cf647 976 if lifetime.res != hir::LifetimeName::Static {
04454e1e 977 for bound in bounds {
9c376795 978 let hir::GenericBound::Outlives(lt) = bound else {
04454e1e
FG
979 continue;
980 };
487cf647 981 if lt.res != hir::LifetimeName::Static {
04454e1e
FG
982 continue;
983 }
9ffffee4
FG
984 this.insert_lifetime(lt, ResolvedArg::StaticLifetime);
985 this.tcx.struct_span_lint_hir(
986 lint::builtin::UNUSED_LIFETIMES,
987 lifetime.hir_id,
988 lifetime.ident.span,
989 format!(
990 "unnecessary lifetime parameter `{}`",
991 lifetime.ident
992 ),
993 |lint| {
994 let help = &format!(
995 "you can use the `'static` lifetime directly, in place of `{}`",
487cf647 996 lifetime.ident,
9ffffee4
FG
997 );
998 lint.help(help)
999 },
1000 );
04454e1e
FG
1001 }
1002 }
cdc7bbd5
XL
1003 }
1004 &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
9c376795
FG
1005 lhs_ty,
1006 rhs_ty,
cdc7bbd5
XL
1007 ..
1008 }) => {
1009 this.visit_ty(lhs_ty);
1010 this.visit_ty(rhs_ty);
dfeec247 1011 }
dfeec247
XL
1012 }
1013 }
cdc7bbd5 1014 })
dfeec247
XL
1015 }
1016
3dfed10e
XL
1017 fn visit_param_bound(&mut self, bound: &'tcx hir::GenericBound<'tcx>) {
1018 match bound {
cdc7bbd5
XL
1019 hir::GenericBound::LangItemTrait(_, _, hir_id, _) => {
1020 // FIXME(jackh726): This is pretty weird. `LangItemTrait` doesn't go
1021 // through the regular poly trait ref code, so we don't get another
1022 // chance to introduce a binder. For now, I'm keeping the existing logic
1023 // of "if there isn't a Binder scope above us, add one", but I
1024 // imagine there's a better way to go about this.
1025 let (binders, scope_type) = self.poly_trait_ref_binder_info();
1026
2b03887a 1027 self.record_late_bound_vars(*hir_id, binders);
3dfed10e 1028 let scope = Scope::Binder {
cdc7bbd5 1029 hir_id: *hir_id,
9ffffee4 1030 bound_vars: FxIndexMap::default(),
3dfed10e 1031 s: self.scope,
cdc7bbd5 1032 scope_type,
04454e1e 1033 where_bound_origin: None,
3dfed10e 1034 };
923072b8 1035 self.with(scope, |this| {
3dfed10e
XL
1036 intravisit::walk_param_bound(this, bound);
1037 });
1038 }
1039 _ => intravisit::walk_param_bound(self, bound),
1040 }
1041 }
1042
f2b60f7d 1043 fn visit_poly_trait_ref(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) {
9ffffee4
FG
1044 self.visit_poly_trait_ref_inner(trait_ref, NonLifetimeBinderAllowed::Allow);
1045 }
cdc7bbd5 1046
9ffffee4
FG
1047 fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
1048 self.with(Scope::AnonConstBoundary { s: self.scope }, |this| {
1049 intravisit::walk_anon_const(this, c);
cdc7bbd5 1050 });
dfeec247
XL
1051 }
1052}
1053
353b0b11 1054fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: LocalDefId) -> ObjectLifetimeDefault {
f2b60f7d 1055 debug_assert_eq!(tcx.def_kind(param_def_id), DefKind::TyParam);
9ffffee4
FG
1056 let hir::Node::GenericParam(param) = tcx.hir().get_by_def_id(param_def_id) else {
1057 bug!("expected GenericParam for object_lifetime_default");
1058 };
1059 match param.source {
1060 hir::GenericParamSource::Generics => {
1061 let parent_def_id = tcx.local_parent(param_def_id);
1062 let generics = tcx.hir().get_generics(parent_def_id).unwrap();
1063 let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id);
1064 let param = generics.params.iter().find(|p| p.hir_id == param_hir_id).unwrap();
1065
1066 // Scan the bounds and where-clauses on parameters to extract bounds
1067 // of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
1068 // for each type parameter.
1069 match param.kind {
1070 GenericParamKind::Type { .. } => {
1071 let mut set = Set1::Empty;
1072
1073 // Look for `type: ...` where clauses.
1074 for bound in generics.bounds_for_param(param_def_id) {
1075 // Ignore `for<'a> type: ...` as they can change what
1076 // lifetimes mean (although we could "just" handle it).
1077 if !bound.bound_generic_params.is_empty() {
1078 continue;
1079 }
dfeec247 1080
9ffffee4
FG
1081 for bound in bound.bounds {
1082 if let hir::GenericBound::Outlives(lifetime) = bound {
1083 set.insert(lifetime.res);
1084 }
1085 }
f2b60f7d 1086 }
5099ac24 1087
9ffffee4
FG
1088 match set {
1089 Set1::Empty => ObjectLifetimeDefault::Empty,
1090 Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static,
1091 Set1::One(hir::LifetimeName::Param(param_def_id)) => {
1092 ObjectLifetimeDefault::Param(param_def_id.to_def_id())
1093 }
1094 _ => ObjectLifetimeDefault::Ambiguous,
1095 }
1096 }
1097 _ => {
1098 bug!("object_lifetime_default_raw must only be called on a type parameter")
5099ac24 1099 }
f2b60f7d 1100 }
5099ac24 1101 }
9ffffee4 1102 hir::GenericParamSource::Binder => ObjectLifetimeDefault::Empty,
f2b60f7d 1103 }
dfeec247
XL
1104}
1105
9ffffee4 1106impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
dfeec247
XL
1107 fn with<F>(&mut self, wrap_scope: Scope<'_>, f: F)
1108 where
9ffffee4 1109 F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>),
dfeec247 1110 {
9ffffee4
FG
1111 let BoundVarContext { tcx, map, .. } = self;
1112 let mut this = BoundVarContext { tcx: *tcx, map, scope: &wrap_scope };
f2b60f7d 1113 let span = debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope));
cdc7bbd5
XL
1114 {
1115 let _enter = span.enter();
923072b8 1116 f(&mut this);
cdc7bbd5 1117 }
dfeec247
XL
1118 }
1119
2b03887a
FG
1120 fn record_late_bound_vars(&mut self, hir_id: hir::HirId, binder: Vec<ty::BoundVariableKind>) {
1121 if let Some(old) = self.map.late_bound_vars.insert(hir_id, binder) {
1122 bug!(
1123 "overwrote bound vars for {hir_id:?}:\nold={old:?}\nnew={:?}",
1124 self.map.late_bound_vars[&hir_id]
1125 )
1126 }
1127 }
1128
dfeec247
XL
1129 /// Visits self by adding a scope and handling recursive walk over the contents with `walk`.
1130 ///
1131 /// Handles visiting fns and methods. These are a bit complicated because we must distinguish
1132 /// early- vs late-bound lifetime parameters. We do this by checking which lifetimes appear
1133 /// within type bounds; those are early bound lifetimes, and the rest are late bound.
1134 ///
1135 /// For example:
1136 ///
1137 /// fn foo<'a,'b,'c,T:Trait<'b>>(...)
1138 ///
1139 /// Here `'a` and `'c` are late bound but `'b` is early bound. Note that early- and late-bound
1140 /// lifetimes may be interspersed together.
1141 ///
1142 /// If early bound lifetimes are present, we separate them into their own list (and likewise
1143 /// for late bound). They will be numbered sequentially, starting from the lowest index that is
1144 /// already in scope (for a fn item, that will be 0, but for a method it might not be). Late
1145 /// bound lifetimes are resolved by name and associated with a binder ID (`binder_id`), so the
1146 /// ordering is not important there.
1147 fn visit_early_late<F>(
1148 &mut self,
cdc7bbd5 1149 hir_id: hir::HirId,
dfeec247
XL
1150 generics: &'tcx hir::Generics<'tcx>,
1151 walk: F,
1152 ) where
9ffffee4 1153 F: for<'b, 'c> FnOnce(&'b mut BoundVarContext<'c, 'tcx>),
dfeec247 1154 {
cdc7bbd5 1155 let mut named_late_bound_vars = 0;
9ffffee4 1156 let bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = generics
dfeec247
XL
1157 .params
1158 .iter()
9ffffee4 1159 .map(|param| match param.kind {
dfeec247 1160 GenericParamKind::Lifetime { .. } => {
923072b8 1161 if self.tcx.is_late_bound(param.hir_id) {
cdc7bbd5
XL
1162 let late_bound_idx = named_late_bound_vars;
1163 named_late_bound_vars += 1;
9ffffee4 1164 ResolvedArg::late(late_bound_idx, param)
dfeec247 1165 } else {
9ffffee4 1166 ResolvedArg::early(param)
dfeec247
XL
1167 }
1168 }
9ffffee4
FG
1169 GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
1170 ResolvedArg::early(param)
1171 }
dfeec247
XL
1172 })
1173 .collect();
dfeec247 1174
cdc7bbd5
XL
1175 let binders: Vec<_> = generics
1176 .params
1177 .iter()
3c0e092e
XL
1178 .filter(|param| {
1179 matches!(param.kind, GenericParamKind::Lifetime { .. })
923072b8 1180 && self.tcx.is_late_bound(param.hir_id)
cdc7bbd5
XL
1181 })
1182 .enumerate()
1183 .map(|(late_bound_idx, param)| {
9ffffee4
FG
1184 let pair = ResolvedArg::late(late_bound_idx as u32, param);
1185 late_arg_as_bound_arg(self.tcx, &pair.1, param)
cdc7bbd5
XL
1186 })
1187 .collect();
2b03887a 1188 self.record_late_bound_vars(hir_id, binders);
dfeec247 1189 let scope = Scope::Binder {
cdc7bbd5 1190 hir_id,
9ffffee4 1191 bound_vars,
dfeec247 1192 s: self.scope,
cdc7bbd5 1193 scope_type: BinderScopeType::Normal,
04454e1e 1194 where_bound_origin: None,
dfeec247 1195 };
923072b8 1196 self.with(scope, walk);
dfeec247
XL
1197 }
1198
f2b60f7d 1199 #[instrument(level = "debug", skip(self))]
923072b8
FG
1200 fn resolve_lifetime_ref(
1201 &mut self,
1202 region_def_id: LocalDefId,
1203 lifetime_ref: &'tcx hir::Lifetime,
1204 ) {
dfeec247
XL
1205 // Walk up the scope chain, tracking the number of fn scopes
1206 // that we pass through, until we find a lifetime with the
1207 // given name or we run out of scopes.
1208 // search.
1209 let mut late_depth = 0;
1210 let mut scope = self.scope;
1211 let mut outermost_body = None;
1212 let result = loop {
1213 match *scope {
1214 Scope::Body { id, s } => {
1215 outermost_body = Some(id);
1216 scope = s;
1217 }
1218
487cf647
FG
1219 Scope::Root { opt_parent_item } => {
1220 if let Some(parent_item) = opt_parent_item
1221 && let parent_generics = self.tcx.generics_of(parent_item)
9ffffee4 1222 && parent_generics.param_def_id_to_index(self.tcx, region_def_id.to_def_id()).is_some()
487cf647 1223 {
9ffffee4 1224 break Some(ResolvedArg::EarlyBound(region_def_id.to_def_id()));
487cf647 1225 }
dfeec247
XL
1226 break None;
1227 }
1228
9ffffee4
FG
1229 Scope::Binder { ref bound_vars, scope_type, s, where_bound_origin, .. } => {
1230 if let Some(&def) = bound_vars.get(&region_def_id) {
923072b8 1231 break Some(def.shifted(late_depth));
dfeec247 1232 }
cdc7bbd5
XL
1233 match scope_type {
1234 BinderScopeType::Normal => late_depth += 1,
1235 BinderScopeType::Concatenating => {}
1236 }
064997fb
FG
1237 // Fresh lifetimes in APIT used to be allowed in async fns and forbidden in
1238 // regular fns.
1239 if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin
487cf647
FG
1240 && let hir::LifetimeName::Param(param_id) = lifetime_ref.res
1241 && let Some(generics) = self.tcx.hir().get_generics(self.tcx.local_parent(param_id))
1242 && let Some(param) = generics.params.iter().find(|p| p.def_id == param_id)
1243 && param.is_elided_lifetime()
2b03887a 1244 && let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id)
064997fb
FG
1245 && !self.tcx.features().anonymous_lifetime_in_impl_trait
1246 {
2b03887a 1247 let mut diag = rustc_session::parse::feature_err(
064997fb
FG
1248 &self.tcx.sess.parse_sess,
1249 sym::anonymous_lifetime_in_impl_trait,
487cf647 1250 lifetime_ref.ident.span,
064997fb 1251 "anonymous lifetimes in `impl Trait` are unstable",
2b03887a
FG
1252 );
1253
487cf647
FG
1254 if let Some(generics) =
1255 self.tcx.hir().get_generics(lifetime_ref.hir_id.owner.def_id)
1256 {
1257 let new_param_sugg = if let Some(span) =
1258 generics.span_for_lifetime_suggestion()
1259 {
1260 (span, "'a, ".to_owned())
1261 } else {
1262 (generics.span, "<'a>".to_owned())
1263 };
1264
1265 let lifetime_sugg = match lifetime_ref.suggestion_position() {
1266 (hir::LifetimeSuggestionPosition::Normal, span) => (span, "'a".to_owned()),
1267 (hir::LifetimeSuggestionPosition::Ampersand, span) => (span, "'a ".to_owned()),
1268 (hir::LifetimeSuggestionPosition::ElidedPath, span) => (span, "<'a>".to_owned()),
1269 (hir::LifetimeSuggestionPosition::ElidedPathArgument, span) => (span, "'a, ".to_owned()),
1270 (hir::LifetimeSuggestionPosition::ObjectDefault, span) => (span, "+ 'a".to_owned()),
1271 };
1272 let suggestions = vec![
1273 lifetime_sugg,
1274 new_param_sugg,
1275 ];
1276
1277 diag.span_label(
1278 lifetime_ref.ident.span,
1279 "expected named lifetime parameter",
1280 );
1281 diag.multipart_suggestion(
1282 "consider introducing a named lifetime parameter",
1283 suggestions,
1284 rustc_errors::Applicability::MaybeIncorrect,
1285 );
2b03887a
FG
1286 }
1287
1288 diag.emit();
064997fb
FG
1289 return;
1290 }
dfeec247
XL
1291 scope = s;
1292 }
1293
cdc7bbd5
XL
1294 Scope::Elision { s, .. }
1295 | Scope::ObjectLifetimeDefault { s, .. }
1296 | Scope::Supertrait { s, .. }
9ffffee4
FG
1297 | Scope::TraitRefBoundary { s, .. }
1298 | Scope::AnonConstBoundary { s } => {
dfeec247
XL
1299 scope = s;
1300 }
1301 }
1302 };
1303
1304 if let Some(mut def) = result {
9ffffee4 1305 if let ResolvedArg::EarlyBound(..) = def {
dfeec247
XL
1306 // Do not free early-bound regions, only late-bound ones.
1307 } else if let Some(body_id) = outermost_body {
1308 let fn_id = self.tcx.hir().body_owner(body_id);
1309 match self.tcx.hir().get(fn_id) {
9ffffee4 1310 Node::Item(hir::Item { owner_id, kind: hir::ItemKind::Fn(..), .. })
487cf647 1311 | Node::TraitItem(hir::TraitItem {
9ffffee4
FG
1312 owner_id,
1313 kind: hir::TraitItemKind::Fn(..),
1314 ..
dfeec247 1315 })
9ffffee4
FG
1316 | Node::ImplItem(hir::ImplItem {
1317 owner_id,
1318 kind: hir::ImplItemKind::Fn(..),
1319 ..
1320 }) => {
1321 def = ResolvedArg::Free(owner_id.to_def_id(), def.id().unwrap());
1322 }
1323 Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) => {
1324 def = ResolvedArg::Free(closure.def_id.to_def_id(), def.id().unwrap());
dfeec247
XL
1325 }
1326 _ => {}
1327 }
1328 }
1329
dfeec247 1330 self.insert_lifetime(lifetime_ref, def);
04454e1e
FG
1331 return;
1332 }
1333
f2b60f7d 1334 // We may fail to resolve higher-ranked lifetimes that are mentioned by APIT.
04454e1e 1335 // AST-based resolution does not care for impl-trait desugaring, which are the
9c376795 1336 // responibility of lowering. This may create a mismatch between the resolution
04454e1e
FG
1337 // AST found (`region_def_id`) which points to HRTB, and what HIR allows.
1338 // ```
1339 // fn foo(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
1340 // ```
1341 //
1342 // In such case, walk back the binders to diagnose it properly.
1343 let mut scope = self.scope;
1344 loop {
1345 match *scope {
1346 Scope::Binder {
1347 where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
1348 } => {
923072b8 1349 let mut err = self.tcx.sess.struct_span_err(
487cf647 1350 lifetime_ref.ident.span,
923072b8
FG
1351 "`impl Trait` can only mention lifetimes bound at the fn or impl level",
1352 );
1353 err.span_note(self.tcx.def_span(region_def_id), "lifetime declared here");
1354 err.emit();
04454e1e
FG
1355 return;
1356 }
487cf647 1357 Scope::Root { .. } => break,
04454e1e
FG
1358 Scope::Binder { s, .. }
1359 | Scope::Body { s, .. }
1360 | Scope::Elision { s, .. }
1361 | Scope::ObjectLifetimeDefault { s, .. }
1362 | Scope::Supertrait { s, .. }
9ffffee4
FG
1363 | Scope::TraitRefBoundary { s, .. }
1364 | Scope::AnonConstBoundary { s } => {
04454e1e
FG
1365 scope = s;
1366 }
1367 }
dfeec247 1368 }
04454e1e
FG
1369
1370 self.tcx.sess.delay_span_bug(
487cf647 1371 lifetime_ref.ident.span,
04454e1e
FG
1372 &format!("Could not resolve {:?} in scope {:#?}", lifetime_ref, self.scope,),
1373 );
dfeec247
XL
1374 }
1375
9ffffee4
FG
1376 fn resolve_type_ref(&mut self, param_def_id: LocalDefId, hir_id: hir::HirId) {
1377 // Walk up the scope chain, tracking the number of fn scopes
1378 // that we pass through, until we find a lifetime with the
1379 // given name or we run out of scopes.
1380 // search.
1381 let mut late_depth = 0;
1382 let mut scope = self.scope;
1383 let mut crossed_anon_const = false;
1384 let result = loop {
1385 match *scope {
1386 Scope::Body { s, .. } => {
1387 scope = s;
1388 }
1389
1390 Scope::Root { opt_parent_item } => {
1391 if let Some(parent_item) = opt_parent_item
1392 && let parent_generics = self.tcx.generics_of(parent_item)
1393 && parent_generics.param_def_id_to_index(self.tcx, param_def_id.to_def_id()).is_some()
1394 {
1395 break Some(ResolvedArg::EarlyBound(param_def_id.to_def_id()));
1396 }
1397 break None;
1398 }
1399
1400 Scope::Binder { ref bound_vars, scope_type, s, .. } => {
1401 if let Some(&def) = bound_vars.get(&param_def_id) {
1402 break Some(def.shifted(late_depth));
1403 }
1404 match scope_type {
1405 BinderScopeType::Normal => late_depth += 1,
1406 BinderScopeType::Concatenating => {}
1407 }
1408 scope = s;
1409 }
1410
1411 Scope::Elision { s, .. }
1412 | Scope::ObjectLifetimeDefault { s, .. }
1413 | Scope::Supertrait { s, .. }
1414 | Scope::TraitRefBoundary { s, .. } => {
1415 scope = s;
1416 }
1417
1418 Scope::AnonConstBoundary { s } => {
1419 crossed_anon_const = true;
1420 scope = s;
1421 }
1422 }
1423 };
1424
1425 if let Some(def) = result {
1426 if let ResolvedArg::LateBound(..) = def && crossed_anon_const {
1427 let use_span = self.tcx.hir().span(hir_id);
1428 let def_span = self.tcx.def_span(param_def_id);
353b0b11 1429 let guar = match self.tcx.def_kind(param_def_id) {
9ffffee4
FG
1430 DefKind::ConstParam => {
1431 self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Const {
1432 use_span,
1433 def_span,
353b0b11 1434 })
9ffffee4
FG
1435 }
1436 DefKind::TyParam => {
1437 self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Type {
1438 use_span,
1439 def_span,
353b0b11 1440 })
9ffffee4
FG
1441 }
1442 _ => unreachable!(),
353b0b11
FG
1443 };
1444 self.map.defs.insert(hir_id, ResolvedArg::Error(guar));
1445 } else {
1446 self.map.defs.insert(hir_id, def);
9ffffee4 1447 }
9ffffee4
FG
1448 return;
1449 }
1450
1451 self.tcx.sess.delay_span_bug(
1452 self.tcx.hir().span(hir_id),
1453 format!("could not resolve {param_def_id:?}"),
1454 );
1455 }
1456
f2b60f7d 1457 #[instrument(level = "debug", skip(self))]
dfeec247
XL
1458 fn visit_segment_args(
1459 &mut self,
1460 res: Res,
1461 depth: usize,
1462 generic_args: &'tcx hir::GenericArgs<'tcx>,
1463 ) {
353b0b11 1464 if generic_args.parenthesized == hir::GenericArgsParentheses::ParenSugar {
064997fb
FG
1465 self.visit_fn_like_elision(
1466 generic_args.inputs(),
1467 Some(generic_args.bindings[0].ty()),
1468 false,
1469 );
dfeec247
XL
1470 return;
1471 }
1472
064997fb
FG
1473 for arg in generic_args.args {
1474 if let hir::GenericArg::Lifetime(lt) = arg {
1475 self.visit_lifetime(lt);
1476 }
dfeec247
XL
1477 }
1478
1479 // Figure out if this is a type/trait segment,
1480 // which requires object lifetime defaults.
dfeec247 1481 let type_def_id = match res {
f2b60f7d
FG
1482 Res::Def(DefKind::AssocTy, def_id) if depth == 1 => Some(self.tcx.parent(def_id)),
1483 Res::Def(DefKind::Variant, def_id) if depth == 0 => Some(self.tcx.parent(def_id)),
ba9703b0
XL
1484 Res::Def(
1485 DefKind::Struct
1486 | DefKind::Union
1487 | DefKind::Enum
1488 | DefKind::TyAlias
1489 | DefKind::Trait,
1490 def_id,
1491 ) if depth == 0 => Some(def_id),
dfeec247
XL
1492 _ => None,
1493 };
1494
f2b60f7d 1495 debug!(?type_def_id);
dfeec247
XL
1496
1497 // Compute a vector of defaults, one for each type parameter,
1498 // per the rules given in RFCs 599 and 1156. Example:
1499 //
1500 // ```rust
1501 // struct Foo<'a, T: 'a, U> { }
1502 // ```
1503 //
1504 // If you have `Foo<'x, dyn Bar, dyn Baz>`, we want to default
1505 // `dyn Bar` to `dyn Bar + 'x` (because of the `T: 'a` bound)
1506 // and `dyn Baz` to `dyn Baz + 'static` (because there is no
1507 // such bound).
1508 //
1509 // Therefore, we would compute `object_lifetime_defaults` to a
1510 // vector like `['x, 'static]`. Note that the vector only
1511 // includes type parameters.
6a06907d 1512 let object_lifetime_defaults = type_def_id.map_or_else(Vec::new, |def_id| {
dfeec247
XL
1513 let in_body = {
1514 let mut scope = self.scope;
1515 loop {
1516 match *scope {
487cf647 1517 Scope::Root { .. } => break false,
dfeec247
XL
1518
1519 Scope::Body { .. } => break true,
1520
1521 Scope::Binder { s, .. }
1522 | Scope::Elision { s, .. }
cdc7bbd5
XL
1523 | Scope::ObjectLifetimeDefault { s, .. }
1524 | Scope::Supertrait { s, .. }
9ffffee4
FG
1525 | Scope::TraitRefBoundary { s, .. }
1526 | Scope::AnonConstBoundary { s } => {
dfeec247
XL
1527 scope = s;
1528 }
1529 }
1530 }
1531 };
1532
1533 let map = &self.map;
f2b60f7d
FG
1534 let generics = self.tcx.generics_of(def_id);
1535
1536 // `type_def_id` points to an item, so there is nothing to inherit generics from.
1537 debug_assert_eq!(generics.parent_count, 0);
1538
1539 let set_to_region = |set: ObjectLifetimeDefault| match set {
1540 ObjectLifetimeDefault::Empty => {
cdc7bbd5
XL
1541 if in_body {
1542 None
1543 } else {
9ffffee4 1544 Some(ResolvedArg::StaticLifetime)
cdc7bbd5
XL
1545 }
1546 }
9ffffee4 1547 ObjectLifetimeDefault::Static => Some(ResolvedArg::StaticLifetime),
f2b60f7d
FG
1548 ObjectLifetimeDefault::Param(param_def_id) => {
1549 // This index can be used with `generic_args` since `parent_count == 0`.
1550 let index = generics.param_def_id_to_index[&param_def_id] as usize;
1551 generic_args.args.get(index).and_then(|arg| match arg {
1552 GenericArg::Lifetime(lt) => map.defs.get(&lt.hir_id).copied(),
cdc7bbd5 1553 _ => None,
f2b60f7d 1554 })
cdc7bbd5 1555 }
f2b60f7d 1556 ObjectLifetimeDefault::Ambiguous => None,
cdc7bbd5 1557 };
f2b60f7d
FG
1558 generics
1559 .params
1560 .iter()
1561 .filter_map(|param| {
1562 match self.tcx.def_kind(param.def_id) {
1563 // Generic consts don't impose any constraints.
1564 //
1565 // We still store a dummy value here to allow generic parameters
1566 // in an arbitrary order.
1567 DefKind::ConstParam => Some(ObjectLifetimeDefault::Empty),
1568 DefKind::TyParam => Some(self.tcx.object_lifetime_default(param.def_id)),
1569 // We may also get a `Trait` or `TraitAlias` because of how generics `Self` parameter
9c376795 1570 // works. Ignore it because it can't have a meaningful lifetime default.
f2b60f7d
FG
1571 DefKind::LifetimeParam | DefKind::Trait | DefKind::TraitAlias => None,
1572 dk => bug!("unexpected def_kind {:?}", dk),
1573 }
1574 })
1575 .map(set_to_region)
1576 .collect()
dfeec247
XL
1577 });
1578
f2b60f7d 1579 debug!(?object_lifetime_defaults);
dfeec247
XL
1580
1581 let mut i = 0;
1582 for arg in generic_args.args {
1583 match arg {
1584 GenericArg::Lifetime(_) => {}
1585 GenericArg::Type(ty) => {
1586 if let Some(&lt) = object_lifetime_defaults.get(i) {
1587 let scope = Scope::ObjectLifetimeDefault { lifetime: lt, s: self.scope };
923072b8 1588 self.with(scope, |this| this.visit_ty(ty));
dfeec247
XL
1589 } else {
1590 self.visit_ty(ty);
1591 }
1592 i += 1;
1593 }
1594 GenericArg::Const(ct) => {
1595 self.visit_anon_const(&ct.value);
a2a8927a 1596 i += 1;
dfeec247 1597 }
94222f64
XL
1598 GenericArg::Infer(inf) => {
1599 self.visit_id(inf.hir_id);
a2a8927a 1600 i += 1;
94222f64 1601 }
dfeec247
XL
1602 }
1603 }
1604
1605 // Hack: when resolving the type `XX` in binding like `dyn
1606 // Foo<'b, Item = XX>`, the current object-lifetime default
1607 // would be to examine the trait `Foo` to check whether it has
1608 // a lifetime bound declared on `Item`. e.g., if `Foo` is
1609 // declared like so, then the default object lifetime bound in
1610 // `XX` should be `'b`:
1611 //
1612 // ```rust
1613 // trait Foo<'a> {
1614 // type Item: 'a;
1615 // }
1616 // ```
1617 //
1618 // but if we just have `type Item;`, then it would be
1619 // `'static`. However, we don't get all of this logic correct.
1620 //
1621 // Instead, we do something hacky: if there are no lifetime parameters
1622 // to the trait, then we simply use a default object lifetime
1623 // bound of `'static`, because there is no other possibility. On the other hand,
1624 // if there ARE lifetime parameters, then we require the user to give an
1625 // explicit bound for now.
1626 //
1627 // This is intended to leave room for us to implement the
1628 // correct behavior in the future.
29967ef6
XL
1629 let has_lifetime_parameter =
1630 generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
dfeec247 1631
cdc7bbd5
XL
1632 // Resolve lifetimes found in the bindings, so either in the type `XX` in `Item = XX` or
1633 // in the trait ref `YY<...>` in `Item: YY<...>`.
1634 for binding in generic_args.bindings {
dfeec247 1635 let scope = Scope::ObjectLifetimeDefault {
9ffffee4
FG
1636 lifetime: if has_lifetime_parameter {
1637 None
1638 } else {
1639 Some(ResolvedArg::StaticLifetime)
1640 },
dfeec247
XL
1641 s: self.scope,
1642 };
353b0b11
FG
1643 // If the binding is parenthesized, then this must be `feature(return_type_notation)`.
1644 // In that case, introduce a binder over all of the function's early and late bound vars.
1645 //
1646 // For example, given
1647 // ```
1648 // trait Foo {
1649 // async fn x<'r, T>();
1650 // }
1651 // ```
1652 // and a bound that looks like:
1653 // `for<'a> T::Trait<'a, x(): for<'b> Other<'b>>`
1654 // this is going to expand to something like:
1655 // `for<'a> for<'r, T> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: for<'b> Other<'b>`.
1656 if binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation {
1657 let bound_vars = if let Some(type_def_id) = type_def_id
1658 && self.tcx.def_kind(type_def_id) == DefKind::Trait
1659 // FIXME(return_type_notation): We could bound supertrait methods.
1660 && let Some(assoc_fn) = self
1661 .tcx
1662 .associated_items(type_def_id)
1663 .find_by_name_and_kind(self.tcx, binding.ident, ty::AssocKind::Fn, type_def_id)
1664 {
1665 self.tcx
1666 .generics_of(assoc_fn.def_id)
1667 .params
1668 .iter()
1669 .map(|param| match param.kind {
1670 ty::GenericParamDefKind::Lifetime => ty::BoundVariableKind::Region(
1671 ty::BoundRegionKind::BrNamed(param.def_id, param.name),
1672 ),
1673 ty::GenericParamDefKind::Type { .. } => ty::BoundVariableKind::Ty(
1674 ty::BoundTyKind::Param(param.def_id, param.name),
1675 ),
1676 ty::GenericParamDefKind::Const { .. } => ty::BoundVariableKind::Const,
1677 })
1678 .chain(self.tcx.fn_sig(assoc_fn.def_id).subst_identity().bound_vars())
1679 .collect()
1680 } else {
1681 self.tcx.sess.delay_span_bug(
1682 binding.ident.span,
1683 "bad return type notation here",
1684 );
1685 vec![]
1686 };
1687 self.with(scope, |this| {
1688 let scope = Scope::Supertrait { bound_vars, s: this.scope };
1689 this.with(scope, |this| {
1690 let (bound_vars, _) = this.poly_trait_ref_binder_info();
1691 this.record_late_bound_vars(binding.hir_id, bound_vars);
1692 this.visit_assoc_type_binding(binding)
1693 });
1694 });
1695 } else if let Some(type_def_id) = type_def_id {
9ffffee4
FG
1696 let bound_vars =
1697 BoundVarContext::supertrait_hrtb_vars(self.tcx, type_def_id, binding.ident);
923072b8 1698 self.with(scope, |this| {
94222f64 1699 let scope = Scope::Supertrait {
9ffffee4 1700 bound_vars: bound_vars.unwrap_or_default(),
94222f64
XL
1701 s: this.scope,
1702 };
923072b8 1703 this.with(scope, |this| this.visit_assoc_type_binding(binding));
cdc7bbd5
XL
1704 });
1705 } else {
923072b8 1706 self.with(scope, |this| this.visit_assoc_type_binding(binding));
cdc7bbd5
XL
1707 }
1708 }
1709 }
1710
1711 /// Returns all the late-bound vars that come into scope from supertrait HRTBs, based on the
1712 /// associated type name and starting trait.
1713 /// For example, imagine we have
04454e1e 1714 /// ```ignore (illustrative)
cdc7bbd5
XL
1715 /// trait Foo<'a, 'b> {
1716 /// type As;
1717 /// }
1718 /// trait Bar<'b>: for<'a> Foo<'a, 'b> {}
1719 /// trait Bar: for<'b> Bar<'b> {}
1720 /// ```
1721 /// In this case, if we wanted to the supertrait HRTB lifetimes for `As` on
1722 /// the starting trait `Bar`, we would return `Some(['b, 'a])`.
9ffffee4 1723 fn supertrait_hrtb_vars(
cdc7bbd5
XL
1724 tcx: TyCtxt<'tcx>,
1725 def_id: DefId,
1726 assoc_name: Ident,
1727 ) -> Option<Vec<ty::BoundVariableKind>> {
1728 let trait_defines_associated_type_named = |trait_def_id: DefId| {
1729 tcx.associated_items(trait_def_id)
1730 .find_by_name_and_kind(tcx, assoc_name, ty::AssocKind::Type, trait_def_id)
1731 .is_some()
1732 };
1733
1734 use smallvec::{smallvec, SmallVec};
1735 let mut stack: SmallVec<[(DefId, SmallVec<[ty::BoundVariableKind; 8]>); 8]> =
1736 smallvec![(def_id, smallvec![])];
1737 let mut visited: FxHashSet<DefId> = FxHashSet::default();
1738 loop {
5e7ed085
FG
1739 let Some((def_id, bound_vars)) = stack.pop() else {
1740 break None;
cdc7bbd5
XL
1741 };
1742 // See issue #83753. If someone writes an associated type on a non-trait, just treat it as
1743 // there being no supertrait HRTBs.
1744 match tcx.def_kind(def_id) {
9ffffee4 1745 DefKind::Trait | DefKind::TraitAlias | DefKind::Impl { .. } => {}
cdc7bbd5
XL
1746 _ => break None,
1747 }
1748
1749 if trait_defines_associated_type_named(def_id) {
1750 break Some(bound_vars.into_iter().collect());
1751 }
353b0b11 1752 let predicates = tcx.super_predicates_that_define_assoc_type((def_id, assoc_name));
cdc7bbd5
XL
1753 let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| {
1754 let bound_predicate = pred.kind();
1755 match bound_predicate.skip_binder() {
487cf647 1756 ty::PredicateKind::Clause(ty::Clause::Trait(data)) => {
cdc7bbd5
XL
1757 // The order here needs to match what we would get from `subst_supertrait`
1758 let pred_bound_vars = bound_predicate.bound_vars();
1759 let mut all_bound_vars = bound_vars.clone();
1760 all_bound_vars.extend(pred_bound_vars.iter());
1761 let super_def_id = data.trait_ref.def_id;
1762 Some((super_def_id, all_bound_vars))
1763 }
1764 _ => None,
1765 }
1766 });
1767
1768 let obligations = obligations.filter(|o| visited.insert(o.0));
1769 stack.extend(obligations);
dfeec247
XL
1770 }
1771 }
1772
f2b60f7d 1773 #[instrument(level = "debug", skip(self))]
dfeec247
XL
1774 fn visit_fn_like_elision(
1775 &mut self,
1776 inputs: &'tcx [hir::Ty<'tcx>],
1777 output: Option<&'tcx hir::Ty<'tcx>>,
064997fb 1778 in_closure: bool,
dfeec247 1779 ) {
064997fb 1780 self.with(Scope::Elision { s: self.scope }, |this| {
dfeec247
XL
1781 for input in inputs {
1782 this.visit_ty(input);
1783 }
064997fb
FG
1784 if !in_closure && let Some(output) = output {
1785 this.visit_ty(output);
dfeec247 1786 }
064997fb
FG
1787 });
1788 if in_closure && let Some(output) = output {
1789 self.visit_ty(output);
dfeec247 1790 }
dfeec247
XL
1791 }
1792
dfeec247
XL
1793 fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
1794 debug!("resolve_object_lifetime_default(lifetime_ref={:?})", lifetime_ref);
1795 let mut late_depth = 0;
1796 let mut scope = self.scope;
1797 let lifetime = loop {
1798 match *scope {
cdc7bbd5
XL
1799 Scope::Binder { s, scope_type, .. } => {
1800 match scope_type {
1801 BinderScopeType::Normal => late_depth += 1,
1802 BinderScopeType::Concatenating => {}
1803 }
dfeec247
XL
1804 scope = s;
1805 }
1806
9ffffee4 1807 Scope::Root { .. } | Scope::Elision { .. } => break ResolvedArg::StaticLifetime,
dfeec247
XL
1808
1809 Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return,
1810
1811 Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => break l,
cdc7bbd5 1812
9ffffee4
FG
1813 Scope::Supertrait { s, .. }
1814 | Scope::TraitRefBoundary { s, .. }
1815 | Scope::AnonConstBoundary { s } => {
cdc7bbd5
XL
1816 scope = s;
1817 }
dfeec247
XL
1818 }
1819 };
1820 self.insert_lifetime(lifetime_ref, lifetime.shifted(late_depth));
1821 }
1822
f2b60f7d 1823 #[instrument(level = "debug", skip(self))]
9ffffee4 1824 fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: ResolvedArg) {
487cf647 1825 debug!(span = ?lifetime_ref.ident.span);
dfeec247 1826 self.map.defs.insert(lifetime_ref.hir_id, def);
dfeec247
XL
1827 }
1828
1829 /// Sometimes we resolve a lifetime, but later find that it is an
1830 /// error (esp. around impl trait). In that case, we remove the
1831 /// entry into `map.defs` so as not to confuse later code.
9ffffee4
FG
1832 fn uninsert_lifetime_on_error(
1833 &mut self,
1834 lifetime_ref: &'tcx hir::Lifetime,
1835 bad_def: ResolvedArg,
1836 ) {
dfeec247
XL
1837 let old_value = self.map.defs.remove(&lifetime_ref.hir_id);
1838 assert_eq!(old_value, Some(bad_def));
1839 }
1840}
1841
1842/// Detects late-bound lifetimes and inserts them into
923072b8 1843/// `late_bound`.
dfeec247
XL
1844///
1845/// A region declared on a fn is **late-bound** if:
1846/// - it is constrained by an argument type;
1847/// - it does not appear in a where-clause.
1848///
1849/// "Constrained" basically means that it appears in any type but
1850/// not amongst the inputs to a projection. In other words, `<&'a
1851/// T as Trait<''b>>::Foo` does not constrain `'a` or `'b`.
9ffffee4
FG
1852fn is_late_bound_map(
1853 tcx: TyCtxt<'_>,
1854 owner_id: hir::OwnerId,
1855) -> Option<&FxIndexSet<hir::ItemLocalId>> {
1856 let decl = tcx.hir().fn_decl_by_hir_id(owner_id.into())?;
1857 let generics = tcx.hir().get_generics(owner_id.def_id)?;
923072b8
FG
1858
1859 let mut late_bound = FxIndexSet::default();
1860
487cf647 1861 let mut constrained_by_input = ConstrainedCollector { regions: Default::default(), tcx };
dfeec247
XL
1862 for arg_ty in decl.inputs {
1863 constrained_by_input.visit_ty(arg_ty);
1864 }
1865
1866 let mut appears_in_output = AllCollector::default();
1867 intravisit::walk_fn_ret_ty(&mut appears_in_output, &decl.output);
1868
cdc7bbd5 1869 debug!(?constrained_by_input.regions);
dfeec247
XL
1870
1871 // Walk the lifetimes that appear in where clauses.
1872 //
1873 // Subtle point: because we disallow nested bindings, we can just
1874 // ignore binders here and scrape up all names we see.
1875 let mut appears_in_where_clause = AllCollector::default();
1876 appears_in_where_clause.visit_generics(generics);
cdc7bbd5 1877 debug!(?appears_in_where_clause.regions);
dfeec247
XL
1878
1879 // Late bound regions are those that:
1880 // - appear in the inputs
1881 // - do not appear in the where-clauses
1882 // - are not implicitly captured by `impl Trait`
1883 for param in generics.params {
1884 match param.kind {
1885 hir::GenericParamKind::Lifetime { .. } => { /* fall through */ }
1886
1887 // Neither types nor consts are late-bound.
1888 hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => continue,
1889 }
1890
dfeec247 1891 // appears in the where clauses? early-bound.
9ffffee4 1892 if appears_in_where_clause.regions.contains(&param.def_id) {
dfeec247
XL
1893 continue;
1894 }
1895
1896 // does not appear in the inputs, but appears in the return type? early-bound.
9ffffee4
FG
1897 if !constrained_by_input.regions.contains(&param.def_id)
1898 && appears_in_output.regions.contains(&param.def_id)
dfeec247
XL
1899 {
1900 continue;
1901 }
1902
9ffffee4 1903 debug!("lifetime {:?} with id {:?} is late-bound", param.name.ident(), param.def_id);
dfeec247 1904
9ffffee4
FG
1905 let inserted = late_bound.insert(param.hir_id.local_id);
1906 assert!(inserted, "visited lifetime {:?} twice", param.def_id);
dfeec247
XL
1907 }
1908
923072b8
FG
1909 debug!(?late_bound);
1910 return Some(tcx.arena.alloc(late_bound));
dfeec247 1911
487cf647
FG
1912 /// Visits a `ty::Ty` collecting information about what generic parameters are constrained.
1913 ///
1914 /// The visitor does not operate on `hir::Ty` so that it can be called on the rhs of a `type Alias<...> = ...;`
1915 /// which may live in a separate crate so there would not be any hir available. Instead we use the `type_of`
1916 /// query to obtain a `ty::Ty` which will be present even in cross crate scenarios. It also naturally
1917 /// handles cycle detection as we go through the query system.
1918 ///
1919 /// This is necessary in the first place for the following case:
1920 /// ```
1921 /// type Alias<'a, T> = <T as Trait<'a>>::Assoc;
1922 /// fn foo<'a>(_: Alias<'a, ()>) -> Alias<'a, ()> { ... }
1923 /// ```
1924 ///
1925 /// If we conservatively considered `'a` unconstrained then we could break users who had written code before
1926 /// we started correctly handling aliases. If we considered `'a` constrained then it would become late bound
1927 /// causing an error during astconv as the `'a` is not constrained by the input type `<() as Trait<'a>>::Assoc`
1928 /// but appears in the output type `<() as Trait<'a>>::Assoc`.
1929 ///
1930 /// We must therefore "look into" the `Alias` to see whether we should consider `'a` constrained or not.
1931 ///
1932 /// See #100508 #85533 #47511 for additional context
1933 struct ConstrainedCollectorPostAstConv {
1934 arg_is_constrained: Box<[bool]>,
1935 }
1936
1937 use std::ops::ControlFlow;
1938 use ty::Ty;
9ffffee4 1939 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstrainedCollectorPostAstConv {
487cf647
FG
1940 fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> {
1941 match t.kind() {
1942 ty::Param(param_ty) => {
1943 self.arg_is_constrained[param_ty.index as usize] = true;
1944 }
9c376795 1945 ty::Alias(ty::Projection, _) => return ControlFlow::Continue(()),
487cf647
FG
1946 _ => (),
1947 }
1948 t.super_visit_with(self)
1949 }
1950
1951 fn visit_const(&mut self, _: ty::Const<'tcx>) -> ControlFlow<!> {
1952 ControlFlow::Continue(())
1953 }
1954
1955 fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<!> {
1956 debug!("r={:?}", r.kind());
1957 if let ty::RegionKind::ReEarlyBound(region) = r.kind() {
1958 self.arg_is_constrained[region.index as usize] = true;
1959 }
1960
1961 ControlFlow::Continue(())
1962 }
1963 }
1964
1965 struct ConstrainedCollector<'tcx> {
1966 tcx: TyCtxt<'tcx>,
923072b8 1967 regions: FxHashSet<LocalDefId>,
dfeec247
XL
1968 }
1969
487cf647 1970 impl<'v> Visitor<'v> for ConstrainedCollector<'_> {
dfeec247
XL
1971 fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
1972 match ty.kind {
ba9703b0
XL
1973 hir::TyKind::Path(
1974 hir::QPath::Resolved(Some(_), _) | hir::QPath::TypeRelative(..),
1975 ) => {
dfeec247
XL
1976 // ignore lifetimes appearing in associated type
1977 // projections, as they are not *constrained*
1978 // (defined above)
1979 }
1980
487cf647
FG
1981 hir::TyKind::Path(hir::QPath::Resolved(
1982 None,
1983 hir::Path { res: Res::Def(DefKind::TyAlias, alias_def), segments, span },
1984 )) => {
1985 // See comments on `ConstrainedCollectorPostAstConv` for why this arm does not just consider
1986 // substs to be unconstrained.
1987 let generics = self.tcx.generics_of(alias_def);
1988 let mut walker = ConstrainedCollectorPostAstConv {
1989 arg_is_constrained: vec![false; generics.params.len()].into_boxed_slice(),
1990 };
9ffffee4 1991 walker.visit_ty(self.tcx.type_of(alias_def).subst_identity());
487cf647
FG
1992
1993 match segments.last() {
1994 Some(hir::PathSegment { args: Some(args), .. }) => {
1995 let tcx = self.tcx;
1996 for constrained_arg in
1997 args.args.iter().enumerate().flat_map(|(n, arg)| {
1998 match walker.arg_is_constrained.get(n) {
1999 Some(true) => Some(arg),
2000 Some(false) => None,
2001 None => {
2002 tcx.sess.delay_span_bug(
2003 *span,
2004 format!(
2005 "Incorrect generic arg count for alias {:?}",
2006 alias_def
2007 ),
2008 );
2009 None
2010 }
2011 }
2012 })
2013 {
2014 self.visit_generic_arg(constrained_arg);
2015 }
2016 }
2017 Some(_) => (),
2018 None => bug!("Path with no segments or self type"),
2019 }
2020 }
2021
9c376795 2022 hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
dfeec247
XL
2023 // consider only the lifetimes on the final
2024 // segment; I am not sure it's even currently
2025 // valid to have them elsewhere, but even if it
2026 // is, those would be potentially inputs to
2027 // projections
2028 if let Some(last_segment) = path.segments.last() {
f2b60f7d 2029 self.visit_path_segment(last_segment);
dfeec247
XL
2030 }
2031 }
2032
2033 _ => {
2034 intravisit::walk_ty(self, ty);
2035 }
2036 }
2037 }
2038
2039 fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
487cf647 2040 if let hir::LifetimeName::Param(def_id) = lifetime_ref.res {
923072b8
FG
2041 self.regions.insert(def_id);
2042 }
dfeec247
XL
2043 }
2044 }
2045
2046 #[derive(Default)]
2047 struct AllCollector {
923072b8 2048 regions: FxHashSet<LocalDefId>,
dfeec247
XL
2049 }
2050
2051 impl<'v> Visitor<'v> for AllCollector {
dfeec247 2052 fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
487cf647 2053 if let hir::LifetimeName::Param(def_id) = lifetime_ref.res {
923072b8
FG
2054 self.regions.insert(def_id);
2055 }
dfeec247
XL
2056 }
2057 }
2058}
9ffffee4
FG
2059
2060pub fn deny_non_region_late_bound(
2061 tcx: TyCtxt<'_>,
2062 bound_vars: &mut FxIndexMap<LocalDefId, ResolvedArg>,
2063 where_: &str,
2064) {
2065 let mut first = true;
2066
2067 for (var, arg) in bound_vars {
2068 let Node::GenericParam(param) = tcx.hir().get_by_def_id(*var) else {
2069 bug!();
2070 };
2071
2072 let what = match param.kind {
2073 hir::GenericParamKind::Type { .. } => "type",
2074 hir::GenericParamKind::Const { .. } => "const",
2075 hir::GenericParamKind::Lifetime { .. } => continue,
2076 };
2077
2078 let mut diag = tcx.sess.struct_span_err(
2079 param.span,
2080 format!("late-bound {what} parameter not allowed on {where_}"),
2081 );
2082
2083 let guar = if tcx.features().non_lifetime_binders && first {
2084 diag.emit()
2085 } else {
2086 diag.delay_as_bug()
2087 };
2088
2089 first = false;
2090 *arg = ResolvedArg::Error(guar);
2091 }
2092}