about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJack Huey <jack.huey@umassmed.edu>2020-10-05 20:41:46 -0400
committerJack Huey <jack.huey@umassmed.edu>2021-03-31 10:15:27 -0400
commit30187c81f65aa29a53ad7c24fe3b4c7bff947094 (patch)
tree85770181bda5407a809b80846672706ee2e97763
parent62a49c3bb8e0c82ee40b482f08a21a65f90b874b (diff)
downloadrust-30187c81f65aa29a53ad7c24fe3b4c7bff947094.tar.gz
rust-30187c81f65aa29a53ad7c24fe3b4c7bff947094.zip
Track bound vars
-rw-r--r--compiler/rustc_hir/src/hir.rs4
-rw-r--r--compiler/rustc_middle/src/ich/impls_ty.rs1
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs37
-rw-r--r--compiler/rustc_middle/src/ty/context.rs20
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs151
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs14
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs6
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs69
-rw-r--r--compiler/rustc_middle/src/ty/util.rs2
-rw-r--r--compiler/rustc_mir/src/transform/check_consts/validation.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs5
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs2
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs19
-rw-r--r--compiler/rustc_typeck/src/check/closure.rs17
-rw-r--r--compiler/rustc_typeck/src/check/compare_method.rs6
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs2
-rw-r--r--compiler/rustc_typeck/src/check/generator_interior.rs4
-rw-r--r--compiler/rustc_typeck/src/check/intrinsic.rs2
-rw-r--r--compiler/rustc_typeck/src/check/method/confirm.rs2
-rw-r--r--compiler/rustc_typeck/src/check/method/mod.rs2
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs5
-rw-r--r--compiler/rustc_typeck/src/collect.rs34
-rw-r--r--src/librustdoc/clean/mod.rs312
-rw-r--r--src/librustdoc/clean/utils.rs12
-rw-r--r--src/test/ui/hrtb/complex.rs20
-rw-r--r--src/test/ui/specialization/min_specialization/repeated_projection_type.stderr2
-rw-r--r--src/test/ui/symbol-names/basic.legacy.stderr4
-rw-r--r--src/test/ui/symbol-names/impl1.legacy.stderr36
-rw-r--r--src/test/ui/symbol-names/impl1.rs3
-rw-r--r--src/test/ui/symbol-names/impl1.v0.stderr24
-rw-r--r--src/test/ui/symbol-names/issue-60925.legacy.stderr4
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs10
33 files changed, 479 insertions, 363 deletions
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 03af81ae02a..4ff5c0a678e 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -314,12 +314,12 @@ pub struct GenericArgs<'hir> {
     pub parenthesized: bool,
 }
 
-impl GenericArgs<'_> {
+impl<'tcx> GenericArgs<'tcx> {
     pub const fn none() -> Self {
         Self { args: &[], bindings: &[], parenthesized: false }
     }
 
-    pub fn inputs(&self) -> &[Ty<'_>] {
+    pub fn inputs(&self) -> &[Ty<'tcx>] {
         if self.parenthesized {
             for arg in self.args {
                 match arg {
diff --git a/compiler/rustc_middle/src/ich/impls_ty.rs b/compiler/rustc_middle/src/ich/impls_ty.rs
index 60b1564d4c5..c39ea5825a7 100644
--- a/compiler/rustc_middle/src/ich/impls_ty.rs
+++ b/compiler/rustc_middle/src/ich/impls_ty.rs
@@ -124,6 +124,7 @@ where
 {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         self.as_ref().skip_binder().hash_stable(hcx, hasher);
+        self.bound_vars().hash_stable(hcx, hasher);
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 3a38f0c8521..d7767dc39cb 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -122,6 +122,7 @@ impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for Ty<'tcx> {
 
 impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Binder<'tcx, ty::PredicateKind<'tcx>> {
     fn encode(&self, e: &mut E) -> Result<(), E::Error> {
+        self.bound_vars().encode(e)?;
         encode_with_shorthand(e, &self.skip_binder(), TyEncoder::predicate_shorthands)
     }
 }
@@ -228,16 +229,20 @@ impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for Ty<'tcx> {
 
 impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Binder<'tcx, ty::PredicateKind<'tcx>> {
     fn decode(decoder: &mut D) -> Result<ty::Binder<'tcx, ty::PredicateKind<'tcx>>, D::Error> {
+        let bound_vars = Decodable::decode(decoder)?;
         // Handle shorthands first, if we have an usize > 0x80.
-        Ok(ty::Binder::bind(if decoder.positioned_at_shorthand() {
-            let pos = decoder.read_usize()?;
-            assert!(pos >= SHORTHAND_OFFSET);
-            let shorthand = pos - SHORTHAND_OFFSET;
-
-            decoder.with_position(shorthand, ty::PredicateKind::decode)?
-        } else {
-            ty::PredicateKind::decode(decoder)?
-        }))
+        Ok(ty::Binder::bind_with_vars(
+            if decoder.positioned_at_shorthand() {
+                let pos = decoder.read_usize()?;
+                assert!(pos >= SHORTHAND_OFFSET);
+                let shorthand = pos - SHORTHAND_OFFSET;
+
+                decoder.with_position(shorthand, ty::PredicateKind::decode)?
+            } else {
+                ty::PredicateKind::decode(decoder)?
+            },
+            bound_vars,
+        ))
     }
 }
 
@@ -379,6 +384,13 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::N
     }
 }
 
+impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<ty::BoundVariableKind> {
+    fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
+        let len = decoder.read_usize()?;
+        Ok(decoder.tcx().mk_bound_variable_kinds((0..len).map(|_| Decodable::decode(decoder)))?)
+    }
+}
+
 impl_decodable_via_ref! {
     &'tcx ty::TypeckResults<'tcx>,
     &'tcx ty::List<Ty<'tcx>>,
@@ -387,7 +399,8 @@ impl_decodable_via_ref! {
     &'tcx mir::Body<'tcx>,
     &'tcx mir::UnsafetyCheckResult,
     &'tcx mir::BorrowCheckResult<'tcx>,
-    &'tcx mir::coverage::CodeRegion
+    &'tcx mir::coverage::CodeRegion,
+    &'tcx ty::List<ty::BoundVariableKind>
 }
 
 #[macro_export]
@@ -490,12 +503,14 @@ macro_rules! impl_binder_encode_decode {
         $(
             impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Binder<'tcx, $t> {
                 fn encode(&self, e: &mut E) -> Result<(), E::Error> {
+                    self.bound_vars().encode(e)?;
                     self.as_ref().skip_binder().encode(e)
                 }
             }
             impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Binder<'tcx, $t> {
                 fn decode(decoder: &mut D) -> Result<Self, D::Error> {
-                    Ok(ty::Binder::bind(Decodable::decode(decoder)?))
+                    let bound_vars = Decodable::decode(decoder)?;
+                    Ok(ty::Binder::bind_with_vars(Decodable::decode(decoder)?, bound_vars))
                 }
             }
         )*
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index a7c05b42755..1f1840c0e4a 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -96,6 +96,7 @@ pub struct CtxtInterners<'tcx> {
     const_: InternedSet<'tcx, Const<'tcx>>,
     /// Const allocations.
     allocation: InternedSet<'tcx, Allocation>,
+    bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
 }
 
 impl<'tcx> CtxtInterners<'tcx> {
@@ -114,6 +115,7 @@ impl<'tcx> CtxtInterners<'tcx> {
             place_elems: Default::default(),
             const_: Default::default(),
             allocation: Default::default(),
+            bound_variable_kinds: Default::default(),
         }
     }
 
@@ -1624,6 +1626,7 @@ nop_list_lift! {poly_existential_predicates; ty::Binder<'a, ExistentialPredicate
 nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>}
 nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>}
 nop_list_lift! {projs; ProjectionKind => ProjectionKind}
+nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind}
 
 // This is the impl for `&'a InternalSubsts<'a>`.
 nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}
@@ -2080,6 +2083,7 @@ slice_interners!(
     predicates: _intern_predicates(Predicate<'tcx>),
     projs: _intern_projs(ProjectionKind),
     place_elems: _intern_place_elems(PlaceElem<'tcx>),
+    bound_variable_kinds: _intern_bound_variable_kinds(ty::BoundVariableKind),
 );
 
 impl<'tcx> TyCtxt<'tcx> {
@@ -2516,6 +2520,13 @@ impl<'tcx> TyCtxt<'tcx> {
         if ts.is_empty() { List::empty() } else { self._intern_canonical_var_infos(ts) }
     }
 
+    pub fn intern_bound_variable_kinds(
+        self,
+        ts: &[ty::BoundVariableKind],
+    ) -> &'tcx List<ty::BoundVariableKind> {
+        if ts.is_empty() { List::empty() } else { self._intern_bound_variable_kinds(ts) }
+    }
+
     pub fn mk_fn_sig<I>(
         self,
         inputs: I,
@@ -2576,6 +2587,15 @@ impl<'tcx> TyCtxt<'tcx> {
         self.mk_substs(iter::once(self_ty.into()).chain(rest.iter().cloned()))
     }
 
+    pub fn mk_bound_variable_kinds<
+        I: InternAs<[ty::BoundVariableKind], &'tcx List<ty::BoundVariableKind>>,
+    >(
+        self,
+        iter: I,
+    ) -> I::Output {
+        iter.intern_with(|xs| self.intern_bound_variable_kinds(xs))
+    }
+
     /// Walks upwards from `id` to find a node which might change lint levels with attributes.
     /// It stops at `bound` and just returns it if reached.
     pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId {
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index fe26314ae2f..32101b4c8c9 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -35,6 +35,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 
 use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::sso::SsoHashSet;
 use std::collections::BTreeMap;
 use std::fmt;
 use std::ops::ControlFlow;
@@ -702,10 +703,109 @@ impl<'tcx> TyCtxt<'tcx> {
                 r
             })
             .0,
+            self,
         )
     }
 }
 
+pub struct BoundVarsCollector<'tcx> {
+    binder_index: ty::DebruijnIndex,
+    vars: BTreeMap<u32, ty::BoundVariableKind>,
+    // We may encounter the same variable at different levels of binding, so
+    // this can't just be `Ty`
+    visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>,
+}
+
+impl<'tcx> BoundVarsCollector<'tcx> {
+    pub fn new() -> Self {
+        BoundVarsCollector {
+            binder_index: ty::INNERMOST,
+            vars: BTreeMap::new(),
+            visited: SsoHashSet::default(),
+        }
+    }
+
+    pub fn into_vars(self, tcx: TyCtxt<'tcx>) -> &'tcx ty::List<ty::BoundVariableKind> {
+        let max = self.vars.iter().map(|(k, _)| *k).max().unwrap_or_else(|| 0);
+        for i in 0..max {
+            if let None = self.vars.get(&i) {
+                panic!("Unknown variable: {:?}", i);
+            }
+        }
+
+        tcx.mk_bound_variable_kinds(self.vars.into_iter().map(|(_, v)| v))
+    }
+}
+
+impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
+    type BreakTy = ();
+
+    fn visit_binder<T: TypeFoldable<'tcx>>(
+        &mut self,
+        t: &Binder<'tcx, T>,
+    ) -> ControlFlow<Self::BreakTy> {
+        self.binder_index.shift_in(1);
+        let result = t.super_visit_with(self);
+        self.binder_index.shift_out(1);
+        result
+    }
+
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+        if t.outer_exclusive_binder < self.binder_index
+            || !self.visited.insert((self.binder_index, t))
+        {
+            return ControlFlow::CONTINUE;
+        }
+        use std::collections::btree_map::Entry;
+        match *t.kind() {
+            ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
+                match self.vars.entry(bound_ty.var.as_u32()) {
+                    Entry::Vacant(entry) => {
+                        entry.insert(ty::BoundVariableKind::Ty(bound_ty.kind));
+                    }
+                    Entry::Occupied(entry) => match entry.get() {
+                        ty::BoundVariableKind::Ty(_) => {}
+                        _ => bug!("Conflicting bound vars"),
+                    },
+                }
+            }
+
+            _ => (),
+        };
+
+        t.super_visit_with(self)
+    }
+
+    fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+        use std::collections::btree_map::Entry;
+        match r {
+            ty::ReLateBound(index, br) if *index == self.binder_index => match br.kind {
+                ty::BrNamed(_def_id, _name) => {
+                    // FIXME
+                }
+
+                ty::BrAnon(var) => match self.vars.entry(var) {
+                    Entry::Vacant(entry) => {
+                        entry.insert(ty::BoundVariableKind::Region(br.kind));
+                    }
+                    Entry::Occupied(entry) => match entry.get() {
+                        ty::BoundVariableKind::Region(_) => {}
+                        _ => bug!("Conflicting bound vars"),
+                    },
+                },
+
+                ty::BrEnv => {
+                    // FIXME
+                }
+            },
+
+            _ => (),
+        };
+
+        r.super_visit_with(self)
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // Shifter
 //
@@ -907,57 +1007,6 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
 struct FoundFlags;
 
-crate struct CountBoundVars {
-    crate outer_index: ty::DebruijnIndex,
-    crate bound_tys: FxHashSet<ty::BoundTy>,
-    crate bound_regions: FxHashSet<ty::BoundRegion>,
-    crate bound_consts: FxHashSet<ty::BoundVar>,
-}
-
-impl<'tcx> TypeVisitor<'tcx> for CountBoundVars {
-    type BreakTy = ();
-
-    fn visit_binder<T: TypeFoldable<'tcx>>(
-        &mut self,
-        t: &Binder<'tcx, T>,
-    ) -> ControlFlow<Self::BreakTy> {
-        self.outer_index.shift_in(1);
-        let result = t.super_visit_with(self);
-        self.outer_index.shift_out(1);
-        result
-    }
-
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-        match t.kind {
-            ty::Bound(debruijn, ty) if debruijn == self.outer_index => {
-                self.bound_tys.insert(ty);
-                ControlFlow::CONTINUE
-            }
-            _ => t.super_visit_with(self),
-        }
-    }
-
-    fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
-        match r {
-            ty::ReLateBound(debruijn, re) if *debruijn == self.outer_index => {
-                self.bound_regions.insert(*re);
-                ControlFlow::CONTINUE
-            }
-            _ => r.super_visit_with(self),
-        }
-    }
-
-    fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
-        match ct.val {
-            ty::ConstKind::Bound(debruijn, c) if debruijn == self.outer_index => {
-                self.bound_consts.insert(c);
-                ControlFlow::CONTINUE
-            }
-            _ => ct.super_visit_with(self),
-        }
-    }
-}
-
 // FIXME: Optimize for checking for infer flags
 struct HasTypeFlagsVisitor {
     flags: ty::TypeFlags,
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 29f82b47305..a09573fac02 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -67,12 +67,12 @@ pub use self::sty::BoundRegionKind::*;
 pub use self::sty::RegionKind::*;
 pub use self::sty::TyKind::*;
 pub use self::sty::{
-    Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, CanonicalPolyFnSig,
-    ClosureSubsts, ClosureSubstsParts, ConstVid, EarlyBoundRegion, ExistentialPredicate,
-    ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig, GeneratorSubsts,
-    GeneratorSubstsParts, ParamConst, ParamTy, PolyExistentialProjection, PolyExistentialTraitRef,
-    PolyFnSig, PolyGenSig, PolyTraitRef, ProjectionTy, Region, RegionKind, RegionVid, TraitRef,
-    TyKind, TypeAndMut, UpvarSubsts,
+    Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, BoundVariableKind,
+    CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid, EarlyBoundRegion,
+    ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig,
+    GeneratorSubsts, GeneratorSubstsParts, ParamConst, ParamTy, PolyExistentialProjection,
+    PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, ProjectionTy, Region, RegionKind,
+    RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts,
 };
 pub use self::trait_def::TraitDef;
 
@@ -546,7 +546,7 @@ impl<'tcx> Predicate<'tcx> {
         let substs = trait_ref.skip_binder().substs;
         let pred = self.kind().skip_binder();
         let new = pred.subst(tcx, substs);
-        tcx.reuse_or_mk_predicate(self, ty::Binder::bind(new))
+        tcx.reuse_or_mk_predicate(self, ty::Binder::bind(new, tcx))
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index dd4bb029747..a969626b370 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -460,8 +460,10 @@ where
 {
     type Lifted = ty::Binder<'tcx, T::Lifted>;
     fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        // FIXME: need to lift inner values
-        tcx.lift(self.skip_binder()).map(|v| ty::Binder::bind(v))
+        let bound_vars = tcx.lift(self.bound_vars());
+        tcx.lift(self.skip_binder())
+            .zip(bound_vars)
+            .map(|(value, vars)| ty::Binder::bind_with_vars(value, vars))
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index c6d72e78df8..1884df0c67b 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -5,6 +5,7 @@
 use self::TyKind::*;
 
 use crate::infer::canonical::Canonical;
+use crate::ty::fold::BoundVarsCollector;
 use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
 use crate::ty::InferTy::{self, *};
 use crate::ty::{
@@ -947,6 +948,14 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> {
     }
 }
 
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
+#[derive(HashStable)]
+pub enum BoundVariableKind {
+    Ty(BoundTyKind),
+    Region(BoundRegionKind),
+    Const,
+}
+
 /// Binder is a binder for higher-ranked lifetimes or types. It is part of the
 /// compiler's representation for things like `for<'a> Fn(&'a isize)`
 /// (which would be represented by the type `PolyTraitRef ==
@@ -957,7 +966,7 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> {
 ///
 /// `Decodable` and `Encodable` are implemented for `Binder<T>` using the `impl_binder_encode_decode!` macro.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
-pub struct Binder<'tcx, T>(T, u32, std::marker::PhantomData<&'tcx ()>);
+pub struct Binder<'tcx, T>(T, &'tcx List<BoundVariableKind>);
 
 impl<'tcx, T> Binder<'tcx, T>
 where
@@ -969,48 +978,22 @@ where
     /// different binding level.
     pub fn dummy(value: T) -> Binder<'tcx, T> {
         debug_assert!(!value.has_escaping_bound_vars());
-        Binder(value, 0, std::marker::PhantomData)
+        Binder(value, ty::List::empty())
     }
 
     /// Wraps `value` in a binder, binding higher-ranked vars (if any).
-    pub fn bind(value: T) -> Binder<'tcx, T> {
-        use crate::ty::fold::CountBoundVars;
-        use rustc_data_structures::fx::FxHashSet;
-        let mut counter = CountBoundVars {
-            outer_index: ty::INNERMOST,
-            bound_tys: FxHashSet::default(),
-            bound_regions: FxHashSet::default(),
-            bound_consts: FxHashSet::default(),
-        };
-        value.visit_with(&mut counter);
-        let bound_tys = counter.bound_tys.len();
-        let bound_regions = if !counter.bound_regions.is_empty() {
-            let mut env = false;
-            let mut anons = FxHashSet::default();
-            let mut named = FxHashSet::default();
-            for br in counter.bound_regions {
-                match br.kind {
-                    ty::BrAnon(idx) => {
-                        anons.insert(idx);
-                    }
-                    ty::BrNamed(def_id, _) => {
-                        named.insert(def_id);
-                    }
-                    ty::BrEnv => env = true,
-                }
-            }
-            (if env { 1 } else { 0 }) + anons.len() + named.len()
-        } else {
-            0
-        };
-        let bound_consts = counter.bound_consts.len();
-
-        let bound_vars = bound_tys + bound_regions + bound_consts;
-        Binder(value, bound_vars as u32, std::marker::PhantomData)
+    pub fn bind(value: T, tcx: TyCtxt<'tcx>) -> Binder<'tcx, T> {
+        let mut collector = BoundVarsCollector::new();
+        value.visit_with(&mut collector);
+        Binder(value, collector.into_vars(tcx))
     }
 }
 
 impl<'tcx, T> Binder<'tcx, T> {
+    pub fn bind_with_vars(value: T, vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> {
+        Binder(value, vars)
+    }
+
     /// Skips the binder and returns the "bound" value. This is a
     /// risky thing to do because it's easy to get confused about
     /// De Bruijn indices and the like. It is usually better to
@@ -1031,12 +1014,12 @@ impl<'tcx, T> Binder<'tcx, T> {
         self.0
     }
 
-    pub fn bound_vars(&self) -> u32 {
+    pub fn bound_vars(&self) -> &'tcx List<BoundVariableKind> {
         self.1
     }
 
     pub fn as_ref(&self) -> Binder<'tcx, &T> {
-        Binder(&self.0, self.1, std::marker::PhantomData)
+        Binder(&self.0, self.1)
     }
 
     pub fn map_bound_ref<F, U>(&self, f: F) -> Binder<'tcx, U>
@@ -1050,7 +1033,7 @@ impl<'tcx, T> Binder<'tcx, T> {
     where
         F: FnOnce(T) -> U,
     {
-        Binder(f(self.0), self.1, std::marker::PhantomData)
+        Binder(f(self.0), self.1)
     }
 
     /// Wraps a `value` in a binder, using the same bound variables as the
@@ -1063,7 +1046,7 @@ impl<'tcx, T> Binder<'tcx, T> {
     /// because bound vars aren't allowed to change here, whereas they are
     /// in `bind`. This may be (debug) asserted in the future.
     pub fn rebind<U>(&self, value: U) -> Binder<'tcx, U> {
-        Binder(value, self.1, std::marker::PhantomData)
+        Binder(value, self.1)
     }
 
     /// Unwraps and returns the value within, but only if it contains
@@ -1094,7 +1077,7 @@ impl<'tcx, T> Binder<'tcx, T> {
     where
         F: FnOnce(T, U) -> R,
     {
-        Binder(f(self.0, u.0), self.1, std::marker::PhantomData)
+        Binder(f(self.0, u.0), self.1)
     }
 
     /// Splits the contents into two things that share the same binder
@@ -1108,14 +1091,14 @@ impl<'tcx, T> Binder<'tcx, T> {
         F: FnOnce(T) -> (U, V),
     {
         let (u, v) = f(self.0);
-        (Binder(u, self.1, std::marker::PhantomData), Binder(v, self.1, std::marker::PhantomData))
+        (Binder(u, self.1), Binder(v, self.1))
     }
 }
 
 impl<'tcx, T> Binder<'tcx, Option<T>> {
     pub fn transpose(self) -> Option<Binder<'tcx, T>> {
         let bound_vars = self.1;
-        self.0.map(|v| Binder(v, bound_vars, std::marker::PhantomData))
+        self.0.map(|v| Binder(v, bound_vars))
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index be9ba56f097..93fbc1f53b2 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -510,7 +510,7 @@ impl<'tcx> TyCtxt<'tcx> {
             ty::ClosureKind::FnMut => self.mk_mut_ref(self.mk_region(env_region), closure_ty),
             ty::ClosureKind::FnOnce => closure_ty,
         };
-        Some(ty::Binder::bind(env_ty))
+        Some(ty::Binder::bind(env_ty, self))
     }
 
     /// Returns `true` if the node pointed to by `def_id` is a `static` item.
diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs
index 1ad7b8fbbd5..ce5e41d3e7c 100644
--- a/compiler/rustc_mir/src/transform/check_consts/validation.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs
@@ -850,9 +850,12 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
                     let obligation = Obligation::new(
                         ObligationCause::dummy(),
                         param_env,
-                        Binder::bind(TraitPredicate {
-                            trait_ref: TraitRef::from_method(tcx, trait_id, substs),
-                        }),
+                        Binder::bind(
+                            TraitPredicate {
+                                trait_ref: TraitRef::from_method(tcx, trait_id, substs),
+                            },
+                            tcx,
+                        ),
                     );
 
                     let implsrc = tcx.infer_ctxt().enter(|infcx| {
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 79f65669479..fc9739f70d4 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -684,7 +684,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
 /// Returns the set of inference variables contained in `substs`.
 fn substs_infer_vars<'a, 'tcx>(
     selcx: &mut SelectionContext<'a, 'tcx>,
-    substs: ty::Binder<SubstsRef<'tcx>>,
+    substs: ty::Binder<'tcx, SubstsRef<'tcx>>,
 ) -> impl Iterator<Item = TyOrConstInferVar<'tcx>> {
     selcx
         .infcx()
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 0af6d645915..b3e5df4da0a 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1275,6 +1275,9 @@ fn confirm_discriminant_kind_candidate<'cx, 'tcx>(
     let tcx = selcx.tcx();
 
     let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty());
+    // We get here from `poly_project_and_unify_type` which replaces bound vars
+    // with placeholders
+    debug_assert!(!self_ty.has_escaping_bound_vars());
     let substs = tcx.mk_substs([self_ty.into()].iter());
 
     let discriminant_def_id = tcx.require_lang_item(LangItem::Discriminant, None);
@@ -1306,7 +1309,7 @@ fn confirm_pointee_candidate<'cx, 'tcx>(
         ty: self_ty.ptr_metadata_ty(tcx),
     };
 
-    confirm_param_env_candidate(selcx, obligation, ty::Binder::bind(predicate), false)
+    confirm_param_env_candidate(selcx, obligation, ty::Binder::bind(predicate, tcx), false)
 }
 
 fn confirm_fn_pointer_candidate<'cx, 'tcx>(
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 6b9d46ee0af..874289d0293 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -115,7 +115,7 @@ fn resolve_associated_item<'tcx>(
     );
 
     let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
-    let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref)))?;
+    let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref, tcx)))?;
 
     // Now that we know which impl is being used, we can dispatch to
     // the actual function:
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 1e194771709..48f2bf1518b 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -658,7 +658,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             self_ty,
             trait_ref.path.segments.last().unwrap(),
         );
-        let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs));
+        let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs), self.tcx());
 
         bounds.trait_bounds.push((poly_trait_ref, span, constness));
 
@@ -741,7 +741,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             false,
             Some(self_ty),
         );
-        let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs));
+        let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs), self.tcx());
         bounds.trait_bounds.push((poly_trait_ref, span, Constness::NotConst));
 
         let mut dup_bindings = FxHashMap::default();
@@ -878,9 +878,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     .instantiate_lang_item_trait_ref(
                         *lang_item, *span, *hir_id, args, param_ty, bounds,
                     ),
-                hir::GenericBound::Outlives(ref l) => bounds
-                    .region_bounds
-                    .push((ty::Binder::bind(self.ast_region_to_region(l, None)), l.span)),
+                hir::GenericBound::Outlives(ref l) => bounds.region_bounds.push((
+                    ty::Binder::bind(self.ast_region_to_region(l, None), self.tcx()),
+                    l.span,
+                )),
             }
         }
     }
@@ -1664,7 +1665,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 };
 
                 self.one_bound_for_assoc_type(
-                    || traits::supertraits(tcx, ty::Binder::bind(trait_ref)),
+                    || traits::supertraits(tcx, ty::Binder::bind(trait_ref, tcx)),
                     || "Self".to_string(),
                     assoc_ident,
                     span,
@@ -2368,8 +2369,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         debug!("ty_of_fn: output_ty={:?}", output_ty);
 
-        let bare_fn_ty =
-            ty::Binder::bind(tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi));
+        let bare_fn_ty = ty::Binder::bind(
+            tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi),
+            tcx,
+        );
 
         if !self.allow_ty_infer() {
             // We always collect the spans for placeholder types when evaluating `fn`s, but we
diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs
index 4099ecd435d..2f30621b019 100644
--- a/compiler/rustc_typeck/src/check/closure.rs
+++ b/compiler/rustc_typeck/src/check/closure.rs
@@ -571,13 +571,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             },
         };
 
-        let result = ty::Binder::bind(self.tcx.mk_fn_sig(
-            supplied_arguments,
-            supplied_return,
-            decl.c_variadic,
-            hir::Unsafety::Normal,
-            Abi::RustCall,
-        ));
+        let result = ty::Binder::bind(
+            self.tcx.mk_fn_sig(
+                supplied_arguments,
+                supplied_return,
+                decl.c_variadic,
+                hir::Unsafety::Normal,
+                Abi::RustCall,
+            ),
+            self.tcx,
+        );
 
         debug!("supplied_sig_of_closure: result={:?}", result);
 
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index 70f850084a8..f044daa4509 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -225,7 +225,7 @@ fn compare_predicate_entailment<'tcx>(
         let (impl_m_own_bounds, _) = infcx.replace_bound_vars_with_fresh_vars(
             impl_m_span,
             infer::HigherRankedType,
-            ty::Binder::bind(impl_m_own_bounds.predicates),
+            ty::Binder::bind(impl_m_own_bounds.predicates, tcx),
         );
         for predicate in impl_m_own_bounds {
             let traits::Normalized { value: predicate, obligations } =
@@ -258,14 +258,14 @@ fn compare_predicate_entailment<'tcx>(
         );
         let impl_sig =
             inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, impl_sig);
-        let impl_fty = tcx.mk_fn_ptr(ty::Binder::bind(impl_sig));
+        let impl_fty = tcx.mk_fn_ptr(ty::Binder::bind(impl_sig, tcx));
         debug!("compare_impl_method: impl_fty={:?}", impl_fty);
 
         let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(trait_m.def_id));
         let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs);
         let trait_sig =
             inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, trait_sig);
-        let trait_fty = tcx.mk_fn_ptr(ty::Binder::bind(trait_sig));
+        let trait_fty = tcx.mk_fn_ptr(ty::Binder::bind(trait_sig, tcx));
 
         debug!("compare_impl_method: trait_fty={:?}", trait_fty);
 
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
index bd89c7274e7..b940e90fadb 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
@@ -486,7 +486,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let found = self.resolve_vars_with_obligations(found);
         if let hir::FnRetTy::Return(ty) = fn_decl.output {
             let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, ty);
-            let ty = self.tcx.erase_late_bound_regions(Binder::bind(ty));
+            let ty = self.tcx.erase_late_bound_regions(Binder::bind(ty, self.tcx));
             let ty = self.normalize_associated_types_in(expr.span, ty);
             if self.can_coerce(found, ty) {
                 err.multipart_suggestion(
diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs
index 91708465b3f..969359a3c21 100644
--- a/compiler/rustc_typeck/src/check/generator_interior.rs
+++ b/compiler/rustc_typeck/src/check/generator_interior.rs
@@ -202,11 +202,11 @@ pub fn resolve_interior<'a, 'tcx>(
 
     // Extract type components to build the witness type.
     let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty));
-    let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list));
+    let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list, fcx.tcx));
 
     // Store the generator types and spans into the typeck results for this generator.
     visitor.fcx.inh.typeck_results.borrow_mut().generator_interior_types =
-        ty::Binder::bind(type_causes);
+        ty::Binder::bind(type_causes, fcx.tcx);
 
     debug!(
         "types in generator after region replacement {:?}, span = {:?}",
diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs
index 990ed5abdbf..3b399b86718 100644
--- a/compiler/rustc_typeck/src/check/intrinsic.rs
+++ b/compiler/rustc_typeck/src/check/intrinsic.rs
@@ -366,7 +366,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
         (n_tps, inputs, output, unsafety)
     };
     let sig = tcx.mk_fn_sig(inputs.into_iter(), output, false, unsafety, Abi::RustIntrinsic);
-    let sig = ty::Binder::bind(sig);
+    let sig = ty::Binder::bind(sig, tcx);
     equate_intrinsic_type(tcx, it, n_tps, sig)
 }
 
diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs
index 901a874980d..900bd2885fd 100644
--- a/compiler/rustc_typeck/src/check/method/confirm.rs
+++ b/compiler/rustc_typeck/src/check/method/confirm.rs
@@ -119,7 +119,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         // We won't add these if we encountered an illegal sized bound, so that we can use
         // a custom error in that case.
         if illegal_sized_bound.is_none() {
-            let method_ty = self.tcx.mk_fn_ptr(ty::Binder::bind(method_sig));
+            let method_ty = self.tcx.mk_fn_ptr(ty::Binder::bind(method_sig, self.tcx));
             self.add_obligations(method_ty, all_substs, method_predicates);
         }
 
diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs
index c74fd25f76d..bd7ffd057b4 100644
--- a/compiler/rustc_typeck/src/check/method/mod.rs
+++ b/compiler/rustc_typeck/src/check/method/mod.rs
@@ -399,7 +399,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         obligations.extend(traits::predicates_for_generics(cause.clone(), self.param_env, bounds));
 
         // Also add an obligation for the method type being well-formed.
-        let method_ty = tcx.mk_fn_ptr(ty::Binder::bind(fn_sig));
+        let method_ty = tcx.mk_fn_ptr(ty::Binder::bind(fn_sig, tcx));
         debug!(
             "lookup_in_trait_adjusted: matched method method_ty={:?} obligation={:?}",
             method_ty, obligation
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index e7e603c8bd5..887cc42a1dd 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -1067,13 +1067,14 @@ fn check_method_receiver<'fcx, 'tcx>(
     debug!("check_method_receiver: sig={:?}", sig);
 
     let self_ty = fcx.normalize_associated_types_in(span, self_ty);
-    let self_ty = fcx.tcx.liberate_late_bound_regions(method.def_id, ty::Binder::bind(self_ty));
+    let self_ty =
+        fcx.tcx.liberate_late_bound_regions(method.def_id, ty::Binder::bind(self_ty, fcx.tcx));
 
     let receiver_ty = sig.inputs()[0];
 
     let receiver_ty = fcx.normalize_associated_types_in(span, receiver_ty);
     let receiver_ty =
-        fcx.tcx.liberate_late_bound_regions(method.def_id, ty::Binder::bind(receiver_ty));
+        fcx.tcx.liberate_late_bound_regions(method.def_id, ty::Binder::bind(receiver_ty, fcx.tcx));
 
     if fcx.tcx.features().arbitrary_self_types {
         if !receiver_is_valid(fcx, span, receiver_ty, self_ty, true) {
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 0ef5f4d1c18..b42ef7efcbc 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -1707,7 +1707,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
                     }
                     diag.emit();
 
-                    ty::Binder::bind(fn_sig)
+                    ty::Binder::bind(fn_sig, tcx)
                 }
                 None => <dyn AstConv<'_>>::ty_of_fn(
                     &icx,
@@ -1749,13 +1749,10 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
             let ty = tcx.type_of(tcx.hir().get_parent_did(hir_id).to_def_id());
             let inputs =
                 data.fields().iter().map(|f| tcx.type_of(tcx.hir().local_def_id(f.hir_id)));
-            ty::Binder::bind(tcx.mk_fn_sig(
-                inputs,
-                ty,
-                false,
-                hir::Unsafety::Normal,
-                abi::Abi::Rust,
-            ))
+            ty::Binder::bind(
+                tcx.mk_fn_sig(inputs, ty, false, hir::Unsafety::Normal, abi::Abi::Rust),
+                tcx,
+            )
         }
 
         Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => {
@@ -2039,7 +2036,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
                 param.bounds.iter().for_each(|bound| match bound {
                     hir::GenericBound::Outlives(lt) => {
                         let bound = <dyn AstConv<'_>>::ast_region_to_region(&icx, &lt, None);
-                        let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound));
+                        let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound), tcx);
                         predicates.insert((outlives.to_predicate(tcx), lt.span));
                     }
                     _ => bug!(),
@@ -2099,9 +2096,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
                     } else {
                         let span = bound_pred.bounded_ty.span;
                         let re_root_empty = tcx.lifetimes.re_root_empty;
-                        let predicate = ty::Binder::bind(ty::PredicateKind::TypeOutlives(
-                            ty::OutlivesPredicate(ty, re_root_empty),
-                        ));
+                        let predicate = ty::Binder::bind(
+                            ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(
+                                ty,
+                                re_root_empty,
+                            )),
+                            tcx,
+                        );
                         predicates.insert((predicate.to_predicate(tcx), span));
                     }
                 }
@@ -2144,9 +2145,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
                             let region =
                                 <dyn AstConv<'_>>::ast_region_to_region(&icx, lifetime, None);
                             predicates.insert((
-                                ty::Binder::bind(ty::PredicateKind::TypeOutlives(
-                                    ty::OutlivesPredicate(ty, region),
-                                ))
+                                ty::Binder::bind(
+                                    ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(
+                                        ty, region,
+                                    )),
+                                    tcx,
+                                )
                                 .to_predicate(tcx),
                                 lifetime.span,
                             ));
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 4d33a1e6961..dac42058b1b 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -48,42 +48,42 @@ crate use self::types::Type::*;
 crate use self::types::Visibility::{Inherited, Public};
 crate use self::types::*;
 
-crate trait Clean<T> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> T;
+crate trait Clean<'tcx, T> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> T;
 }
 
-impl<T: Clean<U>, U> Clean<Vec<U>> for [T] {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Vec<U> {
+impl<'tcx, T: Clean<'tcx, U>, U> Clean<'tcx, Vec<U>> for [T] {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Vec<U> {
         self.iter().map(|x| x.clean(cx)).collect()
     }
 }
 
-impl<T: Clean<U>, U, V: Idx> Clean<IndexVec<V, U>> for IndexVec<V, T> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> IndexVec<V, U> {
+impl<'tcx, T: Clean<'tcx, U>, U, V: Idx> Clean<'tcx, IndexVec<V, U>> for IndexVec<V, T> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> IndexVec<V, U> {
         self.iter().map(|x| x.clean(cx)).collect()
     }
 }
 
-impl<T: Clean<U>, U> Clean<U> for &T {
-    fn clean(&self, cx: &mut DocContext<'_>) -> U {
+impl<'tcx, T: Clean<'tcx, U>, U> Clean<'tcx, U> for &T {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> U {
         (**self).clean(cx)
     }
 }
 
-impl<T: Clean<U>, U> Clean<U> for Rc<T> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> U {
+impl<'tcx, T: Clean<'tcx, U>, U> Clean<'tcx, U> for Rc<T> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> U {
         (**self).clean(cx)
     }
 }
 
-impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Option<U> {
+impl<'tcx, T: Clean<'tcx, U>, U> Clean<'tcx, Option<U>> for Option<T> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Option<U> {
         self.as_ref().map(|v| v.clean(cx))
     }
 }
 
-impl Clean<ExternalCrate> for CrateNum {
-    fn clean(&self, cx: &mut DocContext<'_>) -> ExternalCrate {
+impl<'tcx> Clean<'tcx, ExternalCrate> for CrateNum {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> ExternalCrate {
         let tcx = cx.tcx;
         let root = DefId { krate: *self, index: CRATE_DEF_INDEX };
         let krate_span = tcx.def_span(root);
@@ -204,8 +204,8 @@ impl Clean<ExternalCrate> for CrateNum {
     }
 }
 
-impl Clean<Item> for doctree::Module<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Item {
+impl<'tcx> Clean<'tcx, Item> for doctree::Module<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
         let mut items: Vec<Item> = vec![];
         items.extend(self.foreigns.iter().map(|x| x.clean(cx)));
         items.extend(self.mods.iter().map(|x| x.clean(cx)));
@@ -237,14 +237,14 @@ impl Clean<Item> for doctree::Module<'_> {
     }
 }
 
-impl Clean<Attributes> for [ast::Attribute] {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Attributes {
+impl<'tcx> Clean<'tcx, Attributes> for [ast::Attribute] {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Attributes {
         Attributes::from_ast(cx.sess().diagnostic(), self, None)
     }
 }
 
-impl Clean<GenericBound> for hir::GenericBound<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound {
+impl<'tcx> Clean<'tcx, GenericBound> for hir::GenericBound<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> GenericBound {
         match *self {
             hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)),
             hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => {
@@ -270,8 +270,8 @@ impl Clean<GenericBound> for hir::GenericBound<'_> {
     }
 }
 
-impl Clean<Type> for (ty::TraitRef<'_>, &[TypeBinding]) {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Type {
+impl<'tcx> Clean<'tcx, Type> for (ty::TraitRef<'tcx>, &[TypeBinding]) {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Type {
         let (trait_ref, bounds) = *self;
         inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait);
         let path = external_path(
@@ -289,8 +289,8 @@ impl Clean<Type> for (ty::TraitRef<'_>, &[TypeBinding]) {
     }
 }
 
-impl<'tcx> Clean<GenericBound> for ty::TraitRef<'tcx> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound {
+impl<'tcx> Clean<'tcx, GenericBound> for ty::TraitRef<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> GenericBound {
         GenericBound::TraitBound(
             PolyTrait { trait_: (*self, &[][..]).clean(cx), generic_params: vec![] },
             hir::TraitBoundModifier::None,
@@ -298,8 +298,8 @@ impl<'tcx> Clean<GenericBound> for ty::TraitRef<'tcx> {
     }
 }
 
-impl Clean<GenericBound> for (ty::PolyTraitRef<'_>, &[TypeBinding]) {
-    fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound {
+impl<'tcx> Clean<'tcx, GenericBound> for (ty::PolyTraitRef<'tcx>, &[TypeBinding]) {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> GenericBound {
         let (poly_trait_ref, bounds) = *self;
         let poly_trait_ref = poly_trait_ref.lift_to_tcx(cx.tcx).unwrap();
 
@@ -326,14 +326,14 @@ impl Clean<GenericBound> for (ty::PolyTraitRef<'_>, &[TypeBinding]) {
     }
 }
 
-impl<'tcx> Clean<GenericBound> for ty::PolyTraitRef<'tcx> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound {
+impl<'tcx> Clean<'tcx, GenericBound> for ty::PolyTraitRef<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> GenericBound {
         (*self, &[][..]).clean(cx)
     }
 }
 
-impl<'tcx> Clean<Option<Vec<GenericBound>>> for InternalSubsts<'tcx> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Option<Vec<GenericBound>> {
+impl<'tcx> Clean<'tcx, Option<Vec<GenericBound>>> for InternalSubsts<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Option<Vec<GenericBound>> {
         let mut v = Vec::new();
         v.extend(self.regions().filter_map(|r| r.clean(cx)).map(GenericBound::Outlives));
         v.extend(self.types().map(|t| {
@@ -346,8 +346,8 @@ impl<'tcx> Clean<Option<Vec<GenericBound>>> for InternalSubsts<'tcx> {
     }
 }
 
-impl Clean<Lifetime> for hir::Lifetime {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Lifetime {
+impl<'tcx> Clean<'tcx, Lifetime> for hir::Lifetime {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Lifetime {
         let def = cx.tcx.named_region(self.hir_id);
         match def {
             Some(
@@ -365,8 +365,8 @@ impl Clean<Lifetime> for hir::Lifetime {
     }
 }
 
-impl Clean<Lifetime> for hir::GenericParam<'_> {
-    fn clean(&self, _: &mut DocContext<'_>) -> Lifetime {
+impl<'tcx> Clean<'tcx, Lifetime> for hir::GenericParam<'tcx> {
+    fn clean(&self, _: &mut DocContext<'tcx>) -> Lifetime {
         match self.kind {
             hir::GenericParamKind::Lifetime { .. } => {
                 if !self.bounds.is_empty() {
@@ -389,8 +389,8 @@ impl Clean<Lifetime> for hir::GenericParam<'_> {
     }
 }
 
-impl Clean<Constant> for hir::ConstArg {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Constant {
+impl<'tcx> Clean<'tcx, Constant> for hir::ConstArg {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Constant {
         Constant {
             type_: cx
                 .tcx
@@ -401,14 +401,14 @@ impl Clean<Constant> for hir::ConstArg {
     }
 }
 
-impl Clean<Lifetime> for ty::GenericParamDef {
-    fn clean(&self, _cx: &mut DocContext<'_>) -> Lifetime {
+impl<'tcx> Clean<'tcx, Lifetime> for ty::GenericParamDef {
+    fn clean(&self, _cx: &mut DocContext<'tcx>) -> Lifetime {
         Lifetime(self.name)
     }
 }
 
-impl Clean<Option<Lifetime>> for ty::RegionKind {
-    fn clean(&self, _cx: &mut DocContext<'_>) -> Option<Lifetime> {
+impl<'tcx> Clean<'tcx, Option<Lifetime>> for ty::RegionKind {
+    fn clean(&self, _cx: &mut DocContext<'tcx>) -> Option<Lifetime> {
         match *self {
             ty::ReStatic => Some(Lifetime::statik()),
             ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name) }) => {
@@ -429,8 +429,8 @@ impl Clean<Option<Lifetime>> for ty::RegionKind {
     }
 }
 
-impl Clean<WherePredicate> for hir::WherePredicate<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> WherePredicate {
+impl<'tcx> Clean<'tcx, WherePredicate> for hir::WherePredicate<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> WherePredicate {
         match *self {
             hir::WherePredicate::BoundPredicate(ref wbp) => WherePredicate::BoundPredicate {
                 ty: wbp.bounded_ty.clean(cx),
@@ -449,8 +449,8 @@ impl Clean<WherePredicate> for hir::WherePredicate<'_> {
     }
 }
 
-impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Option<WherePredicate> {
+impl<'a> Clean<'a, Option<WherePredicate>> for ty::Predicate<'a> {
+    fn clean(&self, cx: &mut DocContext<'a>) -> Option<WherePredicate> {
         let bound_predicate = self.kind();
         match bound_predicate.skip_binder() {
             ty::PredicateKind::Trait(pred, _) => Some(bound_predicate.rebind(pred).clean(cx)),
@@ -469,8 +469,8 @@ impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> {
     }
 }
 
-impl<'a> Clean<WherePredicate> for ty::PolyTraitPredicate<'a> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> WherePredicate {
+impl<'tcx> Clean<'tcx, WherePredicate> for ty::PolyTraitPredicate<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> WherePredicate {
         let poly_trait_ref = self.map_bound(|pred| pred.trait_ref);
         WherePredicate::BoundPredicate {
             ty: poly_trait_ref.skip_binder().self_ty().clean(cx),
@@ -479,10 +479,10 @@ impl<'a> Clean<WherePredicate> for ty::PolyTraitPredicate<'a> {
     }
 }
 
-impl<'tcx> Clean<Option<WherePredicate>>
+impl<'tcx> Clean<'tcx, Option<WherePredicate>>
     for ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>
 {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Option<WherePredicate> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Option<WherePredicate> {
         let ty::OutlivesPredicate(a, b) = self;
 
         if let (ty::ReEmpty(_), ty::ReEmpty(_)) = (a, b) {
@@ -496,8 +496,10 @@ impl<'tcx> Clean<Option<WherePredicate>>
     }
 }
 
-impl<'tcx> Clean<Option<WherePredicate>> for ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Option<WherePredicate> {
+impl<'tcx> Clean<'tcx, Option<WherePredicate>>
+    for ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>
+{
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Option<WherePredicate> {
         let ty::OutlivesPredicate(ty, lt) = self;
 
         if let ty::ReEmpty(_) = lt {
@@ -511,15 +513,15 @@ impl<'tcx> Clean<Option<WherePredicate>> for ty::OutlivesPredicate<Ty<'tcx>, ty:
     }
 }
 
-impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> WherePredicate {
+impl<'tcx> Clean<'tcx, WherePredicate> for ty::ProjectionPredicate<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> WherePredicate {
         let ty::ProjectionPredicate { projection_ty, ty } = self;
         WherePredicate::EqPredicate { lhs: projection_ty.clean(cx), rhs: ty.clean(cx) }
     }
 }
 
-impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Type {
+impl<'tcx> Clean<'tcx, Type> for ty::ProjectionTy<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Type {
         let lifted = self.lift_to_tcx(cx.tcx).unwrap();
         let trait_ = match lifted.trait_ref(cx.tcx).clean(cx) {
             GenericBound::TraitBound(t, _) => t.trait_,
@@ -533,8 +535,8 @@ impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
     }
 }
 
-impl Clean<GenericParamDef> for ty::GenericParamDef {
-    fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef {
+impl<'tcx> Clean<'tcx, GenericParamDef> for ty::GenericParamDef {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> GenericParamDef {
         let (name, kind) = match self.kind {
             ty::GenericParamDefKind::Lifetime => (self.name, GenericParamDefKind::Lifetime),
             ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
@@ -563,8 +565,8 @@ impl Clean<GenericParamDef> for ty::GenericParamDef {
     }
 }
 
-impl Clean<GenericParamDef> for hir::GenericParam<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef {
+impl<'tcx> Clean<'tcx, GenericParamDef> for hir::GenericParam<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> GenericParamDef {
         let (name, kind) = match self.kind {
             hir::GenericParamKind::Lifetime { .. } => {
                 let name = if !self.bounds.is_empty() {
@@ -606,8 +608,8 @@ impl Clean<GenericParamDef> for hir::GenericParam<'_> {
     }
 }
 
-impl Clean<Generics> for hir::Generics<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Generics {
+impl<'tcx> Clean<'tcx, Generics> for hir::Generics<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Generics {
         // Synthetic type-parameters are inserted after normal ones.
         // In order for normal parameters to be able to refer to synthetic ones,
         // scans them first.
@@ -686,8 +688,8 @@ impl Clean<Generics> for hir::Generics<'_> {
     }
 }
 
-impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx>) {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Generics {
+impl<'a, 'tcx> Clean<'tcx, Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx>) {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Generics {
         use self::WherePredicate as WP;
         use std::collections::BTreeMap;
 
@@ -851,13 +853,13 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx
     }
 }
 
-fn clean_fn_or_proc_macro(
-    item: &hir::Item<'_>,
-    sig: &'a hir::FnSig<'a>,
-    generics: &'a hir::Generics<'a>,
+fn clean_fn_or_proc_macro<'a, 'tcx>(
+    item: &hir::Item<'tcx>,
+    sig: &'a hir::FnSig<'tcx>,
+    generics: &'a hir::Generics<'tcx>,
     body_id: hir::BodyId,
     name: &mut Symbol,
-    cx: &mut DocContext<'_>,
+    cx: &mut DocContext<'tcx>,
 ) -> ItemKind {
     let attrs = cx.tcx.hir().attrs(item.hir_id());
     let macro_kind = attrs.iter().find_map(|a| {
@@ -911,16 +913,18 @@ fn clean_fn_or_proc_macro(
     }
 }
 
-impl<'a> Clean<Function> for (&'a hir::FnSig<'a>, &'a hir::Generics<'a>, hir::BodyId) {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Function {
+impl<'a, 'tcx> Clean<'tcx, Function>
+    for (&'a hir::FnSig<'tcx>, &'a hir::Generics<'tcx>, hir::BodyId)
+{
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Function {
         let (generics, decl) =
             enter_impl_trait(cx, |cx| (self.1.clean(cx), (&*self.0.decl, self.2).clean(cx)));
         Function { decl, generics, header: self.0.header }
     }
 }
 
-impl<'a> Clean<Arguments> for (&'a [hir::Ty<'a>], &'a [Ident]) {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Arguments {
+impl<'a, 'tcx> Clean<'tcx, Arguments> for (&'a [hir::Ty<'tcx>], &'a [Ident]) {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Arguments {
         Arguments {
             values: self
                 .0
@@ -938,8 +942,8 @@ impl<'a> Clean<Arguments> for (&'a [hir::Ty<'a>], &'a [Ident]) {
     }
 }
 
-impl<'a> Clean<Arguments> for (&'a [hir::Ty<'a>], hir::BodyId) {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Arguments {
+impl<'a, 'tcx> Clean<'tcx, Arguments> for (&'a [hir::Ty<'tcx>], hir::BodyId) {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Arguments {
         let body = cx.tcx.hir().body(self.1);
 
         Arguments {
@@ -948,7 +952,7 @@ impl<'a> Clean<Arguments> for (&'a [hir::Ty<'a>], hir::BodyId) {
                 .iter()
                 .enumerate()
                 .map(|(i, ty)| Argument {
-                    name: name_from_pat(&body.params[i].pat),
+                    name: Symbol::intern(&rustc_hir_pretty::param_to_string(&body.params[i])),
                     type_: ty.clean(cx),
                 })
                 .collect(),
@@ -956,13 +960,13 @@ impl<'a> Clean<Arguments> for (&'a [hir::Ty<'a>], hir::BodyId) {
     }
 }
 
-impl<'a, A: Copy> Clean<FnDecl> for (&'a hir::FnDecl<'a>, A)
+impl<'a, 'tcx, A: Copy> Clean<'tcx, FnDecl> for (&'a hir::FnDecl<'tcx>, A)
 where
-    (&'a [hir::Ty<'a>], A): Clean<Arguments>,
+    (&'a [hir::Ty<'a>], A): Clean<'tcx, Arguments>,
 {
-    fn clean(&self, cx: &mut DocContext<'_>) -> FnDecl {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> FnDecl {
         FnDecl {
-            inputs: (self.0.inputs, self.1).clean(cx),
+            inputs: (&self.0.inputs[..], self.1).clean(cx),
             output: self.0.output.clean(cx),
             c_variadic: self.0.c_variadic,
             attrs: Attributes::default(),
@@ -970,8 +974,8 @@ where
     }
 }
 
-impl<'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) {
-    fn clean(&self, cx: &mut DocContext<'_>) -> FnDecl {
+impl<'tcx> Clean<'tcx, FnDecl> for (DefId, ty::PolyFnSig<'tcx>) {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> FnDecl {
         let (did, sig) = *self;
         let mut names = if did.is_local() { &[] } else { cx.tcx.fn_arg_names(did) }.iter();
 
@@ -994,8 +998,8 @@ impl<'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) {
     }
 }
 
-impl Clean<FnRetTy> for hir::FnRetTy<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> FnRetTy {
+impl<'tcx> Clean<'tcx, FnRetTy> for hir::FnRetTy<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> FnRetTy {
         match *self {
             Self::Return(ref typ) => Return(typ.clean(cx)),
             Self::DefaultReturn(..) => DefaultReturn,
@@ -1003,7 +1007,7 @@ impl Clean<FnRetTy> for hir::FnRetTy<'_> {
     }
 }
 
-impl Clean<bool> for hir::IsAuto {
+impl Clean<'_, bool> for hir::IsAuto {
     fn clean(&self, _: &mut DocContext<'_>) -> bool {
         match *self {
             hir::IsAuto::Yes => true,
@@ -1012,15 +1016,15 @@ impl Clean<bool> for hir::IsAuto {
     }
 }
 
-impl Clean<Type> for hir::TraitRef<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Type {
+impl<'tcx> Clean<'tcx, Type> for hir::TraitRef<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Type {
         let path = self.path.clean(cx);
         resolve_type(cx, path, self.hir_ref_id)
     }
 }
 
-impl Clean<PolyTrait> for hir::PolyTraitRef<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> PolyTrait {
+impl<'tcx> Clean<'tcx, PolyTrait> for hir::PolyTraitRef<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> PolyTrait {
         PolyTrait {
             trait_: self.trait_ref.clean(cx),
             generic_params: self.bound_generic_params.clean(cx),
@@ -1028,14 +1032,14 @@ impl Clean<PolyTrait> for hir::PolyTraitRef<'_> {
     }
 }
 
-impl Clean<TypeKind> for hir::def::DefKind {
-    fn clean(&self, _: &mut DocContext<'_>) -> TypeKind {
+impl<'tcx> Clean<'tcx, TypeKind> for hir::def::DefKind {
+    fn clean(&self, _: &mut DocContext<'tcx>) -> TypeKind {
         (*self).into()
     }
 }
 
-impl Clean<Item> for hir::TraitItem<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Item {
+impl<'tcx> Clean<'tcx, Item> for hir::TraitItem<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
         let local_did = self.def_id.to_def_id();
         cx.with_param_env(local_did, |cx| {
             let inner = match self.kind {
@@ -1075,8 +1079,8 @@ impl Clean<Item> for hir::TraitItem<'_> {
     }
 }
 
-impl Clean<Item> for hir::ImplItem<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Item {
+impl<'tcx> Clean<'tcx, Item> for hir::ImplItem<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
         let local_did = self.def_id.to_def_id();
         cx.with_param_env(local_did, |cx| {
             let inner = match self.kind {
@@ -1124,8 +1128,8 @@ impl Clean<Item> for hir::ImplItem<'_> {
     }
 }
 
-impl Clean<Item> for ty::AssocItem {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Item {
+impl<'tcx> Clean<'tcx, Item> for ty::AssocItem {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
         let tcx = cx.tcx;
         let kind = match self.kind {
             ty::AssocKind::Const => {
@@ -1276,7 +1280,7 @@ impl Clean<Item> for ty::AssocItem {
     }
 }
 
-fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
+fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type {
     use rustc_hir::GenericParamCount;
     let hir::Ty { hir_id, span, ref kind } = *hir_ty;
     let qpath = match kind {
@@ -1428,8 +1432,8 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
     }
 }
 
-impl Clean<Type> for hir::Ty<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Type {
+impl<'tcx> Clean<'tcx, Type> for hir::Ty<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Type {
         use rustc_hir::*;
 
         match self.kind {
@@ -1531,8 +1535,8 @@ fn normalize(cx: &mut DocContext<'tcx>, ty: Ty<'_>) -> Option<Ty<'tcx>> {
     }
 }
 
-impl<'tcx> Clean<Type> for Ty<'tcx> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Type {
+impl<'tcx> Clean<'tcx, Type> for Ty<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Type {
         debug!("cleaning type: {:?}", self);
         let ty = normalize(cx, self).unwrap_or(self);
         match *ty.kind() {
@@ -1739,8 +1743,8 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
     }
 }
 
-impl<'tcx> Clean<Constant> for ty::Const<'tcx> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Constant {
+impl<'tcx> Clean<'tcx, Constant> for ty::Const<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Constant {
         // FIXME: instead of storing the stringified expression, store `self` directly instead.
         Constant {
             type_: self.ty.clean(cx),
@@ -1749,8 +1753,8 @@ impl<'tcx> Clean<Constant> for ty::Const<'tcx> {
     }
 }
 
-impl Clean<Item> for hir::FieldDef<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Item {
+impl<'tcx> Clean<'tcx, Item> for hir::FieldDef<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
         let what_rustc_thinks = Item::from_hir_id_and_parts(
             self.hir_id,
             Some(self.ident.name),
@@ -1762,8 +1766,8 @@ impl Clean<Item> for hir::FieldDef<'_> {
     }
 }
 
-impl Clean<Item> for ty::FieldDef {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Item {
+impl Clean<'tcx, Item> for ty::FieldDef {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
         let what_rustc_thinks = Item::from_def_id_and_parts(
             self.did,
             Some(self.ident.name),
@@ -1775,8 +1779,8 @@ impl Clean<Item> for ty::FieldDef {
     }
 }
 
-impl Clean<Visibility> for hir::Visibility<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Visibility {
+impl<'tcx> Clean<'tcx, Visibility> for hir::Visibility<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Visibility {
         match self.node {
             hir::VisibilityKind::Public => Visibility::Public,
             hir::VisibilityKind::Inherited => Visibility::Inherited,
@@ -1793,8 +1797,8 @@ impl Clean<Visibility> for hir::Visibility<'_> {
     }
 }
 
-impl Clean<Visibility> for ty::Visibility {
-    fn clean(&self, _cx: &mut DocContext<'_>) -> Visibility {
+impl<'tcx> Clean<'tcx, Visibility> for ty::Visibility {
+    fn clean(&self, _cx: &mut DocContext<'tcx>) -> Visibility {
         match *self {
             ty::Visibility::Public => Visibility::Public,
             // NOTE: this is not quite right: `ty` uses `Invisible` to mean 'private',
@@ -1808,8 +1812,8 @@ impl Clean<Visibility> for ty::Visibility {
     }
 }
 
-impl Clean<VariantStruct> for rustc_hir::VariantData<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> VariantStruct {
+impl<'tcx> Clean<'tcx, VariantStruct> for rustc_hir::VariantData<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> VariantStruct {
         VariantStruct {
             struct_type: CtorKind::from_hir(self),
             fields: self.fields().iter().map(|x| x.clean(cx)).collect(),
@@ -1818,8 +1822,8 @@ impl Clean<VariantStruct> for rustc_hir::VariantData<'_> {
     }
 }
 
-impl Clean<Item> for ty::VariantDef {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Item {
+impl<'tcx> Clean<'tcx, Item> for ty::VariantDef {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
         let kind = match self.ctor_kind {
             CtorKind::Const => Variant::CLike,
             CtorKind::Fn => Variant::Tuple(
@@ -1849,8 +1853,8 @@ impl Clean<Item> for ty::VariantDef {
     }
 }
 
-impl Clean<Variant> for hir::VariantData<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Variant {
+impl<'tcx> Clean<'tcx, Variant> for hir::VariantData<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Variant {
         match self {
             hir::VariantData::Struct(..) => Variant::Struct(self.clean(cx)),
             hir::VariantData::Tuple(..) => {
@@ -1861,14 +1865,14 @@ impl Clean<Variant> for hir::VariantData<'_> {
     }
 }
 
-impl Clean<Span> for rustc_span::Span {
-    fn clean(&self, _cx: &mut DocContext<'_>) -> Span {
+impl<'tcx> Clean<'tcx, Span> for rustc_span::Span {
+    fn clean(&self, _cx: &mut DocContext<'tcx>) -> Span {
         Span::from_rustc_span(*self)
     }
 }
 
-impl Clean<Path> for hir::Path<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Path {
+impl<'tcx> Clean<'tcx, Path> for hir::Path<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Path {
         Path {
             global: self.is_global(),
             res: self.res,
@@ -1877,8 +1881,8 @@ impl Clean<Path> for hir::Path<'_> {
     }
 }
 
-impl Clean<GenericArgs> for hir::GenericArgs<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> GenericArgs {
+impl<'tcx> Clean<'tcx, GenericArgs> for hir::GenericArgs<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> GenericArgs {
         if self.parenthesized {
             let output = self.bindings[0].ty().clean(cx);
             GenericArgs::Parenthesized {
@@ -1905,28 +1909,28 @@ impl Clean<GenericArgs> for hir::GenericArgs<'_> {
     }
 }
 
-impl Clean<PathSegment> for hir::PathSegment<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> PathSegment {
+impl<'tcx> Clean<'tcx, PathSegment> for hir::PathSegment<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> PathSegment {
         PathSegment { name: self.ident.name, args: self.args().clean(cx) }
     }
 }
 
-impl Clean<String> for Ident {
+impl<'tcx> Clean<'tcx, String> for Ident {
     #[inline]
-    fn clean(&self, cx: &mut DocContext<'_>) -> String {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> String {
         self.name.clean(cx)
     }
 }
 
-impl Clean<String> for Symbol {
+impl<'tcx> Clean<'tcx, String> for Symbol {
     #[inline]
-    fn clean(&self, _: &mut DocContext<'_>) -> String {
+    fn clean(&self, _: &mut DocContext<'tcx>) -> String {
         self.to_string()
     }
 }
 
-impl Clean<BareFunctionDecl> for hir::BareFnTy<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> BareFunctionDecl {
+impl<'tcx> Clean<'tcx, BareFunctionDecl> for hir::BareFnTy<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> BareFunctionDecl {
         let (generic_params, decl) = enter_impl_trait(cx, |cx| {
             (self.generic_params.clean(cx), (&*self.decl, self.param_names).clean(cx))
         });
@@ -1934,8 +1938,8 @@ impl Clean<BareFunctionDecl> for hir::BareFnTy<'_> {
     }
 }
 
-impl Clean<Vec<Item>> for (&hir::Item<'_>, Option<Symbol>) {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Vec<Item> {
+impl<'tcx> Clean<'tcx, Vec<Item>> for (&hir::Item<'tcx>, Option<Symbol>) {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Vec<Item> {
         use hir::ItemKind;
 
         let (item, renamed) = self;
@@ -2018,8 +2022,8 @@ impl Clean<Vec<Item>> for (&hir::Item<'_>, Option<Symbol>) {
     }
 }
 
-impl Clean<Item> for hir::Variant<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Item {
+impl<'tcx> Clean<'tcx, Item> for hir::Variant<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
         let kind = VariantItem(self.data.clean(cx));
         let what_rustc_thinks =
             Item::from_hir_id_and_parts(self.id, Some(self.ident.name), kind, cx);
@@ -2028,9 +2032,9 @@ impl Clean<Item> for hir::Variant<'_> {
     }
 }
 
-impl Clean<bool> for ty::ImplPolarity {
+impl<'tcx> Clean<'tcx, bool> for ty::ImplPolarity {
     /// Returns whether the impl has negative polarity.
-    fn clean(&self, _: &mut DocContext<'_>) -> bool {
+    fn clean(&self, _: &mut DocContext<'tcx>) -> bool {
         match self {
             &ty::ImplPolarity::Positive |
             // FIXME: do we want to do something else here?
@@ -2040,7 +2044,11 @@ impl Clean<bool> for ty::ImplPolarity {
     }
 }
 
-fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &mut DocContext<'_>) -> Vec<Item> {
+fn clean_impl<'tcx>(
+    impl_: &hir::Impl<'tcx>,
+    hir_id: hir::HirId,
+    cx: &mut DocContext<'tcx>,
+) -> Vec<Item> {
     let tcx = cx.tcx;
     let mut ret = Vec::new();
     let trait_ = impl_.of_trait.clean(cx);
@@ -2085,11 +2093,11 @@ fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &mut DocContext<'_>
     ret
 }
 
-fn clean_extern_crate(
-    krate: &hir::Item<'_>,
+fn clean_extern_crate<'tcx>(
+    krate: &hir::Item<'tcx>,
     name: Symbol,
     orig_name: Option<Symbol>,
-    cx: &mut DocContext<'_>,
+    cx: &mut DocContext<'tcx>,
 ) -> Vec<Item> {
     // this is the ID of the `extern crate` statement
     let cnum = cx.tcx.extern_mod_stmt_cnum(krate.def_id).unwrap_or(LOCAL_CRATE);
@@ -2132,12 +2140,12 @@ fn clean_extern_crate(
     }]
 }
 
-fn clean_use_statement(
-    import: &hir::Item<'_>,
+fn clean_use_statement<'tcx>(
+    import: &hir::Item<'tcx>,
     name: Symbol,
-    path: &hir::Path<'_>,
+    path: &hir::Path<'tcx>,
     kind: hir::UseKind,
-    cx: &mut DocContext<'_>,
+    cx: &mut DocContext<'tcx>,
 ) -> Vec<Item> {
     // We need this comparison because some imports (for std types for example)
     // are "inserted" as well but directly by the compiler and they should not be
@@ -2227,8 +2235,8 @@ fn clean_use_statement(
     vec![Item::from_def_id_and_parts(import.def_id.to_def_id(), None, ImportItem(inner), cx)]
 }
 
-impl Clean<Item> for (&hir::ForeignItem<'_>, Option<Symbol>) {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Item {
+impl<'tcx> Clean<'tcx, Item> for (&hir::ForeignItem<'tcx>, Option<Symbol>) {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
         let (item, renamed) = self;
         cx.with_param_env(item.def_id.to_def_id(), |cx| {
             let kind = match item.kind {
@@ -2264,8 +2272,8 @@ impl Clean<Item> for (&hir::ForeignItem<'_>, Option<Symbol>) {
     }
 }
 
-impl Clean<Item> for (&hir::MacroDef<'_>, Option<Symbol>) {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Item {
+impl<'tcx> Clean<'tcx, Item> for (&hir::MacroDef<'tcx>, Option<Symbol>) {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
         let (item, renamed) = self;
         let name = renamed.unwrap_or(item.ident.name);
         let tts = item.ast.body.inner_tokens().trees().collect::<Vec<_>>();
@@ -2313,14 +2321,14 @@ impl Clean<Item> for (&hir::MacroDef<'_>, Option<Symbol>) {
     }
 }
 
-impl Clean<TypeBinding> for hir::TypeBinding<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> TypeBinding {
+impl<'tcx> Clean<'tcx, TypeBinding> for hir::TypeBinding<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> TypeBinding {
         TypeBinding { name: self.ident.name, kind: self.kind.clean(cx) }
     }
 }
 
-impl Clean<TypeBindingKind> for hir::TypeBindingKind<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> TypeBindingKind {
+impl<'tcx> Clean<'tcx, TypeBindingKind> for hir::TypeBindingKind<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> TypeBindingKind {
         match *self {
             hir::TypeBindingKind::Equality { ref ty } => {
                 TypeBindingKind::Equality { ty: ty.clean(cx) }
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 32bac53e8f5..ce802902f5b 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -84,12 +84,12 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate {
     }
 }
 
-fn external_generic_args(
-    cx: &mut DocContext<'_>,
+fn external_generic_args<'tcx>(
+    cx: &mut DocContext<'tcx>,
     trait_did: Option<DefId>,
     has_self: bool,
     bindings: Vec<TypeBinding>,
-    substs: SubstsRef<'_>,
+    substs: SubstsRef<'tcx>,
 ) -> GenericArgs {
     let mut skip_self = has_self;
     let mut ty_kind = None;
@@ -136,13 +136,13 @@ fn external_generic_args(
 
 // trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
 // from Fn<(A, B,), C> to Fn(A, B) -> C
-pub(super) fn external_path(
-    cx: &mut DocContext<'_>,
+pub(super) fn external_path<'tcx>(
+    cx: &mut DocContext<'tcx>,
     name: Symbol,
     trait_did: Option<DefId>,
     has_self: bool,
     bindings: Vec<TypeBinding>,
-    substs: SubstsRef<'_>,
+    substs: SubstsRef<'tcx>,
 ) -> Path {
     Path {
         global: false,
diff --git a/src/test/ui/hrtb/complex.rs b/src/test/ui/hrtb/complex.rs
new file mode 100644
index 00000000000..0bcda8c01cd
--- /dev/null
+++ b/src/test/ui/hrtb/complex.rs
@@ -0,0 +1,20 @@
+// check-pass
+
+trait A<'a> {}
+trait B<'b> {}
+fn foo<T>() where for<'a> T: A<'a> + 'a {}
+trait C<'c>: for<'a> A<'a> + for<'b> B<'b> {
+    type As;
+}
+struct D<T> where T: for<'c> C<'c, As=&'c ()> {
+    t: std::marker::PhantomData<T>,
+}
+trait E<'e> {
+    type As;
+}
+trait F<'f>: for<'a> A<'a> + for<'e> E<'e> {}
+struct G<T> where T: for<'f> F<'f, As=&'f ()> {
+    t: std::marker::PhantomData<T>,
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr
index 92208231b17..fa59d7a0313 100644
--- a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr
+++ b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr
@@ -1,4 +1,4 @@
-error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[317d]::Id::This) }, (I,)))`
+error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[317d]::Id::This) }, (I,)), [])`
   --> $DIR/repeated_projection_type.rs:19:1
    |
 LL | / impl<I, V: Id<This = (I,)>> X for V {
diff --git a/src/test/ui/symbol-names/basic.legacy.stderr b/src/test/ui/symbol-names/basic.legacy.stderr
index 7155d88be96..3dd2b19fbf9 100644
--- a/src/test/ui/symbol-names/basic.legacy.stderr
+++ b/src/test/ui/symbol-names/basic.legacy.stderr
@@ -1,10 +1,10 @@
-error: symbol-name(_ZN5basic4main17hfcf1daab33c43a6aE)
+error: symbol-name(_ZN5basic4main17h6c535bbea2051f85E)
   --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(basic::main::hfcf1daab33c43a6a)
+error: demangling(basic::main::h6c535bbea2051f85)
   --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
diff --git a/src/test/ui/symbol-names/impl1.legacy.stderr b/src/test/ui/symbol-names/impl1.legacy.stderr
index bd32a39a65c..c9c2664e6de 100644
--- a/src/test/ui/symbol-names/impl1.legacy.stderr
+++ b/src/test/ui/symbol-names/impl1.legacy.stderr
@@ -1,71 +1,71 @@
-error: symbol-name(_ZN5impl13foo3Foo3bar17<SYMBOL_HASH>)
-  --> $DIR/impl1.rs:15:9
+error: symbol-name(_ZN5impl13foo3Foo3bar17h2e76f87b171019e0E)
+  --> $DIR/impl1.rs:16:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(impl1::foo::Foo::bar::<SYMBOL_HASH>)
-  --> $DIR/impl1.rs:15:9
+error: demangling(impl1::foo::Foo::bar::h2e76f87b171019e0)
+  --> $DIR/impl1.rs:16:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(impl1::foo::Foo::bar)
-  --> $DIR/impl1.rs:15:9
+  --> $DIR/impl1.rs:16:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: def-path(foo::Foo::bar)
-  --> $DIR/impl1.rs:22:9
+  --> $DIR/impl1.rs:23:9
    |
 LL |         #[rustc_def_path]
    |         ^^^^^^^^^^^^^^^^^
 
-error: symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz17<SYMBOL_HASH>)
-  --> $DIR/impl1.rs:33:9
+error: symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz17hb388a171ee84bca1E)
+  --> $DIR/impl1.rs:34:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(impl1::bar::<impl impl1::foo::Foo>::baz::<SYMBOL_HASH>)
-  --> $DIR/impl1.rs:33:9
+error: demangling(impl1::bar::<impl impl1::foo::Foo>::baz::hb388a171ee84bca1)
+  --> $DIR/impl1.rs:34:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(impl1::bar::<impl impl1::foo::Foo>::baz)
-  --> $DIR/impl1.rs:33:9
+  --> $DIR/impl1.rs:34:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: def-path(bar::<impl foo::Foo>::baz)
-  --> $DIR/impl1.rs:40:9
+  --> $DIR/impl1.rs:41:9
    |
 LL |         #[rustc_def_path]
    |         ^^^^^^^^^^^^^^^^^
 
-error: symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$3$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method17<SYMBOL_HASH>)
-  --> $DIR/impl1.rs:63:13
+error: symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$3$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method17SYMBOL_HASH)
+  --> $DIR/impl1.rs:64:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method::<SYMBOL_HASH>)
-  --> $DIR/impl1.rs:63:13
+error: demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method::SYMBOL_HASH)
+  --> $DIR/impl1.rs:64:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method)
-  --> $DIR/impl1.rs:63:13
+  --> $DIR/impl1.rs:64:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
 error: def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method)
-  --> $DIR/impl1.rs:70:13
+  --> $DIR/impl1.rs:71:13
    |
 LL |             #[rustc_def_path]
    |             ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/symbol-names/impl1.rs b/src/test/ui/symbol-names/impl1.rs
index 771695330d8..0a865a602f6 100644
--- a/src/test/ui/symbol-names/impl1.rs
+++ b/src/test/ui/symbol-names/impl1.rs
@@ -3,7 +3,8 @@
 // revisions: legacy v0
 //[legacy]compile-flags: -Z symbol-mangling-version=legacy
     //[v0]compile-flags: -Z symbol-mangling-version=v0
-//[legacy]normalize-stderr-test: "h[\w]{16}E?\)" -> "<SYMBOL_HASH>)"
+//[legacy]normalize-stderr-test: "method17h[\d\w]+" -> "method17SYMBOL_HASH"
+//[legacy]normalize-stderr-test: "method::h[\d\w]+" -> "method::SYMBOL_HASH"
 
 #![feature(auto_traits, rustc_attrs)]
 #![allow(dead_code)]
diff --git a/src/test/ui/symbol-names/impl1.v0.stderr b/src/test/ui/symbol-names/impl1.v0.stderr
index 3a6610935d6..a68a74c8552 100644
--- a/src/test/ui/symbol-names/impl1.v0.stderr
+++ b/src/test/ui/symbol-names/impl1.v0.stderr
@@ -1,71 +1,71 @@
 error: symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13fooNtB2_3Foo3bar)
-  --> $DIR/impl1.rs:15:9
+  --> $DIR/impl1.rs:16:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(<impl1[17891616a171812d]::foo::Foo>::bar)
-  --> $DIR/impl1.rs:15:9
+  --> $DIR/impl1.rs:16:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(<impl1::foo::Foo>::bar)
-  --> $DIR/impl1.rs:15:9
+  --> $DIR/impl1.rs:16:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: def-path(foo::Foo::bar)
-  --> $DIR/impl1.rs:22:9
+  --> $DIR/impl1.rs:23:9
    |
 LL |         #[rustc_def_path]
    |         ^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13barNtNtB4_3foo3Foo3baz)
-  --> $DIR/impl1.rs:33:9
+  --> $DIR/impl1.rs:34:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(<impl1[17891616a171812d]::foo::Foo>::baz)
-  --> $DIR/impl1.rs:33:9
+  --> $DIR/impl1.rs:34:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(<impl1::foo::Foo>::baz)
-  --> $DIR/impl1.rs:33:9
+  --> $DIR/impl1.rs:34:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: def-path(bar::<impl foo::Foo>::baz)
-  --> $DIR/impl1.rs:40:9
+  --> $DIR/impl1.rs:41:9
    |
 LL |         #[rustc_def_path]
    |         ^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_RNvXNCNvCs21hi0yVfW1J_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
-  --> $DIR/impl1.rs:63:13
+  --> $DIR/impl1.rs:64:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(<[&dyn impl1[17891616a171812d]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[17891616a171812d]::AutoTrait; 3: usize] as impl1[17891616a171812d]::main::{closure#1}::Bar>::method)
-  --> $DIR/impl1.rs:63:13
+  --> $DIR/impl1.rs:64:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(<[&dyn impl1::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method)
-  --> $DIR/impl1.rs:63:13
+  --> $DIR/impl1.rs:64:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
 error: def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method)
-  --> $DIR/impl1.rs:70:13
+  --> $DIR/impl1.rs:71:13
    |
 LL |             #[rustc_def_path]
    |             ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/symbol-names/issue-60925.legacy.stderr b/src/test/ui/symbol-names/issue-60925.legacy.stderr
index 9575875f5a8..65cc62b4d1d 100644
--- a/src/test/ui/symbol-names/issue-60925.legacy.stderr
+++ b/src/test/ui/symbol-names/issue-60925.legacy.stderr
@@ -1,10 +1,10 @@
-error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17hb8ca3eb2682b1b51E)
+error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h6244e5288326926aE)
   --> $DIR/issue-60925.rs:22:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::hb8ca3eb2682b1b51)
+error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::h6244e5288326926a)
   --> $DIR/issue-60925.rs:22:9
    |
 LL |         #[rustc_symbol_name]
diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
index bad3e488bb6..4c13941f665 100644
--- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
@@ -44,7 +44,7 @@ fn get_trait_predicates_for_trait_id<'tcx>(
     for (pred, _) in generics.predicates {
         if_chain! {
             if let PredicateKind::Trait(poly_trait_pred, _) = pred.kind().skip_binder();
-            let trait_pred = cx.tcx.erase_late_bound_regions(ty::Binder::bind(poly_trait_pred));
+            let trait_pred = cx.tcx.erase_late_bound_regions(pred.kind().rebind(poly_trait_pred));
             if let Some(trait_def_id) = trait_id;
             if trait_def_id == trait_pred.trait_ref.def_id;
             then {
@@ -58,12 +58,12 @@ fn get_trait_predicates_for_trait_id<'tcx>(
 fn get_projection_pred<'tcx>(
     cx: &LateContext<'tcx>,
     generics: GenericPredicates<'tcx>,
-    pred: TraitPredicate<'tcx>,
+    trait_pred: TraitPredicate<'tcx>,
 ) -> Option<ProjectionPredicate<'tcx>> {
     generics.predicates.iter().find_map(|(proj_pred, _)| {
-        if let ty::PredicateKind::Projection(proj_pred) = proj_pred.kind().skip_binder() {
-            let projection_pred = cx.tcx.erase_late_bound_regions(ty::Binder::bind(proj_pred));
-            if projection_pred.projection_ty.substs == pred.trait_ref.substs {
+        if let ty::PredicateKind::Projection(pred) = proj_pred.kind().skip_binder() {
+            let projection_pred = cx.tcx.erase_late_bound_regions(proj_pred.kind().rebind(pred));
+            if projection_pred.projection_ty.substs == trait_pred.trait_ref.substs {
                 return Some(projection_pred);
             }
         }