about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorJack Huey <jack.huey@umassmed.edu>2021-03-26 17:40:15 -0400
committerJack Huey <jack.huey@umassmed.edu>2021-03-31 10:16:37 -0400
commit7108918db6f59fca6656849c3e360045354e8a42 (patch)
tree124e089444740f2ac65eef217e221cd832033ef7 /compiler
parent0c98dc66fdc1bd5a2ff56bc72c67b03c2d376cd0 (diff)
downloadrust-7108918db6f59fca6656849c3e360045354e8a42.tar.gz
rust-7108918db6f59fca6656849c3e360045354e8a42.zip
Cleanups and comments
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_middle/src/ty/util.rs1
-rw-r--r--compiler/rustc_mir/src/monomorphize/mod.rs4
-rw-r--r--compiler/rustc_resolve/src/late.rs1
-rw-r--r--compiler/rustc_resolve/src/late/lifetimes.rs407
-rw-r--r--compiler/rustc_resolve/src/late/supertraits.rs60
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs1
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs5
7 files changed, 214 insertions, 265 deletions
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index b211ac2a79f..7d09ca5152f 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -504,7 +504,6 @@ impl<'tcx> TyCtxt<'tcx> {
         let closure_ty = self.mk_closure(closure_def_id, closure_substs);
         let closure_kind_ty = closure_substs.as_closure().kind_ty();
         let closure_kind = closure_kind_ty.to_opt_closure_kind()?;
-        debug_assert!(!closure_ty.has_escaping_bound_vars());
         let env_ty = match closure_kind {
             ty::ClosureKind::Fn => self.mk_imm_ref(self.mk_region(env_region), closure_ty),
             ty::ClosureKind::FnMut => self.mk_mut_ref(self.mk_region(env_region), closure_ty),
diff --git a/compiler/rustc_mir/src/monomorphize/mod.rs b/compiler/rustc_mir/src/monomorphize/mod.rs
index fd3f3b3a080..9ca4b6687f1 100644
--- a/compiler/rustc_mir/src/monomorphize/mod.rs
+++ b/compiler/rustc_mir/src/monomorphize/mod.rs
@@ -1,6 +1,6 @@
 use rustc_middle::traits;
 use rustc_middle::ty::adjustment::CustomCoerceUnsized;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 
 use rustc_hir::lang_items::LangItem;
 
@@ -15,8 +15,6 @@ fn custom_coerce_unsize_info<'tcx>(
 ) -> CustomCoerceUnsized {
     let def_id = tcx.require_lang_item(LangItem::CoerceUnsized, None);
 
-    debug_assert!(!source_ty.has_escaping_bound_vars());
-    debug_assert!(!target_ty.has_escaping_bound_vars());
     let trait_ref = ty::Binder::dummy(ty::TraitRef {
         def_id,
         substs: tcx.mk_substs_trait(source_ty, &[target_ty.into()]),
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 25acbd478bf..1377bb781d0 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -34,7 +34,6 @@ use tracing::debug;
 
 mod diagnostics;
 crate mod lifetimes;
-crate mod supertraits;
 
 type Res = def::Res<NodeId>;
 
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs
index 79d81ef047e..b89ad867f46 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_resolve/src/late/lifetimes.rs
@@ -151,6 +151,12 @@ struct NamedRegionMap {
     // (b) it DOES appear in the arguments.
     late_bound: HirIdSet,
 
+    // Maps relevant hir items to the bound vars on them. These include:
+    // - function defs
+    // - function pointers
+    // - closures
+    // - trait refs
+    // - bound types (like `T` in `for<'a> T<'a>: Foo`)
     late_bound_vars: HirIdMap<Vec<ty::BoundVariableKind>>,
 }
 
@@ -171,10 +177,16 @@ crate struct LifetimeContext<'a, 'tcx> {
     /// any bound var information.
     ///
     /// So, if we encounter a quantifier at the outer scope, we set
-    /// `trait_ref_hack` to `true` (and introduce a scope), and then if we encounter
-    /// a quantifier at the inner scope, we error. If `trait_ref_hack` is `false`,
-    /// then we introduce the scope at the inner quantifier.
-    trait_ref_hack: Option<(Vec<ty::BoundVariableKind>, u32)>,
+    /// `trait_ref_hack` to the hir id of the bounded type (and introduce a scope).
+    /// Then, if we encounter a quantifier at the inner scope, then we know to
+    /// emit an error. Importantly though, we do have to track the lifetimes
+    /// defined on the outer scope (i.e. the bounded ty), since we continue
+    /// to type check after emitting an error; we therefore assume that the bound
+    /// vars on the inner trait refs come from both quantifiers.
+    ///
+    /// If we encounter a quantifier in the inner scope `trait_ref_hack` being
+    /// `None`, then we just introduce the scope at the inner quantifier as normal.
+    trait_ref_hack: Option<hir::HirId>,
 
     /// Used to disallow the use of in-band lifetimes in `fn` or `Fn` syntax.
     is_in_fn_syntax: bool,
@@ -232,11 +244,9 @@ enum Scope<'a> {
         /// of the resulting opaque type.
         opaque_type_parent: bool,
 
-        /// We need to keep track of the number of named late bound vars, since
-        /// we may have elided lifetimes that have an index starting *after*
-        /// these.
-        named_late_bound_vars: u32,
-
+        /// True only if this `Binder` scope is from the quantifiers on a
+        /// `PolyTraitRef`. This is necessary for `assocated_type_bounds`, which
+        /// requires binders of nested trait refs to be merged.
         from_poly_trait_ref: bool,
 
         /// The late bound vars for a given item are stored by `HirId` to be
@@ -304,7 +314,6 @@ enum Scope<'a> {
     /// vars from both `for<...>`s *do* share the same binder level.
     TraitRefHackInner {
         hir_id: hir::HirId,
-        named_late_bound_vars: u32,
         s: ScopeRef<'a>,
     },
 
@@ -331,7 +340,6 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
                 next_early_index,
                 track_lifetime_uses,
                 opaque_type_parent,
-                named_late_bound_vars,
                 from_poly_trait_ref,
                 hir_id,
                 s: _,
@@ -341,7 +349,6 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
                 .field("next_early_index", next_early_index)
                 .field("track_lifetime_uses", track_lifetime_uses)
                 .field("opaque_type_parent", opaque_type_parent)
-                .field("named_late_bound_vars", named_late_bound_vars)
                 .field("from_poly_trait_ref", from_poly_trait_ref)
                 .field("hir_id", hir_id)
                 .field("s", &"..")
@@ -357,10 +364,9 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
                 .field("lifetime", lifetime)
                 .field("s", &"..")
                 .finish(),
-            Scope::TraitRefHackInner { hir_id, named_late_bound_vars, s: _ } => f
+            Scope::TraitRefHackInner { hir_id, s: _ } => f
                 .debug_struct("TraitRefHackInner")
                 .field("hir_id", hir_id)
-                .field("named_late_bound_vars", named_late_bound_vars)
                 .field("s", &"..")
                 .finish(),
             Scope::Supertrait { lifetimes, s: _ } => f
@@ -664,7 +670,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     s: self.scope,
                     track_lifetime_uses: true,
                     opaque_type_parent: false,
-                    named_late_bound_vars: 0,
                     from_poly_trait_ref: false,
                 };
                 self.with(scope, move |_old_scope, this| {
@@ -790,7 +795,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     next_early_index: index + non_lifetime_count,
                     opaque_type_parent: true,
                     track_lifetime_uses,
-                    named_late_bound_vars: 0,
                     from_poly_trait_ref: false,
                     s: ROOT_SCOPE,
                 };
@@ -838,21 +842,19 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 };
                 self.missing_named_lifetime_spots
                     .push(MissingLifetimeSpot::HigherRanked { span, span_type });
-                let mut named_late_bound_vars = 0;
                 let (lifetimes, binders): (FxHashMap<hir::ParamName, Region>, Vec<_>) = c
                     .generic_params
                     .iter()
                     .filter_map(|param| match param.kind {
-                        GenericParamKind::Lifetime { .. } => {
-                            let late_bound_idx = named_late_bound_vars;
-                            named_late_bound_vars += 1;
-                            let pair = Region::late(late_bound_idx, &self.tcx.hir(), param);
-                            let r = pair.1.clone();
-                            let r = late_region_as_bound_region(self.tcx, &r);
-                            Some((pair, r))
-                        }
+                        GenericParamKind::Lifetime { .. } => Some(param),
                         _ => None,
                     })
+                    .enumerate()
+                    .map(|(late_bound_idx, param)| {
+                        let pair = Region::late(late_bound_idx as u32, &self.tcx.hir(), param);
+                        let r = late_region_as_bound_region(self.tcx, &pair.1);
+                        (pair, r)
+                    })
                     .unzip();
                 self.map.late_bound_vars.insert(ty.hir_id, binders);
                 let scope = Scope::Binder {
@@ -862,7 +864,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     next_early_index,
                     track_lifetime_uses: true,
                     opaque_type_parent: false,
-                    named_late_bound_vars,
                     from_poly_trait_ref: false,
                 };
                 self.with(scope, |old_scope, this| {
@@ -1053,7 +1054,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                             s: this.scope,
                             track_lifetime_uses: true,
                             opaque_type_parent: false,
-                            named_late_bound_vars: 0,
                             from_poly_trait_ref: false,
                         };
                         this.with(scope, |_old_scope, this| {
@@ -1071,7 +1071,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                         s: self.scope,
                         track_lifetime_uses: true,
                         opaque_type_parent: false,
-                        named_late_bound_vars: 0,
                         from_poly_trait_ref: false,
                     };
                     self.with(scope, |_old_scope, this| {
@@ -1128,7 +1127,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     s: self.scope,
                     track_lifetime_uses: true,
                     opaque_type_parent: true,
-                    named_late_bound_vars: 0,
                     from_poly_trait_ref: false,
                 };
                 self.with(scope, |old_scope, this| {
@@ -1195,7 +1193,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     s: self.scope,
                     track_lifetime_uses: true,
                     opaque_type_parent: true,
-                    named_late_bound_vars: 0,
                     from_poly_trait_ref: false,
                 };
                 self.with(scope, |old_scope, this| {
@@ -1279,21 +1276,21 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     ref bound_generic_params,
                     ..
                 }) => {
-                    let mut named_late_bound_vars = 0;
-                    let (lifetimes, binders): (FxHashMap<_, _>, Vec<_>) = bound_generic_params
-                        .iter()
-                        .filter_map(|param| match param.kind {
-                            GenericParamKind::Lifetime { .. } => {
-                                let late_bound_idx = named_late_bound_vars;
-                                named_late_bound_vars += 1;
-                                let pair = Region::late(late_bound_idx, &self.tcx.hir(), param);
-                                let r = pair.1.clone();
-                                let r = late_region_as_bound_region(self.tcx, &r);
-                                Some((pair, r))
-                            }
-                            _ => None,
-                        })
-                        .unzip();
+                    let (lifetimes, binders): (FxHashMap<hir::ParamName, Region>, Vec<_>) =
+                        bound_generic_params
+                            .iter()
+                            .filter_map(|param| match param.kind {
+                                GenericParamKind::Lifetime { .. } => Some(param),
+                                _ => None,
+                            })
+                            .enumerate()
+                            .map(|(late_bound_idx, param)| {
+                                let pair =
+                                    Region::late(late_bound_idx as u32, &self.tcx.hir(), param);
+                                let r = late_region_as_bound_region(self.tcx, &pair.1);
+                                (pair, r)
+                            })
+                            .unzip();
                     self.map.late_bound_vars.insert(bounded_ty.hir_id, binders.clone());
                     if !lifetimes.is_empty() {
                         let next_early_index = self.next_early_index();
@@ -1304,13 +1301,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                             next_early_index,
                             track_lifetime_uses: true,
                             opaque_type_parent: false,
-                            named_late_bound_vars,
                             from_poly_trait_ref: true,
                         };
                         let result = self.with(scope, |old_scope, this| {
                             this.check_lifetime_params(old_scope, &bound_generic_params);
                             this.visit_ty(&bounded_ty);
-                            this.trait_ref_hack = Some((binders, named_late_bound_vars));
+                            this.trait_ref_hack = Some(bounded_ty.hir_id);
                             walk_list!(this, visit_param_bound, bounds);
                             this.trait_ref_hack = None;
                         });
@@ -1351,7 +1347,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     next_early_index: self.next_early_index(),
                     track_lifetime_uses: true,
                     opaque_type_parent: false,
-                    named_late_bound_vars: 0,
                     from_poly_trait_ref: false,
                 };
                 self.with(scope, |_, this| {
@@ -1389,112 +1384,97 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             .emit();
         }
 
-        let (binders, named_late_bound_vars, lifetimes) =
-            if let Some((mut binders, mut named_late_bound_vars)) = trait_ref_hack.clone() {
-                let initial_binders = named_late_bound_vars;
-                binders.extend(trait_ref.bound_generic_params.iter().filter_map(|param| {
-                    match param.kind {
-                        GenericParamKind::Lifetime { .. } => {
-                            let late_bound_idx = named_late_bound_vars;
-                            named_late_bound_vars += 1;
-                            let region = Region::late(late_bound_idx, &self.tcx.hir(), param).1;
-                            Some(late_region_as_bound_region(self.tcx, &region))
-                        }
-                        GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
-                    }
-                }));
-
-                let mut named_late_bound_vars = initial_binders;
-                let lifetimes: FxHashMap<hir::ParamName, Region> = trait_ref
-                    .bound_generic_params
-                    .iter()
-                    .filter_map(|param| match param.kind {
-                        GenericParamKind::Lifetime { .. } => {
-                            let late_bound_idx = named_late_bound_vars;
-                            named_late_bound_vars += 1;
-                            Some(Region::late(late_bound_idx, &self.tcx.hir(), param))
-                        }
-                        _ => None,
-                    })
-                    .collect();
-
-                (binders, named_late_bound_vars, lifetimes)
-            } else {
-                let mut supertrait_lifetimes = vec![];
-                let mut scope = self.scope;
-                let mut binders = loop {
-                    match scope {
-                        Scope::Body { .. } | Scope::Root => {
-                            break vec![];
-                        }
+        let (binders, lifetimes) = if let Some(hir_id) = trait_ref_hack {
+            let mut binders = self.map.late_bound_vars.entry(hir_id).or_default().clone();
+            let initial_bound_vars = binders.len() as u32;
+            let mut lifetimes: FxHashMap<hir::ParamName, Region> = FxHashMap::default();
+            let binders_iter = trait_ref
+                .bound_generic_params
+                .iter()
+                .filter_map(|param| match param.kind {
+                    GenericParamKind::Lifetime { .. } => Some(param),
+                    _ => None,
+                })
+                .enumerate()
+                .map(|(late_bound_idx, param)| {
+                    let pair = Region::late(
+                        initial_bound_vars + late_bound_idx as u32,
+                        &self.tcx.hir(),
+                        param,
+                    );
+                    let r = late_region_as_bound_region(self.tcx, &pair.1);
+                    lifetimes.insert(pair.0, pair.1);
+                    r
+                });
+            binders.extend(binders_iter);
 
-                        Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => {
-                            scope = s;
-                        }
+            (binders, lifetimes)
+        } else {
+            let mut supertrait_lifetimes = vec![];
+            let mut scope = self.scope;
+            let mut outer_binders = loop {
+                match scope {
+                    Scope::Body { .. } | Scope::Root => {
+                        break vec![];
+                    }
 
-                        Scope::TraitRefHackInner { hir_id, .. } => {
-                            // Nested poly trait refs have the binders concatenated
-                            // If we reach `TraitRefHackInner`, then there is only one more `Binder` above us,
-                            // over all the bounds. We don't want this, since all the lifetimes we care about
-                            // are here anyways.
-                            let mut full_binders =
-                                self.map.late_bound_vars.entry(*hir_id).or_default().clone();
-                            full_binders.extend(supertrait_lifetimes.into_iter());
-                            break full_binders;
-                        }
+                    Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => {
+                        scope = s;
+                    }
 
-                        Scope::Supertrait { s, lifetimes } => {
-                            supertrait_lifetimes = lifetimes.clone();
-                            scope = s;
-                        }
+                    Scope::TraitRefHackInner { hir_id, .. } => {
+                        // Nested poly trait refs have the binders concatenated
+                        // If we reach `TraitRefHackInner`, then there is only one more `Binder` above us,
+                        // over all the bounds. We don't want this, since all the lifetimes we care about
+                        // are here anyways.
+                        let mut full_binders =
+                            self.map.late_bound_vars.entry(*hir_id).or_default().clone();
+                        full_binders.extend(supertrait_lifetimes.into_iter());
+                        break full_binders;
+                    }
 
-                        Scope::Binder { hir_id, from_poly_trait_ref, .. } => {
-                            if !from_poly_trait_ref {
-                                // We should only see super trait lifetimes if there is a `Binder` above
-                                assert!(supertrait_lifetimes.is_empty());
-                                break vec![];
-                            }
-                            // Nested poly trait refs have the binders concatenated
-                            let mut full_binders =
-                                self.map.late_bound_vars.entry(*hir_id).or_default().clone();
-                            full_binders.extend(supertrait_lifetimes.into_iter());
-                            break full_binders;
-                        }
+                    Scope::Supertrait { s, lifetimes } => {
+                        supertrait_lifetimes = lifetimes.clone();
+                        scope = s;
                     }
-                };
-                let mut named_late_bound_vars = binders.len() as u32;
-                let local_binders: Vec<_> = trait_ref
-                    .bound_generic_params
-                    .iter()
-                    .filter_map(|param| match param.kind {
-                        GenericParamKind::Lifetime { .. } => {
-                            let late_bound_idx = named_late_bound_vars;
-                            named_late_bound_vars += 1;
-                            let region = Region::late(late_bound_idx, &self.tcx.hir(), param).1;
-                            Some(late_region_as_bound_region(self.tcx, &region))
-                        }
-                        GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
-                    })
-                    .collect();
 
-                let mut named_late_bound_vars = binders.len() as u32;
-                let lifetimes: FxHashMap<hir::ParamName, Region> = trait_ref
-                    .bound_generic_params
-                    .iter()
-                    .filter_map(|param| match param.kind {
-                        GenericParamKind::Lifetime { .. } => {
-                            let late_bound_idx = named_late_bound_vars;
-                            named_late_bound_vars += 1;
-                            Some(Region::late(late_bound_idx, &self.tcx.hir(), param))
+                    Scope::Binder { hir_id, from_poly_trait_ref, .. } => {
+                        if !from_poly_trait_ref {
+                            // We should only see super trait lifetimes if there is a `Binder` above
+                            assert!(supertrait_lifetimes.is_empty());
+                            break vec![];
                         }
-                        _ => None,
-                    })
-                    .collect();
+                        // Nested poly trait refs have the binders concatenated
+                        let mut full_binders =
+                            self.map.late_bound_vars.entry(*hir_id).or_default().clone();
+                        full_binders.extend(supertrait_lifetimes.into_iter());
+                        break full_binders;
+                    }
+                }
+            };
+            let (lifetimes, local_binders): (FxHashMap<hir::ParamName, Region>, Vec<_>) = trait_ref
+                .bound_generic_params
+                .iter()
+                .filter_map(|param| match param.kind {
+                    GenericParamKind::Lifetime { .. } => Some(param),
+                    _ => None,
+                })
+                .enumerate()
+                .map(|(late_bound_idx, param)| {
+                    let pair = Region::late(
+                        outer_binders.len() as u32 + late_bound_idx as u32,
+                        &self.tcx.hir(),
+                        param,
+                    );
+                    let r = late_region_as_bound_region(self.tcx, &pair.1);
+                    (pair, r)
+                })
+                .unzip();
 
-                binders.extend(local_binders.into_iter());
+            outer_binders.extend(local_binders.into_iter());
 
-                (binders, named_late_bound_vars, lifetimes)
-            };
+            (outer_binders, lifetimes)
+        };
 
         debug!(?binders);
         self.map.late_bound_vars.insert(trait_ref.trait_ref.hir_ref_id, binders);
@@ -1507,7 +1487,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 next_early_index,
                 track_lifetime_uses: true,
                 opaque_type_parent: false,
-                named_late_bound_vars: named_late_bound_vars as u32,
                 from_poly_trait_ref: true,
             };
             self.with(scope, |old_scope, this| {
@@ -1516,11 +1495,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 this.visit_trait_ref(&trait_ref.trait_ref);
             });
         } else {
-            let scope = Scope::TraitRefHackInner {
-                hir_id: trait_ref.trait_ref.hir_ref_id,
-                named_late_bound_vars: named_late_bound_vars as u32,
-                s: self.scope,
-            };
+            let scope =
+                Scope::TraitRefHackInner { hir_id: trait_ref.trait_ref.hir_ref_id, s: self.scope };
             self.with(scope, |_old_scope, this| {
                 this.visit_trait_ref(&trait_ref.trait_ref);
             });
@@ -2234,23 +2210,22 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             .collect();
         let next_early_index = next_early_index + non_lifetime_count;
 
-        let mut named_late_bound_vars = 0;
         let binders: Vec<_> = generics
             .params
             .iter()
             .filter_map(|param| match param.kind {
-                GenericParamKind::Lifetime { .. } => {
-                    if self.map.late_bound.contains(&param.hir_id) {
-                        let late_bound_idx = named_late_bound_vars;
-                        named_late_bound_vars += 1;
-                        let r = Region::late(late_bound_idx, &self.tcx.hir(), param).1;
-                        let r = late_region_as_bound_region(self.tcx, &r);
-                        Some(r)
-                    } else {
-                        None
-                    }
+                GenericParamKind::Lifetime { .. }
+                    if self.map.late_bound.contains(&param.hir_id) =>
+                {
+                    Some(param)
                 }
-                GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
+                _ => None,
+            })
+            .enumerate()
+            .map(|(late_bound_idx, param)| {
+                let pair = Region::late(late_bound_idx as u32, &self.tcx.hir(), param);
+                let r = late_region_as_bound_region(self.tcx, &pair.1);
+                r
             })
             .collect();
         self.map.late_bound_vars.insert(hir_id, binders);
@@ -2261,7 +2236,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             s: self.scope,
             opaque_type_parent: true,
             track_lifetime_uses: false,
-            named_late_bound_vars: named_late_bound_vars as u32,
             from_poly_trait_ref: false,
         };
         self.with(scope, move |old_scope, this| {
@@ -2629,49 +2603,85 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         let has_lifetime_parameter =
             generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
 
-        // Resolve lifetimes found in the type `XX` from `Item = XX` bindings.
+        // Resolve lifetimes found in the bindings, so either in the type `XX` in `Item = XX` or
+        // in the trait ref `YY<...>` in `Item: YY<...>`.
         for binding in generic_args.bindings {
             let scope = Scope::ObjectLifetimeDefault {
                 lifetime: if has_lifetime_parameter { None } else { Some(Region::Static) },
                 s: self.scope,
             };
             if let Some(type_def_id) = type_def_id {
-                let lifetimes =
-                    LifetimeContext::supertrait_bounds(self.tcx, type_def_id, binding.ident);
-                if let Some(lifetimes) = lifetimes {
-                    self.with(scope, |_, this| {
-                        let scope = Scope::Supertrait { lifetimes, s: this.scope };
-                        this.with(scope, |_, this| this.visit_assoc_type_binding(binding));
-                    });
-                } else {
-                    self.with(scope, |_, this| this.visit_assoc_type_binding(binding));
-                }
+                let lifetimes = LifetimeContext::supertrait_hrtb_lifetimes(
+                    self.tcx,
+                    type_def_id,
+                    binding.ident,
+                );
+                self.with(scope, |_, this| {
+                    let scope =
+                        Scope::Supertrait { lifetimes: lifetimes.unwrap_or(vec![]), s: this.scope };
+                    this.with(scope, |_, this| this.visit_assoc_type_binding(binding));
+                });
             } else {
                 self.with(scope, |_, this| this.visit_assoc_type_binding(binding));
             }
         }
     }
 
-    fn trait_defines_associated_type_named(
-        tcx: TyCtxt<'tcx>,
-        trait_def_id: DefId,
-        assoc_name: Ident,
-    ) -> bool {
-        tcx.associated_items(trait_def_id)
-            .find_by_name_and_kind(tcx, assoc_name, ty::AssocKind::Type, trait_def_id)
-            .is_some()
-    }
-
-    fn supertrait_bounds(
+    /// Returns all the late-bound vars that come into scope from supertrait HRTBs, based on the
+    /// associated type name and starting trait.
+    /// For example, imagine we have
+    /// ```rust
+    /// trait Foo<'a, 'b> {
+    ///   type As;
+    /// }
+    /// trait Bar<'b>: for<'a> Foo<'a, 'b> {}
+    /// trait Bar: for<'b> Bar<'b> {}
+    /// ```
+    /// In this case, if we wanted to the supertrait HRTB lifetimes for `As` on
+    /// the starting trait `Bar`, we would return `Some(['b, 'a])`.
+    fn supertrait_hrtb_lifetimes(
         tcx: TyCtxt<'tcx>,
         def_id: DefId,
         assoc_name: Ident,
     ) -> Option<Vec<ty::BoundVariableKind>> {
-        let all_candidates = super::supertraits::supertraits(tcx, def_id);
-        let mut matching_candidates = all_candidates
-            .filter(|r| LifetimeContext::trait_defines_associated_type_named(tcx, r.0, assoc_name));
+        let trait_defines_associated_type_named = |trait_def_id: DefId| {
+            tcx.associated_items(trait_def_id)
+                .find_by_name_and_kind(tcx, assoc_name, ty::AssocKind::Type, trait_def_id)
+                .is_some()
+        };
+
+        use smallvec::{smallvec, SmallVec};
+        let mut stack: SmallVec<[(DefId, SmallVec<[ty::BoundVariableKind; 8]>); 8]> =
+            smallvec![(def_id, smallvec![])];
+        let mut visited: FxHashSet<DefId> = FxHashSet::default();
+        loop {
+            let (def_id, bound_vars) = match stack.pop() {
+                Some(next) => next,
+                None => break None,
+            };
+            if trait_defines_associated_type_named(def_id) {
+                break Some(bound_vars.into_iter().collect());
+            }
+            let predicates =
+                tcx.super_predicates_that_define_assoc_type((def_id, Some(assoc_name)));
+            let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| {
+                let bound_predicate = pred.kind();
+                match bound_predicate.skip_binder() {
+                    ty::PredicateKind::Trait(data, _) => {
+                        // The order here needs to match what we would get from `subst_supertrait`
+                        let pred_bound_vars = bound_predicate.bound_vars();
+                        let mut all_bound_vars = bound_vars.clone();
+                        all_bound_vars.extend(pred_bound_vars.iter());
+                        let super_def_id = data.trait_ref.def_id;
+                        Some((super_def_id, all_bound_vars))
+                    }
+                    _ => None,
+                }
+            });
 
-        matching_candidates.next().map(|c| c.1.into_iter().collect())
+            let obligations = obligations.filter(|o| visited.insert(o.0));
+            stack.extend(obligations);
+        }
     }
 
     #[tracing::instrument(level = "debug", skip(self))]
@@ -2682,13 +2692,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
     ) {
         debug!("visit_fn_like_elision: enter");
         let mut scope = &*self.scope;
-        let (hir_id, named_late_bound_vars) = loop {
+        let hir_id = loop {
             match scope {
-                Scope::Binder { hir_id, named_late_bound_vars, .. }
-                | Scope::TraitRefHackInner { hir_id, named_late_bound_vars, .. } => {
-                    break (*hir_id, *named_late_bound_vars);
+                Scope::Binder { hir_id, .. } | Scope::TraitRefHackInner { hir_id, .. } => {
+                    break *hir_id;
                 }
-                Scope::Body { id, .. } => break (id.hir_id, 0),
+                Scope::Body { id, .. } => break id.hir_id,
                 Scope::ObjectLifetimeDefault { ref s, .. }
                 | Scope::Elision { ref s, .. }
                 | Scope::Supertrait { ref s, .. } => {
@@ -2697,11 +2706,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                 Scope::Root => bug!("In fn_like_elision without appropriate scope above"),
             }
         };
+        // While not strictly necessary, we gather anon lifetimes *before* actually
+        // visiting the argument types.
         let mut gather = GatherAnonLifetimes { anon_count: 0 };
         for input in inputs {
             gather.visit_ty(input);
         }
-        self.map.late_bound_vars.entry(hir_id).or_default().extend(
+        let late_bound_vars = self.map.late_bound_vars.entry(hir_id).or_default();
+        let named_late_bound_vars = late_bound_vars.len() as u32;
+        late_bound_vars.extend(
             (0..gather.anon_count).map(|var| ty::BoundVariableKind::Region(ty::BrAnon(var))),
         );
         let arg_scope = Scope::Elision {
@@ -2987,6 +3000,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             }
 
             fn visit_ty(&mut self, ty: &hir::Ty<'_>) {
+                // If we enter a `BareFn`, then we enter a *new* binding scope
                 if let hir::TyKind::BareFn(_) = ty.kind {
                     return;
                 }
@@ -2998,6 +3012,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                 path_span: Span,
                 generic_args: &'v hir::GenericArgs<'v>,
             ) {
+                // parenthesized args enter a new elison scope
                 if generic_args.parenthesized {
                     return;
                 }
diff --git a/compiler/rustc_resolve/src/late/supertraits.rs b/compiler/rustc_resolve/src/late/supertraits.rs
deleted file mode 100644
index 2130c33bd77..00000000000
--- a/compiler/rustc_resolve/src/late/supertraits.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-use smallvec::{smallvec, SmallVec};
-
-use rustc_data_structures::fx::FxHashSet;
-use rustc_hir::def_id::DefId;
-use rustc_middle::ty::{self, TyCtxt};
-
-pub struct Elaborator<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    stack: SmallVec<[(DefId, SmallVec<[ty::BoundVariableKind; 8]>); 8]>,
-    visited: FxHashSet<DefId>,
-}
-
-#[allow(dead_code)]
-pub fn supertraits<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Elaborator<'tcx> {
-    Elaborator { tcx, stack: smallvec![(def_id, smallvec![])], visited: Default::default() }
-}
-
-impl<'tcx> Elaborator<'tcx> {
-    fn elaborate(&mut self, def_id: DefId, bound_vars: &SmallVec<[ty::BoundVariableKind; 8]>) {
-        let tcx = self.tcx;
-
-        let predicates = tcx.super_predicates_of(def_id);
-        let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| {
-            let bound_predicate = pred.kind();
-            match bound_predicate.skip_binder() {
-                ty::PredicateKind::Trait(data, _) => {
-                    // The order here needs to match what we would get from `subst_supertrait`
-                    let pred_bound_vars = bound_predicate.bound_vars();
-                    let mut all_bound_vars = bound_vars.clone();
-                    all_bound_vars.extend(pred_bound_vars.iter());
-                    let super_def_id = data.trait_ref.def_id;
-                    Some((super_def_id, all_bound_vars))
-                }
-                _ => None,
-            }
-        });
-
-        let visited = &mut self.visited;
-        let obligations = obligations.filter(|o| visited.insert(o.0));
-        self.stack.extend(obligations);
-    }
-}
-
-impl<'tcx> Iterator for Elaborator<'tcx> {
-    type Item = (DefId, SmallVec<[ty::BoundVariableKind; 8]>);
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        (self.stack.len(), None)
-    }
-
-    fn next(&mut self) -> Option<Self::Item> {
-        match self.stack.pop() {
-            Some((def_id, bound_vars)) => {
-                self.elaborate(def_id, &bound_vars);
-                Some((def_id, bound_vars))
-            }
-            None => None,
-        }
-    }
-}
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index cb66dc7e5d9..f54eb0914a5 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -82,7 +82,6 @@ impl<'tcx> AutoTraitFinder<'tcx> {
     ) -> AutoTraitResult<A> {
         let tcx = self.tcx;
 
-        debug_assert!(!ty.has_escaping_bound_vars());
         let trait_ref = ty::TraitRef { def_id: trait_did, substs: tcx.mk_substs_trait(ty, &[]) };
 
         let trait_pred = ty::Binder::dummy(trait_ref);
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 8d55bc8f2f3..b6de491911a 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -2186,13 +2186,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         }
     }
 
+    /// Parses the programmer's textual representation of a type into our
+    /// internal notion of a type.
     pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
         self.ast_ty_to_ty_inner(ast_ty, false)
     }
 
-    /// Parses the programmer's textual representation of a type into our
-    /// internal notion of a type.
-    ///
     /// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait
     /// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors.
     #[tracing::instrument(level = "debug", skip(self))]