about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs41
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs4
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs4
-rw-r--r--compiler/rustc_hir/src/hir.rs52
-rw-r--r--compiler/rustc_hir/src/intravisit.rs8
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs6
-rw-r--r--compiler/rustc_middle/src/middle/resolve_lifetime.rs11
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs7
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs29
-rw-r--r--compiler/rustc_resolve/src/late/lifetimes.rs233
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs364
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs1
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/checks.rs7
-rw-r--r--compiler/rustc_typeck/src/collect.rs35
-rw-r--r--compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs4
-rw-r--r--src/librustdoc/clean/mod.rs23
-rw-r--r--src/librustdoc/html/static/.eslintrc.js8
-rw-r--r--src/test/ui/derives/issue-97343.rs2
-rw-r--r--src/test/ui/derives/issue-97343.stderr12
-rw-r--r--src/test/ui/error-codes/E0109.stderr12
-rw-r--r--src/test/ui/error-codes/E0110.stderr12
-rw-r--r--src/test/ui/issues/issue-22706.rs2
-rw-r--r--src/test/ui/issues/issue-22706.stderr6
-rw-r--r--src/test/ui/issues/issue-57924.rs2
-rw-r--r--src/test/ui/issues/issue-57924.stderr6
-rw-r--r--src/test/ui/issues/issue-60989.rs4
-rw-r--r--src/test/ui/issues/issue-60989.stderr12
-rw-r--r--src/test/ui/mod-subitem-as-enum-variant.rs2
-rw-r--r--src/test/ui/mod-subitem-as-enum-variant.stderr6
-rw-r--r--src/test/ui/structs/struct-path-associated-type.rs4
-rw-r--r--src/test/ui/structs/struct-path-associated-type.stderr12
-rw-r--r--src/test/ui/structs/struct-path-self.rs6
-rw-r--r--src/test/ui/structs/struct-path-self.stderr52
-rw-r--r--src/test/ui/type-alias-enum-variants/enum-variant-generic-args.rs54
-rw-r--r--src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr284
-rw-r--r--src/test/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.rs2
-rw-r--r--src/test/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.stderr6
-rw-r--r--src/test/ui/type/issue-91268.rs2
-rw-r--r--src/test/ui/type/issue-91268.stderr12
-rw-r--r--src/test/ui/typeck/prim-with-args.fixed28
-rw-r--r--src/test/ui/typeck/prim-with-args.rs45
-rw-r--r--src/test/ui/typeck/prim-with-args.stderr342
-rw-r--r--src/test/ui/usize-generic-argument-parent.rs2
-rw-r--r--src/test/ui/usize-generic-argument-parent.stderr12
-rw-r--r--src/tools/clippy/clippy_lints/src/lifetimes.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs8
48 files changed, 1211 insertions, 581 deletions
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 96db40cb95b..d1ea76b3922 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -672,9 +672,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             LifetimeRes::Param { .. } => {
                 (hir::ParamName::Plain(ident), hir::LifetimeParamKind::Explicit)
             }
-            LifetimeRes::Fresh { param, .. } => {
-                (hir::ParamName::Fresh(param), hir::LifetimeParamKind::Elided)
-            }
+            LifetimeRes::Fresh { .. } => (hir::ParamName::Fresh, hir::LifetimeParamKind::Elided),
             LifetimeRes::Static | LifetimeRes::Error => return None,
             res => panic!(
                 "Unexpected lifetime resolution {:?} for {:?} at {:?}",
@@ -1576,10 +1574,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     (hir::ParamName::Plain(ident), LifetimeRes::Param { param, binder: fn_node_id })
                 }
                 // Input lifetime like `'1`:
-                LifetimeRes::Fresh { param, .. } => (
-                    hir::ParamName::Fresh(outer_def_id),
-                    LifetimeRes::Fresh { param, binder: fn_node_id },
-                ),
+                LifetimeRes::Fresh { param, .. } => {
+                    (hir::ParamName::Fresh, LifetimeRes::Fresh { param, binder: fn_node_id })
+                }
                 LifetimeRes::Static | LifetimeRes::Error => continue,
                 res => {
                     panic!("Unexpected lifetime resolution {:?} for {:?} at {:?}", res, ident, span)
@@ -1749,7 +1746,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     ) -> hir::Lifetime {
         debug!(?self.captured_lifetimes);
         let name = match res {
-            LifetimeRes::Param { param, binder } => {
+            LifetimeRes::Param { mut param, binder } => {
                 debug_assert_ne!(ident.name, kw::UnderscoreLifetime);
                 let p_name = ParamName::Plain(ident);
                 if let Some(LifetimeCaptureContext { parent_def_id, captures, binders_to_ignore }) =
@@ -1757,10 +1754,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     && !binders_to_ignore.contains(&binder)
                 {
                     match captures.entry(param) {
-                        Entry::Occupied(_) => {}
+                        Entry::Occupied(o) => param = self.resolver.local_def_id(o.get().1),
                         Entry::Vacant(v) => {
                             let p_id = self.resolver.next_node_id();
-                            self.resolver.create_def(
+                            let p_def_id = self.resolver.create_def(
                                 *parent_def_id,
                                 p_id,
                                 DefPathData::LifetimeNs(p_name.ident().name),
@@ -1769,10 +1766,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             );
 
                             v.insert((span, p_id, p_name, res));
+                            param = p_def_id;
                         }
                     }
                 }
-                hir::LifetimeName::Param(p_name)
+                hir::LifetimeName::Param(param, p_name)
             }
             LifetimeRes::Fresh { mut param, binder } => {
                 debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
@@ -1792,21 +1790,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                                 span.with_parent(None),
                             );
 
-                            let p_name = ParamName::Fresh(param);
-                            v.insert((span, p_id, p_name, res));
+                            v.insert((span, p_id, ParamName::Fresh, res));
                             param = p_def_id;
                         }
                     }
                 }
-                let p_name = ParamName::Fresh(param);
-                hir::LifetimeName::Param(p_name)
+                hir::LifetimeName::Param(param, ParamName::Fresh)
             }
             LifetimeRes::Anonymous { binder, elided } => {
-                let l_name = if elided {
-                    hir::LifetimeName::Implicit
-                } else {
-                    hir::LifetimeName::Underscore
-                };
                 if let Some(LifetimeCaptureContext { parent_def_id, captures, binders_to_ignore }) =
                     &mut self.captured_lifetimes
                     && !binders_to_ignore.contains(&binder)
@@ -1819,11 +1810,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         ExpnId::root(),
                         span.with_parent(None),
                     );
-                    let p_name = ParamName::Fresh(p_def_id);
-                    captures.insert(p_def_id, (span, p_id, p_name, res));
-                    hir::LifetimeName::Param(p_name)
+                    captures.insert(p_def_id, (span, p_id, ParamName::Fresh, res));
+                    hir::LifetimeName::Param(p_def_id, ParamName::Fresh)
+                } else if elided {
+                    hir::LifetimeName::Implicit
                 } else {
-                    l_name
+                    hir::LifetimeName::Underscore
                 }
             }
             LifetimeRes::Static => hir::LifetimeName::Static,
@@ -1831,6 +1823,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             res => panic!("Unexpected lifetime resolution {:?} for {:?} at {:?}", res, ident, span),
         };
         debug!(?self.captured_lifetimes);
+        debug!(?name);
         hir::Lifetime { hir_id: self.lower_node_id(id), span: self.lower_span(span), name }
     }
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index cb4b154d271..fcb6ae438fe 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -567,14 +567,14 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
         let lifetime =
             self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?;
         match lifetime.name {
-            hir::LifetimeName::Param(hir::ParamName::Plain(_) | hir::ParamName::Error)
+            hir::LifetimeName::Param(_, hir::ParamName::Plain(_) | hir::ParamName::Error)
             | hir::LifetimeName::Error
             | hir::LifetimeName::Static => {
                 let lifetime_span = lifetime.span;
                 Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime_span))
             }
 
-            hir::LifetimeName::Param(hir::ParamName::Fresh(_))
+            hir::LifetimeName::Param(_, hir::ParamName::Fresh)
             | hir::LifetimeName::ImplicitObjectLifetimeDefault
             | hir::LifetimeName::Implicit
             | hir::LifetimeName::Underscore => {
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 7b63ec516b8..c2c093f9f2f 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -830,11 +830,11 @@ fn for_each_late_bound_region_defined_on<'tcx>(
     fn_def_id: DefId,
     mut f: impl FnMut(ty::Region<'tcx>),
 ) {
-    if let Some((owner, late_bounds)) = tcx.is_late_bound_map(fn_def_id.expect_local()) {
+    if let Some(late_bounds) = tcx.is_late_bound_map(fn_def_id.expect_local()) {
         for &region_def_id in late_bounds.iter() {
             let name = tcx.item_name(region_def_id.to_def_id());
             let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion {
-                scope: owner.to_def_id(),
+                scope: fn_def_id,
                 bound_region: ty::BoundRegionKind::BrNamed(region_def_id.to_def_id(), name),
             }));
             f(liberated_region);
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index dbe6fe6ea84..b98d4341118 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -26,7 +26,7 @@ use rustc_target::spec::abi::Abi;
 use smallvec::SmallVec;
 use std::fmt;
 
-#[derive(Copy, Clone, Encodable, HashStable_Generic)]
+#[derive(Debug, Copy, Clone, Encodable, HashStable_Generic)]
 pub struct Lifetime {
     pub hir_id: HirId,
     pub span: Span,
@@ -60,7 +60,7 @@ pub enum ParamName {
     /// ```
     /// where `'f` is something like `Fresh(0)`. The indices are
     /// unique per impl, but not necessarily continuous.
-    Fresh(LocalDefId),
+    Fresh,
 
     /// Indicates an illegal name was given and an error has been
     /// reported (so we should squelch other derived errors). Occurs
@@ -72,9 +72,7 @@ impl ParamName {
     pub fn ident(&self) -> Ident {
         match *self {
             ParamName::Plain(ident) => ident,
-            ParamName::Fresh(_) | ParamName::Error => {
-                Ident::with_dummy_span(kw::UnderscoreLifetime)
-            }
+            ParamName::Fresh | ParamName::Error => Ident::with_dummy_span(kw::UnderscoreLifetime),
         }
     }
 
@@ -90,7 +88,7 @@ impl ParamName {
 #[derive(HashStable_Generic)]
 pub enum LifetimeName {
     /// User-given names or fresh (synthetic) names.
-    Param(ParamName),
+    Param(LocalDefId, ParamName),
 
     /// User wrote nothing (e.g., the lifetime in `&u32`).
     Implicit,
@@ -127,7 +125,7 @@ impl LifetimeName {
             | LifetimeName::Error => Ident::empty(),
             LifetimeName::Underscore => Ident::with_dummy_span(kw::UnderscoreLifetime),
             LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime),
-            LifetimeName::Param(param_name) => param_name.ident(),
+            LifetimeName::Param(_, param_name) => param_name.ident(),
         }
     }
 
@@ -136,9 +134,9 @@ impl LifetimeName {
             LifetimeName::ImplicitObjectLifetimeDefault
             | LifetimeName::Implicit
             | LifetimeName::Underscore
-            | LifetimeName::Param(ParamName::Fresh(_))
+            | LifetimeName::Param(_, ParamName::Fresh)
             | LifetimeName::Error => true,
-            LifetimeName::Static | LifetimeName::Param(_) => false,
+            LifetimeName::Static | LifetimeName::Param(..) => false,
         }
     }
 
@@ -148,12 +146,12 @@ impl LifetimeName {
             | LifetimeName::Implicit
             | LifetimeName::Underscore => true,
 
-            // It might seem surprising that `Fresh(_)` counts as
+            // It might seem surprising that `Fresh` counts as
             // *not* elided -- but this is because, as far as the code
-            // in the compiler is concerned -- `Fresh(_)` variants act
+            // in the compiler is concerned -- `Fresh` variants act
             // equivalently to "some fresh name". They correspond to
             // early-bound regions on an impl, in other words.
-            LifetimeName::Error | LifetimeName::Param(_) | LifetimeName::Static => false,
+            LifetimeName::Error | LifetimeName::Param(..) | LifetimeName::Static => false,
         }
     }
 
@@ -163,8 +161,8 @@ impl LifetimeName {
 
     pub fn normalize_to_macros_2_0(&self) -> LifetimeName {
         match *self {
-            LifetimeName::Param(param_name) => {
-                LifetimeName::Param(param_name.normalize_to_macros_2_0())
+            LifetimeName::Param(def_id, param_name) => {
+                LifetimeName::Param(def_id, param_name.normalize_to_macros_2_0())
             }
             lifetime_name => lifetime_name,
         }
@@ -177,12 +175,6 @@ impl fmt::Display for Lifetime {
     }
 }
 
-impl fmt::Debug for Lifetime {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "lifetime({}: {})", self.hir_id, self.name.ident())
-    }
-}
-
 impl Lifetime {
     pub fn is_elided(&self) -> bool {
         self.name.is_elided()
@@ -628,6 +620,16 @@ impl<'hir> Generics<'hir> {
         })
     }
 
+    pub fn outlives_for_param(
+        &self,
+        param_def_id: LocalDefId,
+    ) -> impl Iterator<Item = &WhereRegionPredicate<'_>> {
+        self.predicates.iter().filter_map(move |pred| match pred {
+            WherePredicate::RegionPredicate(rp) if rp.is_param_bound(param_def_id) => Some(rp),
+            _ => None,
+        })
+    }
+
     pub fn bounds_span_for_suggestions(&self, param_def_id: LocalDefId) -> Option<Span> {
         self.bounds_for_param(param_def_id).flat_map(|bp| bp.bounds.iter().rev()).find_map(
             |bound| {
@@ -769,6 +771,16 @@ pub struct WhereRegionPredicate<'hir> {
     pub bounds: GenericBounds<'hir>,
 }
 
+impl<'hir> WhereRegionPredicate<'hir> {
+    /// Returns `true` if `param_def_id` matches the `lifetime` of this predicate.
+    pub fn is_param_bound(&self, param_def_id: LocalDefId) -> bool {
+        match self.lifetime.name {
+            LifetimeName::Param(id, _) => id == param_def_id,
+            _ => false,
+        }
+    }
+}
+
 /// An equality predicate (e.g., `T = int`); currently unsupported.
 #[derive(Debug, HashStable_Generic)]
 pub struct WhereEqPredicate<'hir> {
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 5b83a29bb33..bd8587f1106 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -510,11 +510,11 @@ pub fn walk_label<'v, V: Visitor<'v>>(visitor: &mut V, label: &'v Label) {
 pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
     visitor.visit_id(lifetime.hir_id);
     match lifetime.name {
-        LifetimeName::Param(ParamName::Plain(ident)) => {
+        LifetimeName::Param(_, ParamName::Plain(ident)) => {
             visitor.visit_ident(ident);
         }
-        LifetimeName::Param(ParamName::Fresh(_))
-        | LifetimeName::Param(ParamName::Error)
+        LifetimeName::Param(_, ParamName::Fresh)
+        | LifetimeName::Param(_, ParamName::Error)
         | LifetimeName::Static
         | LifetimeName::Error
         | LifetimeName::Implicit
@@ -879,7 +879,7 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Generi
     visitor.visit_id(param.hir_id);
     match param.name {
         ParamName::Plain(ident) => visitor.visit_ident(ident),
-        ParamName::Error | ParamName::Fresh(_) => {}
+        ParamName::Error | ParamName::Fresh => {}
     }
     match param.kind {
         GenericParamKind::Lifetime { .. } => {}
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 7a1bdd6beca..aab84b718d4 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -364,7 +364,11 @@ impl<'hir> Map<'hir> {
         match node.node {
             OwnerNode::ImplItem(impl_item) => Some(&impl_item.generics),
             OwnerNode::TraitItem(trait_item) => Some(&trait_item.generics),
-            OwnerNode::Item(Item {
+            OwnerNode::ForeignItem(ForeignItem {
+                kind: ForeignItemKind::Fn(_, _, generics),
+                ..
+            })
+            | OwnerNode::Item(Item {
                 kind:
                     ItemKind::Fn(_, generics, _)
                     | ItemKind::TyAlias(_, generics)
diff --git a/compiler/rustc_middle/src/middle/resolve_lifetime.rs b/compiler/rustc_middle/src/middle/resolve_lifetime.rs
index 70586cefaee..cdc0d076801 100644
--- a/compiler/rustc_middle/src/middle/resolve_lifetime.rs
+++ b/compiler/rustc_middle/src/middle/resolve_lifetime.rs
@@ -6,7 +6,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::ItemLocalId;
 use rustc_macros::HashStable;
-use rustc_span::symbol::Symbol;
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)]
 pub enum Region {
@@ -22,12 +21,12 @@ pub enum Region {
 /// so that we can e.g. suggest elided-lifetimes-in-paths of the form <'_, '_> e.g.
 #[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)]
 pub enum LifetimeScopeForPath {
-    // Contains all lifetime names that are in scope and could possibly be used in generics
-    // arguments of path.
-    NonElided(Vec<Symbol>),
+    /// Contains all lifetime names that are in scope and could possibly be used in generics
+    /// arguments of path.
+    NonElided(Vec<LocalDefId>),
 
-    // Information that allows us to suggest args of the form `<'_>` in case
-    // no generic arguments were provided for a path.
+    /// Information that allows us to suggest args of the form `<'_>` in case
+    /// no generic arguments were provided for a path.
     Elided,
 }
 
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 38d8e0b5819..899d6c7e490 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1584,7 +1584,7 @@ rustc_queries! {
         Option<&'tcx FxHashMap<ItemLocalId, Region>> {
         desc { "looking up a named region" }
     }
-    query is_late_bound_map(_: LocalDefId) -> Option<(LocalDefId, &'tcx FxHashSet<LocalDefId>)> {
+    query is_late_bound_map(_: LocalDefId) -> Option<&'tcx FxHashSet<LocalDefId>> {
         desc { "testing if a region is late bound" }
     }
     /// For a given item (like a struct), gets the default lifetimes to be used
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index a0d92e2a5dd..72e2beb372d 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -2803,6 +2803,13 @@ impl<'tcx> TyCtxt<'tcx> {
         self.named_region_map(id.owner).and_then(|map| map.get(&id.local_id).cloned())
     }
 
+    pub fn is_late_bound(self, id: HirId) -> bool {
+        self.is_late_bound_map(id.owner).map_or(false, |set| {
+            let def_id = self.hir().local_def_id(id);
+            set.contains(&def_id)
+        })
+    }
+
     pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> {
         self.mk_bound_variable_kinds(
             self.late_bound_vars_map(id.owner)
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 9213652e35f..cb39eb5416b 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -13,7 +13,7 @@ use rustc_ast::{
 };
 use rustc_ast_lowering::ResolverAstLowering;
 use rustc_ast_pretty::pprust::path_segment_to_string;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_errors::{
     pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
     MultiSpan,
@@ -21,7 +21,7 @@ use rustc_errors::{
 use rustc_hir as hir;
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, CtorOf, DefKind};
-use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::PrimTy;
 use rustc_session::lint;
 use rustc_session::parse::feature_err;
@@ -2082,7 +2082,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
 
     /// Returns whether to add `'static` lifetime to the suggested lifetime list.
     pub(crate) fn report_elision_failure(
-        &mut self,
+        &self,
         diag: &mut Diagnostic,
         params: &[ElisionFailureInfo],
     ) -> bool {
@@ -2187,10 +2187,27 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
         &self,
         err: &mut Diagnostic,
         mut spans_with_counts: Vec<(Span, usize)>,
-        lifetime_names: &FxHashSet<Symbol>,
-        lifetime_spans: Vec<Span>,
-        params: &[ElisionFailureInfo],
+        in_scope_lifetimes: FxIndexSet<LocalDefId>,
+        params: Option<&[ElisionFailureInfo]>,
     ) {
+        let (mut lifetime_names, lifetime_spans): (FxHashSet<_>, Vec<_>) = in_scope_lifetimes
+            .iter()
+            .filter_map(|def_id| {
+                let name = self.tcx.item_name(def_id.to_def_id());
+                let span = self.tcx.def_ident_span(def_id.to_def_id())?;
+                Some((name, span))
+            })
+            .filter(|&(n, _)| n != kw::UnderscoreLifetime)
+            .unzip();
+
+        if let Some(params) = params {
+            // If there's no lifetime available, suggest `'static`.
+            if self.report_elision_failure(err, params) && lifetime_names.is_empty() {
+                lifetime_names.insert(kw::StaticLifetime);
+            }
+        }
+        let params = params.unwrap_or(&[]);
+
         let snippets: Vec<Option<String>> = spans_with_counts
             .iter()
             .map(|(span, _)| self.tcx.sess.source_map().span_to_snippet(*span).ok())
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs
index 59c2db25b8e..11f80b314d7 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_resolve/src/late/lifetimes.rs
@@ -8,19 +8,19 @@
 
 use crate::late::diagnostics::{ForLifetimeSpanType, MissingLifetimeSpot};
 use rustc_ast::walk_list;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefIdMap, LocalDefId};
 use rustc_hir::hir_id::ItemLocalId;
 use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::{GenericArg, GenericParam, LifetimeName, Node, ParamName};
-use rustc_hir::{GenericParamKind, HirIdMap, HirIdSet};
+use rustc_hir::{GenericArg, GenericParam, LifetimeName, Node};
+use rustc_hir::{GenericParamKind, HirIdMap};
 use rustc_middle::hir::map::Map;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::resolve_lifetime::*;
-use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, TyCtxt};
+use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_span::def_id::DefId;
 use rustc_span::symbol::{kw, sym, Ident};
@@ -33,9 +33,9 @@ use std::mem::take;
 use tracing::{debug, span, Level};
 
 trait RegionExt {
-    fn early(hir_map: Map<'_>, index: &mut u32, param: &GenericParam<'_>) -> (ParamName, Region);
+    fn early(hir_map: Map<'_>, index: &mut u32, param: &GenericParam<'_>) -> (LocalDefId, Region);
 
-    fn late(index: u32, hir_map: Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region);
+    fn late(index: u32, hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region);
 
     fn late_anon(named_late_bound_vars: u32, index: &Cell<u32>) -> Region;
 
@@ -51,22 +51,22 @@ trait RegionExt {
 }
 
 impl RegionExt for Region {
-    fn early(hir_map: Map<'_>, index: &mut u32, param: &GenericParam<'_>) -> (ParamName, Region) {
+    fn early(hir_map: Map<'_>, index: &mut u32, param: &GenericParam<'_>) -> (LocalDefId, Region) {
         let i = *index;
         *index += 1;
         let def_id = hir_map.local_def_id(param.hir_id);
         debug!("Region::early: index={} def_id={:?}", i, def_id);
-        (param.name.normalize_to_macros_2_0(), Region::EarlyBound(i, def_id.to_def_id()))
+        (def_id, Region::EarlyBound(i, def_id.to_def_id()))
     }
 
-    fn late(idx: u32, hir_map: Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region) {
+    fn late(idx: u32, hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region) {
         let depth = ty::INNERMOST;
         let def_id = hir_map.local_def_id(param.hir_id);
         debug!(
             "Region::late: idx={:?}, param={:?} depth={:?} def_id={:?}",
             idx, param, depth, def_id,
         );
-        (param.name.normalize_to_macros_2_0(), Region::LateBound(depth, idx, def_id.to_def_id()))
+        (def_id, Region::LateBound(depth, idx, def_id.to_def_id()))
     }
 
     fn late_anon(named_late_bound_vars: u32, index: &Cell<u32>) -> Region {
@@ -134,11 +134,6 @@ struct NamedRegionMap {
     // `Region` describing how that region is bound
     defs: HirIdMap<Region>,
 
-    // the set of lifetime def ids that are late-bound; a region can
-    // be late-bound if (a) it does NOT appear in a where-clause and
-    // (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
@@ -178,7 +173,7 @@ enum Scope<'a> {
     Binder {
         /// We use an IndexMap here because we want these lifetimes in order
         /// for diagnostics.
-        lifetimes: FxIndexMap<hir::ParamName, Region>,
+        lifetimes: FxIndexMap<LocalDefId, Region>,
 
         /// if we extend this scope with another scope, what is the next index
         /// we should use for an early-bound region?
@@ -402,7 +397,7 @@ fn resolve_lifetimes_trait_definition(
     tcx: TyCtxt<'_>,
     local_def_id: LocalDefId,
 ) -> ResolveLifetimes {
-    convert_named_region_map(tcx, do_resolve(tcx, local_def_id, true, false))
+    convert_named_region_map(do_resolve(tcx, local_def_id, true, false))
 }
 
 /// Computes the `ResolveLifetimes` map that contains data for an entire `Item`.
@@ -410,7 +405,7 @@ fn resolve_lifetimes_trait_definition(
 /// `named_region_map`, `is_late_bound_map`, etc.
 #[tracing::instrument(level = "debug", skip(tcx))]
 fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> ResolveLifetimes {
-    convert_named_region_map(tcx, do_resolve(tcx, local_def_id, false, false))
+    convert_named_region_map(do_resolve(tcx, local_def_id, false, false))
 }
 
 fn do_resolve(
@@ -422,7 +417,6 @@ fn do_resolve(
     let item = tcx.hir().expect_item(local_def_id);
     let mut named_region_map = NamedRegionMap {
         defs: Default::default(),
-        late_bound: Default::default(),
         late_bound_vars: Default::default(),
         scope_for_path: with_scope_for_path.then(|| Default::default()),
     };
@@ -439,18 +433,13 @@ fn do_resolve(
     named_region_map
 }
 
-fn convert_named_region_map(tcx: TyCtxt<'_>, named_region_map: NamedRegionMap) -> ResolveLifetimes {
+fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetimes {
     let mut rl = ResolveLifetimes::default();
 
     for (hir_id, v) in named_region_map.defs {
         let map = rl.defs.entry(hir_id.owner).or_default();
         map.insert(hir_id.local_id, v);
     }
-    for hir_id in named_region_map.late_bound {
-        let map = rl.late_bound.entry(hir_id.owner).or_default();
-        let def_id = tcx.hir().local_def_id(hir_id);
-        map.insert(def_id);
-    }
     for (hir_id, v) in named_region_map.late_bound_vars {
         let map = rl.late_bound_vars.entry(hir_id.owner).or_default();
         map.insert(hir_id.local_id, v);
@@ -506,28 +495,6 @@ fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId {
     item
 }
 
-fn is_late_bound_map<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    def_id: LocalDefId,
-) -> Option<(LocalDefId, &'tcx FxHashSet<LocalDefId>)> {
-    match tcx.def_kind(def_id) {
-        DefKind::AnonConst | DefKind::InlineConst => {
-            let mut def_id = tcx.local_parent(def_id);
-            // We search for the next outer anon const or fn here
-            // while skipping closures.
-            //
-            // Note that for `AnonConst` we still just recurse until we
-            // find a function body, but who cares :shrug:
-            while tcx.is_closure(def_id.to_def_id()) {
-                def_id = tcx.local_parent(def_id);
-            }
-
-            tcx.is_late_bound_map(def_id)
-        }
-        _ => resolve_lifetimes_for(tcx, def_id).late_bound.get(&def_id).map(|lt| (def_id, lt)),
-    }
-}
-
 /// In traits, there is an implicit `Self` type parameter which comes before the generics.
 /// We have to account for this when computing the index of the other generic parameters.
 /// This function returns whether there is such an implicit parameter defined on the given item.
@@ -554,10 +521,7 @@ fn get_lifetime_scopes_for_path(mut scope: &Scope<'_>) -> LifetimeScopeForPath {
     loop {
         match scope {
             Scope::Binder { lifetimes, s, .. } => {
-                available_lifetimes.extend(lifetimes.keys().filter_map(|p| match p {
-                    hir::ParamName::Plain(ident) => Some(ident.name),
-                    _ => None,
-                }));
+                available_lifetimes.extend(lifetimes.keys());
                 scope = s;
             }
             Scope::Body { s, .. } => {
@@ -690,9 +654,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             _ => {}
         }
         match item.kind {
-            hir::ItemKind::Fn(ref sig, ref generics, _) => {
+            hir::ItemKind::Fn(_, ref generics, _) => {
                 self.missing_named_lifetime_spots.push(generics.into());
-                self.visit_early_late(None, item.hir_id(), &sig.decl, generics, |this| {
+                self.visit_early_late(None, item.hir_id(), generics, |this| {
                     intravisit::walk_item(this, item);
                 });
                 self.missing_named_lifetime_spots.pop();
@@ -734,13 +698,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                                     self.map.defs.insert(hir::HirId { owner, local_id }, *region);
                                 });
                             }
-                            for (&owner, late_bound) in resolved_lifetimes.late_bound.iter() {
-                                late_bound.iter().for_each(|&id| {
-                                    let hir_id = self.tcx.local_def_id_to_hir_id(id);
-                                    debug_assert_eq!(owner, hir_id.owner);
-                                    self.map.late_bound.insert(hir_id);
-                                });
-                            }
                             for (&owner, late_bound_vars) in
                                 resolved_lifetimes.late_bound_vars.iter()
                             {
@@ -810,8 +767,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
 
     fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
         match item.kind {
-            hir::ForeignItemKind::Fn(ref decl, _, ref generics) => {
-                self.visit_early_late(None, item.hir_id(), decl, generics, |this| {
+            hir::ForeignItemKind::Fn(_, _, ref generics) => {
+                self.visit_early_late(None, item.hir_id(), generics, |this| {
                     intravisit::walk_foreign_item(this, item);
                 })
             }
@@ -841,7 +798,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 };
                 self.missing_named_lifetime_spots
                     .push(MissingLifetimeSpot::HigherRanked { span, span_type });
-                let (lifetimes, binders): (FxIndexMap<hir::ParamName, Region>, Vec<_>) = c
+                let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) = c
                     .generic_params
                     .iter()
                     .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
@@ -898,7 +855,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                         // cc #48468
                         self.resolve_elided_lifetimes(&[lifetime])
                     }
-                    LifetimeName::Param(_) | LifetimeName::Static => {
+                    LifetimeName::Param(..) | LifetimeName::Static => {
                         // If the user wrote an explicit name, use that.
                         self.visit_lifetime(lifetime);
                     }
@@ -1016,17 +973,17 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 for param in generics.params {
                     match param.kind {
                         GenericParamKind::Lifetime { .. } => {
-                            let (name, reg) = Region::early(self.tcx.hir(), &mut index, &param);
+                            let (def_id, reg) = Region::early(self.tcx.hir(), &mut index, &param);
                             if let hir::ParamName::Plain(Ident {
                                 name: kw::UnderscoreLifetime,
                                 ..
-                            }) = name
+                            }) = param.name
                             {
                                 // Pick the elided lifetime "definition" if one exists
                                 // and use it to make an elision scope.
                                 elision = Some(reg);
                             } else {
-                                lifetimes.insert(name, reg);
+                                lifetimes.insert(def_id, reg);
                             }
                         }
                         GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
@@ -1088,13 +1045,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
         use self::hir::TraitItemKind::*;
         match trait_item.kind {
-            Fn(ref sig, _) => {
+            Fn(_, _) => {
                 self.missing_named_lifetime_spots.push((&trait_item.generics).into());
                 let tcx = self.tcx;
                 self.visit_early_late(
                     Some(tcx.hir().get_parent_item(trait_item.hir_id())),
                     trait_item.hir_id(),
-                    &sig.decl,
                     &trait_item.generics,
                     |this| intravisit::walk_trait_item(this, trait_item),
                 );
@@ -1156,13 +1112,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         use self::hir::ImplItemKind::*;
         match impl_item.kind {
-            Fn(ref sig, _) => {
+            Fn(..) => {
                 self.missing_named_lifetime_spots.push((&impl_item.generics).into());
                 let tcx = self.tcx;
                 self.visit_early_late(
                     Some(tcx.hir().get_parent_item(impl_item.hir_id())),
                     impl_item.hir_id(),
-                    &sig.decl,
                     &impl_item.generics,
                     |this| intravisit::walk_impl_item(this, impl_item),
                 );
@@ -1174,7 +1129,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 let mut index = self.next_early_index();
                 let mut non_lifetime_count = 0;
                 debug!("visit_ty: index = {}", index);
-                let lifetimes: FxIndexMap<hir::ParamName, Region> = generics
+                let lifetimes: FxIndexMap<LocalDefId, Region> = generics
                     .params
                     .iter()
                     .filter_map(|param| match param.kind {
@@ -1218,15 +1173,17 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
 
     #[tracing::instrument(level = "debug", skip(self))]
     fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
-        if lifetime_ref.is_elided() {
-            self.resolve_elided_lifetimes(&[lifetime_ref]);
-            return;
-        }
-        if lifetime_ref.is_static() {
-            self.insert_lifetime(lifetime_ref, Region::Static);
-            return;
+        match lifetime_ref.name {
+            hir::LifetimeName::ImplicitObjectLifetimeDefault
+            | hir::LifetimeName::Implicit
+            | hir::LifetimeName::Underscore => self.resolve_elided_lifetimes(&[lifetime_ref]),
+            hir::LifetimeName::Static => self.insert_lifetime(lifetime_ref, Region::Static),
+            hir::LifetimeName::Param(param_def_id, _) => {
+                self.resolve_lifetime_ref(param_def_id, lifetime_ref)
+            }
+            // If we've already reported an error, just ignore `lifetime_ref`.
+            hir::LifetimeName::Error => {}
         }
-        self.resolve_lifetime_ref(lifetime_ref);
     }
 
     fn visit_assoc_type_binding(&mut self, type_binding: &'tcx hir::TypeBinding<'_>) {
@@ -1311,7 +1268,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                         ref bound_generic_params,
                         ..
                     }) => {
-                        let (lifetimes, binders): (FxIndexMap<hir::ParamName, Region>, Vec<_>) =
+                        let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) =
                             bound_generic_params
                                 .iter()
                                 .filter(|param| {
@@ -1433,7 +1390,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
         let (mut binders, scope_type) = self.poly_trait_ref_binder_info();
 
         let initial_bound_vars = binders.len() as u32;
-        let mut lifetimes: FxIndexMap<hir::ParamName, Region> = FxIndexMap::default();
+        let mut lifetimes: FxIndexMap<LocalDefId, Region> = FxIndexMap::default();
         let binders_iter = trait_ref
             .bound_generic_params
             .iter()
@@ -1580,14 +1537,17 @@ fn object_lifetime_defaults_for_item<'tcx>(
                             .iter()
                             .filter_map(|param| match param.kind {
                                 GenericParamKind::Lifetime { .. } => {
-                                    Some((param.hir_id, hir::LifetimeName::Param(param.name)))
+                                    let param_def_id = tcx.hir().local_def_id(param.hir_id);
+                                    Some((
+                                        param_def_id,
+                                        hir::LifetimeName::Param(param_def_id, param.name),
+                                    ))
                                 }
                                 _ => None,
                             })
                             .enumerate()
                             .find(|&(_, (_, lt_name))| lt_name == name)
-                            .map_or(Set1::Many, |(i, (id, _))| {
-                                let def_id = tcx.hir().local_def_id(id);
+                            .map_or(Set1::Many, |(i, (def_id, _))| {
                                 Set1::One(Region::EarlyBound(i as u32, def_id.to_def_id()))
                             })
                     }
@@ -1654,14 +1614,11 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         &mut self,
         parent_id: Option<LocalDefId>,
         hir_id: hir::HirId,
-        decl: &'tcx hir::FnDecl<'tcx>,
         generics: &'tcx hir::Generics<'tcx>,
         walk: F,
     ) where
         F: for<'b, 'c> FnOnce(&'b mut LifetimeContext<'c, 'tcx>),
     {
-        insert_late_bound_lifetimes(self.map, decl, generics);
-
         // Find the start of nested early scopes, e.g., in methods.
         let mut next_early_index = 0;
         if let Some(parent_id) = parent_id {
@@ -1680,12 +1637,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
 
         let mut non_lifetime_count = 0;
         let mut named_late_bound_vars = 0;
-        let lifetimes: FxIndexMap<hir::ParamName, Region> = generics
+        let lifetimes: FxIndexMap<LocalDefId, Region> = generics
             .params
             .iter()
             .filter_map(|param| match param.kind {
                 GenericParamKind::Lifetime { .. } => {
-                    if self.map.late_bound.contains(&param.hir_id) {
+                    if self.tcx.is_late_bound(param.hir_id) {
                         let late_bound_idx = named_late_bound_vars;
                         named_late_bound_vars += 1;
                         Some(Region::late(late_bound_idx, self.tcx.hir(), param))
@@ -1706,7 +1663,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             .iter()
             .filter(|param| {
                 matches!(param.kind, GenericParamKind::Lifetime { .. })
-                    && self.map.late_bound.contains(&param.hir_id)
+                    && self.tcx.is_late_bound(param.hir_id)
             })
             .enumerate()
             .map(|(late_bound_idx, param)| {
@@ -1763,14 +1720,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         self.next_early_index_helper(false)
     }
 
-    fn resolve_lifetime_ref(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
-        debug!("resolve_lifetime_ref(lifetime_ref={:?})", lifetime_ref);
-
-        // If we've already reported an error, just ignore `lifetime_ref`.
-        if let LifetimeName::Error = lifetime_ref.name {
-            return;
-        }
-
+    #[tracing::instrument(level = "debug", skip(self))]
+    fn resolve_lifetime_ref(
+        &mut self,
+        region_def_id: LocalDefId,
+        lifetime_ref: &'tcx hir::Lifetime,
+    ) {
         // Walk up the scope chain, tracking the number of fn scopes
         // that we pass through, until we find a lifetime with the
         // given name or we run out of scopes.
@@ -1790,14 +1745,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                 }
 
                 Scope::Binder { ref lifetimes, scope_type, s, .. } => {
-                    match lifetime_ref.name {
-                        LifetimeName::Param(param_name) => {
-                            if let Some(&def) = lifetimes.get(&param_name.normalize_to_macros_2_0())
-                            {
-                                break Some(def.shifted(late_depth));
-                            }
-                        }
-                        _ => bug!("expected LifetimeName::Param"),
+                    if let Some(&def) = lifetimes.get(&region_def_id) {
+                        break Some(def.shifted(late_depth));
                     }
                     match scope_type {
                         BinderScopeType::Normal => late_depth += 1,
@@ -2473,8 +2422,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
 
         let mut late_depth = 0;
         let mut scope = self.scope;
-        let mut lifetime_names = FxHashSet::default();
-        let mut lifetime_spans = vec![];
+        let mut in_scope_lifetimes = FxIndexSet::default();
         let error = loop {
             match *scope {
                 // Do not assign any resolution, it will be inferred.
@@ -2484,12 +2432,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
 
                 Scope::Binder { s, ref lifetimes, scope_type, .. } => {
                     // collect named lifetimes for suggestions
-                    for name in lifetimes.keys() {
-                        if let hir::ParamName::Plain(name) = name {
-                            lifetime_names.insert(name.name);
-                            lifetime_spans.push(name.span);
-                        }
-                    }
+                    in_scope_lifetimes.extend(lifetimes.keys().copied());
                     match scope_type {
                         BinderScopeType::Normal => late_depth += 1,
                         BinderScopeType::Concatenating => {}
@@ -2524,12 +2467,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                         match scope {
                             Scope::Binder { ref lifetimes, s, .. } => {
                                 // Collect named lifetimes for suggestions.
-                                for name in lifetimes.keys() {
-                                    if let hir::ParamName::Plain(name) = name {
-                                        lifetime_names.insert(name.name);
-                                        lifetime_spans.push(name.span);
-                                    }
-                                }
+                                in_scope_lifetimes.extend(lifetimes.keys().copied());
                                 scope = s;
                             }
                             Scope::ObjectLifetimeDefault { ref s, .. }
@@ -2574,19 +2512,11 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
 
         let mut err = self.report_missing_lifetime_specifiers(spans.clone(), lifetime_refs.len());
 
-        if let Some(params) = error {
-            // If there's no lifetime available, suggest `'static`.
-            if self.report_elision_failure(&mut err, params) && lifetime_names.is_empty() {
-                lifetime_names.insert(kw::StaticLifetime);
-            }
-        }
-
         self.add_missing_lifetime_specifiers_label(
             &mut err,
             spans_with_counts,
-            &lifetime_names,
-            lifetime_spans,
-            error.unwrap_or(&[]),
+            in_scope_lifetimes,
+            error,
         );
         err.emit();
     }
@@ -2638,7 +2568,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
 }
 
 /// Detects late-bound lifetimes and inserts them into
-/// `map.late_bound`.
+/// `late_bound`.
 ///
 /// A region declared on a fn is **late-bound** if:
 /// - it is constrained by an argument type;
@@ -2647,12 +2577,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
 /// "Constrained" basically means that it appears in any type but
 /// not amongst the inputs to a projection. In other words, `<&'a
 /// T as Trait<''b>>::Foo` does not constrain `'a` or `'b`.
-#[tracing::instrument(level = "debug", skip(map))]
-fn insert_late_bound_lifetimes(
-    map: &mut NamedRegionMap,
-    decl: &hir::FnDecl<'_>,
-    generics: &hir::Generics<'_>,
-) {
+fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxHashSet<LocalDefId>> {
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+    let decl = tcx.hir().fn_decl_by_hir_id(hir_id)?;
+    let generics = tcx.hir().get_generics(def_id)?;
+
+    let mut late_bound = FxHashSet::default();
+
     let mut constrained_by_input = ConstrainedCollector::default();
     for arg_ty in decl.inputs {
         constrained_by_input.visit_ty(arg_ty);
@@ -2683,30 +2614,32 @@ fn insert_late_bound_lifetimes(
             hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => continue,
         }
 
-        let lt_name = hir::LifetimeName::Param(param.name.normalize_to_macros_2_0());
+        let param_def_id = tcx.hir().local_def_id(param.hir_id);
+
         // appears in the where clauses? early-bound.
-        if appears_in_where_clause.regions.contains(&lt_name) {
+        if appears_in_where_clause.regions.contains(&param_def_id) {
             continue;
         }
 
         // does not appear in the inputs, but appears in the return type? early-bound.
-        if !constrained_by_input.regions.contains(&lt_name)
-            && appears_in_output.regions.contains(&lt_name)
+        if !constrained_by_input.regions.contains(&param_def_id)
+            && appears_in_output.regions.contains(&param_def_id)
         {
             continue;
         }
 
         debug!("lifetime {:?} with id {:?} is late-bound", param.name.ident(), param.hir_id);
 
-        let inserted = map.late_bound.insert(param.hir_id);
+        let inserted = late_bound.insert(param_def_id);
         assert!(inserted, "visited lifetime {:?} twice", param.hir_id);
     }
 
-    return;
+    debug!(?late_bound);
+    return Some(tcx.arena.alloc(late_bound));
 
     #[derive(Default)]
     struct ConstrainedCollector {
-        regions: FxHashSet<hir::LifetimeName>,
+        regions: FxHashSet<LocalDefId>,
     }
 
     impl<'v> Visitor<'v> for ConstrainedCollector {
@@ -2738,18 +2671,22 @@ fn insert_late_bound_lifetimes(
         }
 
         fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
-            self.regions.insert(lifetime_ref.name.normalize_to_macros_2_0());
+            if let hir::LifetimeName::Param(def_id, _) = lifetime_ref.name {
+                self.regions.insert(def_id);
+            }
         }
     }
 
     #[derive(Default)]
     struct AllCollector {
-        regions: FxHashSet<hir::LifetimeName>,
+        regions: FxHashSet<LocalDefId>,
     }
 
     impl<'v> Visitor<'v> for AllCollector {
         fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
-            self.regions.insert(lifetime_ref.name.normalize_to_macros_2_0());
+            if let hir::LifetimeName::Param(def_id, _) = lifetime_ref.name {
+                self.regions.insert(def_id);
+            }
         }
     }
 }
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 96d083bb94f..bcff2ae5129 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -16,7 +16,7 @@ use crate::require_c_abi_if_c_variadic;
 use rustc_ast::TraitObjectSyntax;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{
-    struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError,
+    struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, MultiSpan,
 };
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
@@ -30,7 +30,7 @@ use rustc_middle::ty::{self, Const, DefIdTree, EarlyBinder, Ty, TyCtxt, TypeFold
 use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS};
 use rustc_span::edition::Edition;
 use rustc_span::lev_distance::find_best_match_for_name;
-use rustc_span::symbol::{Ident, Symbol};
+use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::spec::abi;
 use rustc_trait_selection::traits;
@@ -653,7 +653,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             span, item_def_id, item_segment
         );
         if tcx.generics_of(item_def_id).params.is_empty() {
-            self.prohibit_generics(slice::from_ref(item_segment));
+            self.prohibit_generics(slice::from_ref(item_segment).iter(), |_| {});
 
             parent_substs
         } else {
@@ -681,7 +681,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         trait_ref: &hir::TraitRef<'_>,
         self_ty: Ty<'tcx>,
     ) -> ty::TraitRef<'tcx> {
-        self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
+        self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {});
 
         self.ast_path_to_mono_trait_ref(
             trait_ref.path.span,
@@ -784,7 +784,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let args = trait_segment.args();
         let infer_args = trait_segment.infer_args;
 
-        self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
+        self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {});
         self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, false);
 
         self.instantiate_poly_trait_ref_inner(
@@ -1776,12 +1776,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         hir_ref_id: hir::HirId,
         span: Span,
         qself_ty: Ty<'tcx>,
-        qself_res: Res,
+        qself: &hir::Ty<'_>,
         assoc_segment: &hir::PathSegment<'_>,
         permit_variants: bool,
     ) -> Result<(Ty<'tcx>, DefKind, DefId), ErrorGuaranteed> {
         let tcx = self.tcx();
         let assoc_ident = assoc_segment.ident;
+        let qself_res = if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = qself.kind {
+            path.res
+        } else {
+            Res::Err
+        };
 
         debug!("associated_path_to_ty: {:?}::{}", qself_ty, assoc_ident);
 
@@ -1796,7 +1801,87 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 if let Some(variant_def) = variant_def {
                     if permit_variants {
                         tcx.check_stability(variant_def.def_id, Some(hir_ref_id), span, None);
-                        self.prohibit_generics(slice::from_ref(assoc_segment));
+                        self.prohibit_generics(slice::from_ref(assoc_segment).iter(), |err| {
+                            err.note("enum variants can't have type parameters");
+                            let type_name = tcx.item_name(adt_def.did());
+                            let msg = format!(
+                                "you might have meant to specity type parameters on enum \
+                                 `{type_name}`"
+                            );
+                            let Some(args) = assoc_segment.args else { return; };
+                            // Get the span of the generics args *including* the leading `::`.
+                            let args_span = assoc_segment.ident.span.shrink_to_hi().to(args.span_ext);
+                            if tcx.generics_of(adt_def.did()).count() == 0 {
+                                // FIXME(estebank): we could also verify that the arguments being
+                                // work for the `enum`, instead of just looking if it takes *any*.
+                                err.span_suggestion_verbose(
+                                    args_span,
+                                    &format!("{type_name} doesn't have generic parameters"),
+                                    String::new(),
+                                    Applicability::MachineApplicable,
+                                );
+                                return;
+                            }
+                            let Ok(snippet) = tcx.sess.source_map().span_to_snippet(args_span) else {
+                                err.note(&msg);
+                                return;
+                            };
+                            let (qself_sugg_span, is_self) = if let hir::TyKind::Path(
+                                hir::QPath::Resolved(_, ref path)
+                            ) = qself.kind {
+                                // If the path segment already has type params, we want to overwrite
+                                // them.
+                                match &path.segments[..] {
+                                    // `segment` is the previous to last element on the path,
+                                    // which would normally be the `enum` itself, while the last
+                                    // `_` `PathSegment` corresponds to the variant.
+                                    [.., hir::PathSegment {
+                                        ident,
+                                        args,
+                                        res: Some(Res::Def(DefKind::Enum, _)),
+                                        ..
+                                    }, _] => (
+                                        // We need to include the `::` in `Type::Variant::<Args>`
+                                        // to point the span to `::<Args>`, not just `<Args>`.
+                                        ident.span.shrink_to_hi().to(args.map_or(
+                                            ident.span.shrink_to_hi(),
+                                            |a| a.span_ext)),
+                                        false,
+                                    ),
+                                    [segment] => (
+                                        // We need to include the `::` in `Type::Variant::<Args>`
+                                        // to point the span to `::<Args>`, not just `<Args>`.
+                                        segment.ident.span.shrink_to_hi().to(segment.args.map_or(
+                                            segment.ident.span.shrink_to_hi(),
+                                            |a| a.span_ext)),
+                                        kw::SelfUpper == segment.ident.name,
+                                    ),
+                                    _ => {
+                                        err.note(&msg);
+                                        return;
+                                    }
+                                }
+                            } else {
+                                err.note(&msg);
+                                return;
+                            };
+                            let suggestion = vec![
+                                if is_self {
+                                    // Account for people writing `Self::Variant::<Args>`, where
+                                    // `Self` is the enum, and suggest replacing `Self` with the
+                                    // appropriate type: `Type::<Args>::Variant`.
+                                    (qself.span, format!("{type_name}{snippet}"))
+                                } else {
+                                    (qself_sugg_span, snippet)
+                                },
+                                (args_span, String::new()),
+                            ];
+                            err.multipart_suggestion_verbose(
+                                &msg,
+                                suggestion,
+                                Applicability::MaybeIncorrect,
+                            );
+                        });
                         return Ok((qself_ty, DefKind::Variant, variant_def.def_id));
                     } else {
                         variant_resolution = Some(variant_def.def_id);
@@ -2017,69 +2102,112 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         self.normalize_ty(span, tcx.mk_projection(item_def_id, item_substs))
     }
 
-    pub fn prohibit_generics<'a, T: IntoIterator<Item = &'a hir::PathSegment<'a>>>(
+    pub fn prohibit_generics<'a>(
         &self,
-        segments: T,
+        segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
+        extend: impl Fn(&mut DiagnosticBuilder<'tcx, ErrorGuaranteed>),
     ) -> bool {
-        let mut has_err = false;
-        for segment in segments {
-            let (mut err_for_lt, mut err_for_ty, mut err_for_ct) = (false, false, false);
-            for arg in segment.args().args {
-                let (span, kind) = match arg {
-                    hir::GenericArg::Lifetime(lt) => {
-                        if err_for_lt {
-                            continue;
-                        }
-                        err_for_lt = true;
-                        has_err = true;
-                        (lt.span, "lifetime")
-                    }
-                    hir::GenericArg::Type(ty) => {
-                        if err_for_ty {
-                            continue;
-                        }
-                        err_for_ty = true;
-                        has_err = true;
-                        (ty.span, "type")
-                    }
-                    hir::GenericArg::Const(ct) => {
-                        if err_for_ct {
-                            continue;
-                        }
-                        err_for_ct = true;
-                        has_err = true;
-                        (ct.span, "const")
-                    }
-                    hir::GenericArg::Infer(inf) => {
-                        if err_for_ty {
-                            continue;
-                        }
-                        has_err = true;
-                        err_for_ty = true;
-                        (inf.span, "generic")
+        let args = segments.clone().flat_map(|segment| segment.args().args);
+        let types_and_spans: Vec<_> = segments
+            .clone()
+            .flat_map(|segment| {
+                segment.res.and_then(|res| {
+                    if segment.args().args.is_empty() {
+                        None
+                    } else {
+                        Some((
+                            match res {
+                                Res::PrimTy(ty) => format!("{} `{}`", res.descr(), ty.name()),
+                                Res::Def(_, def_id)
+                                if let Some(name) = self.tcx().opt_item_name(def_id) => {
+                                    format!("{} `{name}`", res.descr())
+                                }
+                                Res::Err => "this type".to_string(),
+                                _ => res.descr().to_string(),
+                            },
+                            segment.ident.span,
+                        ))
                     }
-                };
-                let mut err = struct_span_err!(
-                    self.tcx().sess,
-                    span,
-                    E0109,
-                    "{} arguments are not allowed for this type",
-                    kind,
-                );
-                err.span_label(span, format!("{} argument not allowed", kind));
-                err.emit();
-                if err_for_lt && err_for_ty && err_for_ct {
-                    break;
-                }
+                })
+            })
+            .collect();
+        let this_type = match &types_and_spans[..] {
+            [.., _, (last, _)] => format!(
+                "{} and {last}",
+                types_and_spans[..types_and_spans.len() - 1]
+                    .iter()
+                    .map(|(x, _)| x.as_str())
+                    .intersperse(&", ")
+                    .collect::<String>()
+            ),
+            [(only, _)] => only.to_string(),
+            [] => "this type".to_string(),
+        };
+
+        let (lt, ty, ct, inf) =
+            args.clone().fold((false, false, false, false), |(lt, ty, ct, inf), arg| match arg {
+                hir::GenericArg::Lifetime(_) => (true, ty, ct, inf),
+                hir::GenericArg::Type(_) => (lt, true, ct, inf),
+                hir::GenericArg::Const(_) => (lt, ty, true, inf),
+                hir::GenericArg::Infer(_) => (lt, ty, ct, true),
+            });
+        let mut emitted = false;
+        if lt || ty || ct || inf {
+            let arg_spans: Vec<Span> = args.map(|arg| arg.span()).collect();
+
+            let mut kinds = Vec::with_capacity(4);
+            if lt {
+                kinds.push("lifetime");
+            }
+            if ty {
+                kinds.push("type");
+            }
+            if ct {
+                kinds.push("const");
             }
+            if inf {
+                kinds.push("generic");
+            }
+            let (kind, s) = match kinds[..] {
+                [.., _, last] => (
+                    format!(
+                        "{} and {last}",
+                        kinds[..kinds.len() - 1]
+                            .iter()
+                            .map(|&x| x)
+                            .intersperse(", ")
+                            .collect::<String>()
+                    ),
+                    "s",
+                ),
+                [only] => (format!("{only}"), ""),
+                [] => unreachable!(),
+            };
+            let last_span = *arg_spans.last().unwrap();
+            let span: MultiSpan = arg_spans.into();
+            let mut err = struct_span_err!(
+                self.tcx().sess,
+                span,
+                E0109,
+                "{kind} arguments are not allowed on {this_type}",
+            );
+            err.span_label(last_span, format!("{kind} argument{s} not allowed"));
+            for (_, span) in types_and_spans {
+                err.span_label(span, "not allowed on this");
+            }
+            extend(&mut err);
+            err.emit();
+            emitted = true;
+        }
 
+        for segment in segments {
             // Only emit the first error to avoid overloading the user with error messages.
             if let [binding, ..] = segment.args().bindings {
-                has_err = true;
                 Self::prohibit_assoc_ty_binding(self.tcx(), binding.span);
+                return true;
             }
         }
-        has_err
+        emitted
     }
 
     // FIXME(eddyb, varkor) handle type paths here too, not just value ones.
@@ -2229,7 +2357,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 // Check for desugared `impl Trait`.
                 assert!(ty::is_impl_trait_defn(tcx, did).is_none());
                 let item_segment = path.segments.split_last().unwrap();
-                self.prohibit_generics(item_segment.1);
+                self.prohibit_generics(item_segment.1.iter(), |err| {
+                    err.note("`impl Trait` types can't have type parameters");
+                });
                 let substs = self.ast_path_substs_for_ty(span, did, item_segment.0);
                 self.normalize_ty(span, tcx.mk_opaque(did, substs))
             }
@@ -2242,7 +2372,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 did,
             ) => {
                 assert_eq!(opt_self_ty, None);
-                self.prohibit_generics(path.segments.split_last().unwrap().1);
+                self.prohibit_generics(path.segments.split_last().unwrap().1.iter(), |_| {});
                 self.ast_path_to_ty(span, did, path.segments.last().unwrap())
             }
             Res::Def(kind @ DefKind::Variant, def_id) if permit_variants => {
@@ -2254,18 +2384,26 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     self.def_ids_for_value_path_segments(path.segments, None, kind, def_id);
                 let generic_segs: FxHashSet<_> =
                     path_segs.iter().map(|PathSeg(_, index)| index).collect();
-                self.prohibit_generics(path.segments.iter().enumerate().filter_map(
-                    |(index, seg)| {
+                self.prohibit_generics(
+                    path.segments.iter().enumerate().filter_map(|(index, seg)| {
                         if !generic_segs.contains(&index) { Some(seg) } else { None }
+                    }),
+                    |err| {
+                        err.note("enum variants can't have type parameters");
                     },
-                ));
+                );
 
                 let PathSeg(def_id, index) = path_segs.last().unwrap();
                 self.ast_path_to_ty(span, *def_id, &path.segments[*index])
             }
             Res::Def(DefKind::TyParam, def_id) => {
                 assert_eq!(opt_self_ty, None);
-                self.prohibit_generics(path.segments);
+                self.prohibit_generics(path.segments.iter(), |err| {
+                    if let Some(span) = tcx.def_ident_span(def_id) {
+                        let name = tcx.item_name(def_id);
+                        err.span_note(span, &format!("type parameter `{name}` defined here"));
+                    }
+                });
 
                 let def_id = def_id.expect_local();
                 let item_def_id = tcx.hir().ty_param_owner(def_id);
@@ -2276,15 +2414,81 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             Res::SelfTy { trait_: Some(_), alias_to: None } => {
                 // `Self` in trait or type alias.
                 assert_eq!(opt_self_ty, None);
-                self.prohibit_generics(path.segments);
+                self.prohibit_generics(path.segments.iter(), |err| {
+                    if let [hir::PathSegment { args: Some(args), ident, .. }] = &path.segments[..] {
+                        err.span_suggestion_verbose(
+                            ident.span.shrink_to_hi().to(args.span_ext),
+                            "the `Self` type doesn't accept type parameters",
+                            String::new(),
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                });
                 tcx.types.self_param
             }
             Res::SelfTy { trait_: _, alias_to: Some((def_id, forbid_generic)) } => {
                 // `Self` in impl (we know the concrete type).
                 assert_eq!(opt_self_ty, None);
-                self.prohibit_generics(path.segments);
                 // Try to evaluate any array length constants.
                 let ty = tcx.at(span).type_of(def_id);
+                let span_of_impl = tcx.span_of_impl(def_id);
+                self.prohibit_generics(path.segments.iter(), |err| {
+                    let def_id = match *ty.kind() {
+                        ty::Adt(self_def, _) => self_def.did(),
+                        _ => return,
+                    };
+
+                    let type_name = tcx.item_name(def_id);
+                    let span_of_ty = tcx.def_ident_span(def_id);
+                    let generics = tcx.generics_of(def_id).count();
+
+                    let msg = format!("`Self` is of type `{ty}`");
+                    if let (Ok(i_sp), Some(t_sp)) = (span_of_impl, span_of_ty) {
+                        let i_sp = tcx.sess.source_map().guess_head_span(i_sp);
+                        let mut span: MultiSpan = vec![t_sp].into();
+                        span.push_span_label(
+                            i_sp,
+                            &format!("`Self` is on type `{type_name}` in this `impl`"),
+                        );
+                        let mut postfix = "";
+                        if generics == 0 {
+                            postfix = ", which doesn't have generic parameters";
+                        }
+                        span.push_span_label(
+                            t_sp,
+                            &format!("`Self` corresponds to this type{postfix}"),
+                        );
+                        err.span_note(span, &msg);
+                    } else {
+                        err.note(&msg);
+                    }
+                    for segment in path.segments {
+                        if let Some(args) = segment.args && segment.ident.name == kw::SelfUpper {
+                            if generics == 0 {
+                                // FIXME(estebank): we could also verify that the arguments being
+                                // work for the `enum`, instead of just looking if it takes *any*.
+                                err.span_suggestion_verbose(
+                                    segment.ident.span.shrink_to_hi().to(args.span_ext),
+                                    "the `Self` type doesn't accept type parameters",
+                                    String::new(),
+                                    Applicability::MachineApplicable,
+                                );
+                                return;
+                            } else {
+                                err.span_suggestion_verbose(
+                                    segment.ident.span,
+                                    format!(
+                                        "the `Self` type doesn't accept type parameters, use the \
+                                        concrete type's name `{type_name}` instead if you want to \
+                                        specify its type parameters"
+                                    ),
+                                    type_name.to_string(),
+                                    Applicability::MaybeIncorrect,
+                                );
+                            }
+                        }
+                    }
+                });
                 // HACK(min_const_generics): Forbid generic `Self` types
                 // here as we can't easily do that during nameres.
                 //
@@ -2324,7 +2528,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
             Res::Def(DefKind::AssocTy, def_id) => {
                 debug_assert!(path.segments.len() >= 2);
-                self.prohibit_generics(&path.segments[..path.segments.len() - 2]);
+                self.prohibit_generics(path.segments[..path.segments.len() - 2].iter(), |_| {});
                 self.qpath_to_ty(
                     span,
                     opt_self_ty,
@@ -2335,7 +2539,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
             Res::PrimTy(prim_ty) => {
                 assert_eq!(opt_self_ty, None);
-                self.prohibit_generics(path.segments);
+                self.prohibit_generics(path.segments.iter(), |err| {
+                    let name = prim_ty.name_str();
+                    for segment in path.segments {
+                        if let Some(args) = segment.args {
+                            err.span_suggestion_verbose(
+                                segment.ident.span.shrink_to_hi().to(args.span_ext),
+                                &format!("primitive type `{name}` doesn't have generic parameters"),
+                                String::new(),
+                                Applicability::MaybeIncorrect,
+                            );
+                        }
+                    }
+                });
                 match prim_ty {
                     hir::PrimTy::Bool => tcx.types.bool,
                     hir::PrimTy::Char => tcx.types.char,
@@ -2426,13 +2642,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
                 debug!(?qself, ?segment);
                 let ty = self.ast_ty_to_ty_inner(qself, false, true);
-
-                let res = if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = qself.kind {
-                    path.res
-                } else {
-                    Res::Err
-                };
-                self.associated_path_to_ty(ast_ty.hir_id, ast_ty.span, ty, res, segment, false)
+                self.associated_path_to_ty(ast_ty.hir_id, ast_ty.span, ty, qself, segment, false)
                     .map(|(ty, _, _)| ty)
                     .unwrap_or_else(|_| tcx.ty_error())
             }
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
index ac2dc6522ad..c28c041e78d 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
@@ -1228,6 +1228,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     None
                 }
             }),
+            |_| {},
         );
 
         if let Res::Local(hid) = res {
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
index 34cc02f180b..83afbfa54b1 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -1564,13 +1564,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             QPath::TypeRelative(ref qself, ref segment) => {
                 let ty = self.to_ty(qself);
 
-                let res = if let hir::TyKind::Path(QPath::Resolved(_, ref path)) = qself.kind {
-                    path.res
-                } else {
-                    Res::Err
-                };
                 let result = <dyn AstConv<'_>>::associated_path_to_ty(
-                    self, hir_id, path_span, ty, res, segment, true,
+                    self, hir_id, path_span, ty, qself, segment, true,
                 );
                 let ty = result.map(|(ty, _, _)| ty).unwrap_or_else(|_| self.tcx().ty_error());
                 let result = result.map(|(_, kind, def_id)| (kind, def_id));
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 4322440d685..34d107349e7 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -1364,7 +1364,6 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
 
     fn has_late_bound_regions<'tcx>(
         tcx: TyCtxt<'tcx>,
-        def_id: LocalDefId,
         generics: &'tcx hir::Generics<'tcx>,
         decl: &'tcx hir::FnDecl<'tcx>,
     ) -> Option<Span> {
@@ -1373,14 +1372,9 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
             outer_index: ty::INNERMOST,
             has_late_bound_regions: None,
         };
-        let late_bound_map = tcx.is_late_bound_map(def_id);
-        let is_late_bound = |id| {
-            let id = tcx.hir().local_def_id(id);
-            late_bound_map.map_or(false, |(_, set)| set.contains(&id))
-        };
         for param in generics.params {
             if let GenericParamKind::Lifetime { .. } = param.kind {
-                if is_late_bound(param.hir_id) {
+                if tcx.is_late_bound(param.hir_id) {
                     return Some(param.span);
                 }
             }
@@ -1392,25 +1386,25 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
     match node {
         Node::TraitItem(item) => match item.kind {
             hir::TraitItemKind::Fn(ref sig, _) => {
-                has_late_bound_regions(tcx, item.def_id, &item.generics, sig.decl)
+                has_late_bound_regions(tcx, &item.generics, sig.decl)
             }
             _ => None,
         },
         Node::ImplItem(item) => match item.kind {
             hir::ImplItemKind::Fn(ref sig, _) => {
-                has_late_bound_regions(tcx, item.def_id, &item.generics, sig.decl)
+                has_late_bound_regions(tcx, &item.generics, sig.decl)
             }
             _ => None,
         },
         Node::ForeignItem(item) => match item.kind {
             hir::ForeignItemKind::Fn(fn_decl, _, ref generics) => {
-                has_late_bound_regions(tcx, item.def_id, generics, fn_decl)
+                has_late_bound_regions(tcx, generics, fn_decl)
             }
             _ => None,
         },
         Node::Item(item) => match item.kind {
             hir::ItemKind::Fn(ref sig, .., ref generics, _) => {
-                has_late_bound_regions(tcx, item.def_id, generics, sig.decl)
+                has_late_bound_regions(tcx, generics, sig.decl)
             }
             _ => None,
         },
@@ -1671,7 +1665,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
         params.push(opt_self);
     }
 
-    let early_lifetimes = early_bound_lifetimes_from_generics(tcx, hir_id.owner, ast_generics);
+    let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics);
     params.extend(early_lifetimes.enumerate().map(|(i, param)| ty::GenericParamDef {
         name: param.name.ident().name,
         index: own_start + i as u32,
@@ -2054,23 +2048,10 @@ fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity {
 /// `resolve_lifetime::early_bound_lifetimes`.
 fn early_bound_lifetimes_from_generics<'a, 'tcx: 'a>(
     tcx: TyCtxt<'tcx>,
-    def_id: LocalDefId,
     generics: &'a hir::Generics<'a>,
 ) -> impl Iterator<Item = &'a hir::GenericParam<'a>> + Captures<'tcx> {
-    let late_bound_map = if generics.params.is_empty() {
-        // This function may be called on `def_id == CRATE_DEF_ID`,
-        // which makes `is_late_bound_map` ICE.  Don't even try if there
-        // is no generic parameter.
-        None
-    } else {
-        tcx.is_late_bound_map(def_id)
-    };
-    let is_late_bound = move |hir_id| {
-        let id = tcx.hir().local_def_id(hir_id);
-        late_bound_map.map_or(false, |(_, set)| set.contains(&id))
-    };
     generics.params.iter().filter(move |param| match param.kind {
-        GenericParamKind::Lifetime { .. } => !is_late_bound(param.hir_id),
+        GenericParamKind::Lifetime { .. } => !tcx.is_late_bound(param.hir_id),
         _ => false,
     })
 }
@@ -2255,7 +2236,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
     // have to be careful to only iterate over early-bound regions.
     let mut index = parent_count
         + has_own_self as u32
-        + early_bound_lifetimes_from_generics(tcx, hir_id.owner, ast_generics).count() as u32;
+        + early_bound_lifetimes_from_generics(tcx, ast_generics).count() as u32;
 
     // Collect the predicates that were written inline by the user on each
     // type parameter (e.g., `<T: Foo>`).
diff --git a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
index f1dc3cbbac4..bc3a3db9fda 100644
--- a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
@@ -514,7 +514,9 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
                             param_names
                                 .iter()
                                 .take(num_params_to_take)
-                                .map(|p| p.as_str())
+                                .map(|def_id| {
+                                    self.tcx.item_name(def_id.to_def_id()).to_ident_string()
+                                })
                                 .collect::<Vec<_>>()
                                 .join(", ")
                         } else {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index c725cf93be2..f3070fb35f1 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -475,24 +475,14 @@ fn clean_generic_param<'tcx>(
     generics: Option<&hir::Generics<'tcx>>,
     param: &hir::GenericParam<'tcx>,
 ) -> GenericParamDef {
+    let did = cx.tcx.hir().local_def_id(param.hir_id);
     let (name, kind) = match param.kind {
         hir::GenericParamKind::Lifetime { .. } => {
             let outlives = if let Some(generics) = generics {
                 generics
-                    .predicates
-                    .iter()
-                    .flat_map(|pred| {
-                        match pred {
-                            hir::WherePredicate::RegionPredicate(rp)
-                                if rp.lifetime.name == hir::LifetimeName::Param(param.name)
-                                    && !rp.in_where_clause =>
-                            {
-                                rp.bounds
-                            }
-                            _ => &[],
-                        }
-                        .iter()
-                    })
+                    .outlives_for_param(did)
+                    .filter(|bp| !bp.in_where_clause)
+                    .flat_map(|bp| bp.bounds)
                     .map(|bound| match bound {
                         hir::GenericBound::Outlives(lt) => lt.clean(cx),
                         _ => panic!(),
@@ -504,7 +494,6 @@ fn clean_generic_param<'tcx>(
             (param.name.ident().name, GenericParamDefKind::Lifetime { outlives })
         }
         hir::GenericParamKind::Type { ref default, synthetic } => {
-            let did = cx.tcx.hir().local_def_id(param.hir_id);
             let bounds = if let Some(generics) = generics {
                 generics
                     .bounds_for_param(did)
@@ -528,7 +517,7 @@ fn clean_generic_param<'tcx>(
         hir::GenericParamKind::Const { ty, default } => (
             param.name.ident().name,
             GenericParamDefKind::Const {
-                did: cx.tcx.hir().local_def_id(param.hir_id).to_def_id(),
+                did: did.to_def_id(),
                 ty: Box::new(ty.clean(cx)),
                 default: default.map(|ct| {
                     let def_id = cx.tcx.hir().local_def_id(ct.hir_id);
@@ -1459,7 +1448,7 @@ impl<'tcx> Clean<'tcx, Type> for hir::Ty<'tcx> {
                 // Turning `fn f(&'_ self)` into `fn f(&self)` isn't the worst thing in the world, though;
                 // there's no case where it could cause the function to fail to compile.
                 let elided =
-                    l.is_elided() || matches!(l.name, LifetimeName::Param(ParamName::Fresh(_)));
+                    l.is_elided() || matches!(l.name, LifetimeName::Param(_, ParamName::Fresh));
                 let lifetime = if elided { None } else { Some(l.clean(cx)) };
                 BorrowedRef { lifetime, mutability: m.mutbl, type_: box m.ty.clean(cx) }
             }
diff --git a/src/librustdoc/html/static/.eslintrc.js b/src/librustdoc/html/static/.eslintrc.js
index f66ecbf78af..bd83b254caa 100644
--- a/src/librustdoc/html/static/.eslintrc.js
+++ b/src/librustdoc/html/static/.eslintrc.js
@@ -70,5 +70,13 @@ module.exports = {
         "no-dupe-keys": "error",
         "no-duplicate-case": "error",
         "no-ex-assign": "error",
+        "no-fallthrough": "error",
+        "no-invalid-regexp": "error",
+        "no-import-assign": "error",
+        "no-self-compare": "error",
+        "no-template-curly-in-string": "error",
+        "block-scoped-var": "error",
+        "guard-for-in": "error",
+        "no-alert": "error",
     }
 };
diff --git a/src/test/ui/derives/issue-97343.rs b/src/test/ui/derives/issue-97343.rs
index adec6c7a5c5..6f0e4d55aeb 100644
--- a/src/test/ui/derives/issue-97343.rs
+++ b/src/test/ui/derives/issue-97343.rs
@@ -1,7 +1,7 @@
 use std::fmt::Debug;
 
 #[derive(Debug)]
-pub struct Irrelevant<Irrelevant> { //~ ERROR type arguments are not allowed for this type
+pub struct Irrelevant<Irrelevant> { //~ ERROR type arguments are not allowed on type parameter
     irrelevant: Irrelevant,
 }
 
diff --git a/src/test/ui/derives/issue-97343.stderr b/src/test/ui/derives/issue-97343.stderr
index eedd54f1e9f..ac797a8f501 100644
--- a/src/test/ui/derives/issue-97343.stderr
+++ b/src/test/ui/derives/issue-97343.stderr
@@ -1,11 +1,19 @@
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on type parameter `Irrelevant`
   --> $DIR/issue-97343.rs:4:23
    |
 LL | #[derive(Debug)]
-   |          ----- in this derive macro expansion
+   |          -----
+   |          |
+   |          not allowed on this
+   |          in this derive macro expansion
 LL | pub struct Irrelevant<Irrelevant> {
    |                       ^^^^^^^^^^ type argument not allowed
    |
+note: type parameter `Irrelevant` defined here
+  --> $DIR/issue-97343.rs:4:23
+   |
+LL | pub struct Irrelevant<Irrelevant> {
+   |                       ^^^^^^^^^^
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
diff --git a/src/test/ui/error-codes/E0109.stderr b/src/test/ui/error-codes/E0109.stderr
index 577e286fcc6..e0e437e18ae 100644
--- a/src/test/ui/error-codes/E0109.stderr
+++ b/src/test/ui/error-codes/E0109.stderr
@@ -1,8 +1,16 @@
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/E0109.rs:1:14
    |
 LL | type X = u32<i32>;
-   |              ^^^ type argument not allowed
+   |          --- ^^^ type argument not allowed
+   |          |
+   |          not allowed on this
+   |
+help: primitive type `u32` doesn't have generic parameters
+   |
+LL - type X = u32<i32>;
+LL + type X = u32;
+   | 
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0110.stderr b/src/test/ui/error-codes/E0110.stderr
index b0221318087..15e1b959193 100644
--- a/src/test/ui/error-codes/E0110.stderr
+++ b/src/test/ui/error-codes/E0110.stderr
@@ -1,8 +1,16 @@
-error[E0109]: lifetime arguments are not allowed for this type
+error[E0109]: lifetime arguments are not allowed on this type
   --> $DIR/E0110.rs:1:14
    |
 LL | type X = u32<'static>;
-   |              ^^^^^^^ lifetime argument not allowed
+   |          --- ^^^^^^^ lifetime argument not allowed
+   |          |
+   |          not allowed on this
+   |
+help: primitive type `u32` doesn't have generic parameters
+   |
+LL - type X = u32<'static>;
+LL + type X = u32;
+   | 
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-22706.rs b/src/test/ui/issues/issue-22706.rs
index 28e8a722804..bb8a58d3d2e 100644
--- a/src/test/ui/issues/issue-22706.rs
+++ b/src/test/ui/issues/issue-22706.rs
@@ -1,3 +1,3 @@
 fn is_copy<T: ::std::marker<i32>::Copy>() {}
-//~^ ERROR type arguments are not allowed for this type [E0109]
+//~^ ERROR type arguments are not allowed on module `marker` [E0109]
 fn main() {}
diff --git a/src/test/ui/issues/issue-22706.stderr b/src/test/ui/issues/issue-22706.stderr
index c5929397f65..66911f081d7 100644
--- a/src/test/ui/issues/issue-22706.stderr
+++ b/src/test/ui/issues/issue-22706.stderr
@@ -1,8 +1,10 @@
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on module `marker`
   --> $DIR/issue-22706.rs:1:29
    |
 LL | fn is_copy<T: ::std::marker<i32>::Copy>() {}
-   |                             ^^^ type argument not allowed
+   |                      ------ ^^^ type argument not allowed
+   |                      |
+   |                      not allowed on this
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-57924.rs b/src/test/ui/issues/issue-57924.rs
index dc2942225e3..8846912a8ff 100644
--- a/src/test/ui/issues/issue-57924.rs
+++ b/src/test/ui/issues/issue-57924.rs
@@ -3,7 +3,7 @@ pub struct Gcm<E>(E);
 impl<E> Gcm<E> {
     pub fn crash(e: E) -> Self {
         Self::<E>(e)
-        //~^ ERROR type arguments are not allowed for this type
+        //~^ ERROR type arguments are not allowed on self constructor
     }
 }
 
diff --git a/src/test/ui/issues/issue-57924.stderr b/src/test/ui/issues/issue-57924.stderr
index 2f184b1aae1..211b0dde48c 100644
--- a/src/test/ui/issues/issue-57924.stderr
+++ b/src/test/ui/issues/issue-57924.stderr
@@ -1,8 +1,10 @@
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on self constructor
   --> $DIR/issue-57924.rs:5:16
    |
 LL |         Self::<E>(e)
-   |                ^ type argument not allowed
+   |         ----   ^ type argument not allowed
+   |         |
+   |         not allowed on this
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-60989.rs b/src/test/ui/issues/issue-60989.rs
index 6dae1e1347b..29db3fdb471 100644
--- a/src/test/ui/issues/issue-60989.rs
+++ b/src/test/ui/issues/issue-60989.rs
@@ -10,9 +10,9 @@ impl From<A> for B {
 fn main() {
     let c1 = ();
     c1::<()>;
-    //~^ ERROR type arguments are not allowed for this type
+    //~^ ERROR type arguments are not allowed on local variable
 
     let c1 = A {};
     c1::<dyn Into<B>>;
-    //~^ ERROR type arguments are not allowed for this type
+    //~^ ERROR type arguments are not allowed on local variable
 }
diff --git a/src/test/ui/issues/issue-60989.stderr b/src/test/ui/issues/issue-60989.stderr
index 5d2d9e83c9b..9076f4f9385 100644
--- a/src/test/ui/issues/issue-60989.stderr
+++ b/src/test/ui/issues/issue-60989.stderr
@@ -1,14 +1,18 @@
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on local variable
   --> $DIR/issue-60989.rs:12:10
    |
 LL |     c1::<()>;
-   |          ^^ type argument not allowed
+   |     --   ^^ type argument not allowed
+   |     |
+   |     not allowed on this
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on local variable
   --> $DIR/issue-60989.rs:16:10
    |
 LL |     c1::<dyn Into<B>>;
-   |          ^^^^^^^^^^^ type argument not allowed
+   |     --   ^^^^^^^^^^^ type argument not allowed
+   |     |
+   |     not allowed on this
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/mod-subitem-as-enum-variant.rs b/src/test/ui/mod-subitem-as-enum-variant.rs
index 9328d1a9045..959024c46f4 100644
--- a/src/test/ui/mod-subitem-as-enum-variant.rs
+++ b/src/test/ui/mod-subitem-as-enum-variant.rs
@@ -5,5 +5,5 @@ mod Mod {
 fn main() {
     Mod::FakeVariant::<i32>(0);
     Mod::<i32>::FakeVariant(0);
-    //~^ ERROR type arguments are not allowed for this type [E0109]
+    //~^ ERROR type arguments are not allowed on module `Mod` [E0109]
 }
diff --git a/src/test/ui/mod-subitem-as-enum-variant.stderr b/src/test/ui/mod-subitem-as-enum-variant.stderr
index d6815c91e5e..15da1d155a3 100644
--- a/src/test/ui/mod-subitem-as-enum-variant.stderr
+++ b/src/test/ui/mod-subitem-as-enum-variant.stderr
@@ -1,8 +1,10 @@
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on module `Mod`
   --> $DIR/mod-subitem-as-enum-variant.rs:7:11
    |
 LL |     Mod::<i32>::FakeVariant(0);
-   |           ^^^ type argument not allowed
+   |     ---   ^^^ type argument not allowed
+   |     |
+   |     not allowed on this
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/structs/struct-path-associated-type.rs b/src/test/ui/structs/struct-path-associated-type.rs
index e44a203b783..f88572f8419 100644
--- a/src/test/ui/structs/struct-path-associated-type.rs
+++ b/src/test/ui/structs/struct-path-associated-type.rs
@@ -13,7 +13,7 @@ fn f<T: Tr>() {
     //~^ ERROR expected struct, variant or union type, found associated type
     let z = T::A::<u8> {};
     //~^ ERROR expected struct, variant or union type, found associated type
-    //~| ERROR type arguments are not allowed for this type
+    //~| ERROR type arguments are not allowed on this type
     match S {
         T::A {} => {}
         //~^ ERROR expected struct, variant or union type, found associated type
@@ -22,7 +22,7 @@ fn f<T: Tr>() {
 
 fn g<T: Tr<A = S>>() {
     let s = T::A {}; // OK
-    let z = T::A::<u8> {}; //~ ERROR type arguments are not allowed for this type
+    let z = T::A::<u8> {}; //~ ERROR type arguments are not allowed on this type
     match S {
         T::A {} => {} // OK
     }
diff --git a/src/test/ui/structs/struct-path-associated-type.stderr b/src/test/ui/structs/struct-path-associated-type.stderr
index 0b1b6a5e3af..7424ceecbe3 100644
--- a/src/test/ui/structs/struct-path-associated-type.stderr
+++ b/src/test/ui/structs/struct-path-associated-type.stderr
@@ -4,11 +4,13 @@ error[E0071]: expected struct, variant or union type, found associated type
 LL |     let s = T::A {};
    |             ^^^^ not a struct
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/struct-path-associated-type.rs:14:20
    |
 LL |     let z = T::A::<u8> {};
-   |                    ^^ type argument not allowed
+   |                -   ^^ type argument not allowed
+   |                |
+   |                not allowed on this
 
 error[E0071]: expected struct, variant or union type, found associated type
   --> $DIR/struct-path-associated-type.rs:14:13
@@ -22,11 +24,13 @@ error[E0071]: expected struct, variant or union type, found associated type
 LL |         T::A {} => {}
    |         ^^^^ not a struct
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/struct-path-associated-type.rs:25:20
    |
 LL |     let z = T::A::<u8> {};
-   |                    ^^ type argument not allowed
+   |                -   ^^ type argument not allowed
+   |                |
+   |                not allowed on this
 
 error[E0223]: ambiguous associated type
   --> $DIR/struct-path-associated-type.rs:32:13
diff --git a/src/test/ui/structs/struct-path-self.rs b/src/test/ui/structs/struct-path-self.rs
index c938ce8dad9..6e529c7ed2b 100644
--- a/src/test/ui/structs/struct-path-self.rs
+++ b/src/test/ui/structs/struct-path-self.rs
@@ -6,7 +6,7 @@ trait Tr {
         //~^ ERROR expected struct, variant or union type, found type parameter
         let z = Self::<u8> {};
         //~^ ERROR expected struct, variant or union type, found type parameter
-        //~| ERROR type arguments are not allowed for this type
+        //~| ERROR type arguments are not allowed on self type
         match s {
             Self { .. } => {}
             //~^ ERROR expected struct, variant or union type, found type parameter
@@ -17,7 +17,7 @@ trait Tr {
 impl Tr for S {
     fn f() {
         let s = Self {}; // OK
-        let z = Self::<u8> {}; //~ ERROR type arguments are not allowed for this type
+        let z = Self::<u8> {}; //~ ERROR type arguments are not allowed on self type
         match s {
             Self { .. } => {} // OK
         }
@@ -27,7 +27,7 @@ impl Tr for S {
 impl S {
     fn g() {
         let s = Self {}; // OK
-        let z = Self::<u8> {}; //~ ERROR type arguments are not allowed for this type
+        let z = Self::<u8> {}; //~ ERROR type arguments are not allowed on self type
         match s {
             Self { .. } => {} // OK
         }
diff --git a/src/test/ui/structs/struct-path-self.stderr b/src/test/ui/structs/struct-path-self.stderr
index 693ed35cbc9..cccdd7b0f02 100644
--- a/src/test/ui/structs/struct-path-self.stderr
+++ b/src/test/ui/structs/struct-path-self.stderr
@@ -4,11 +4,19 @@ error[E0071]: expected struct, variant or union type, found type parameter `Self
 LL |         let s = Self {};
    |                 ^^^^ not a struct
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on self type
   --> $DIR/struct-path-self.rs:7:24
    |
 LL |         let z = Self::<u8> {};
-   |                        ^^ type argument not allowed
+   |                 ----   ^^ type argument not allowed
+   |                 |
+   |                 not allowed on this
+   |
+help: the `Self` type doesn't accept type parameters
+   |
+LL -         let z = Self::<u8> {};
+LL +         let z = Self {};
+   | 
 
 error[E0071]: expected struct, variant or union type, found type parameter `Self`
   --> $DIR/struct-path-self.rs:7:17
@@ -22,17 +30,49 @@ error[E0071]: expected struct, variant or union type, found type parameter `Self
 LL |             Self { .. } => {}
    |             ^^^^ not a struct
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on self type
   --> $DIR/struct-path-self.rs:20:24
    |
 LL |         let z = Self::<u8> {};
-   |                        ^^ type argument not allowed
+   |                 ----   ^^ type argument not allowed
+   |                 |
+   |                 not allowed on this
+   |
+note: `Self` is of type `S`
+  --> $DIR/struct-path-self.rs:1:8
+   |
+LL | struct S;
+   |        ^ `Self` corresponds to this type, which doesn't have generic parameters
+...
+LL | impl Tr for S {
+   | ------------- `Self` is on type `S` in this `impl`
+help: the `Self` type doesn't accept type parameters
+   |
+LL -         let z = Self::<u8> {};
+LL +         let z = Self {};
+   | 
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on self type
   --> $DIR/struct-path-self.rs:30:24
    |
 LL |         let z = Self::<u8> {};
-   |                        ^^ type argument not allowed
+   |                 ----   ^^ type argument not allowed
+   |                 |
+   |                 not allowed on this
+   |
+note: `Self` is of type `S`
+  --> $DIR/struct-path-self.rs:1:8
+   |
+LL | struct S;
+   |        ^ `Self` corresponds to this type, which doesn't have generic parameters
+...
+LL | impl S {
+   | ------ `Self` is on type `S` in this `impl`
+help: the `Self` type doesn't accept type parameters
+   |
+LL -         let z = Self::<u8> {};
+LL +         let z = Self {};
+   | 
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.rs b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.rs
index 6bc4f528faa..e6f45036f85 100644
--- a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.rs
+++ b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.rs
@@ -13,38 +13,38 @@ impl<T> Enum<T> {
         Self::TSVariant(());
         //~^ ERROR mismatched types [E0308]
         Self::TSVariant::<()>(());
-        //~^ ERROR type arguments are not allowed for this type [E0109]
+        //~^ ERROR type arguments are not allowed on this type [E0109]
         Self::<()>::TSVariant(());
-        //~^ ERROR type arguments are not allowed for this type [E0109]
+        //~^ ERROR type arguments are not allowed on self type [E0109]
         //~| ERROR mismatched types [E0308]
         Self::<()>::TSVariant::<()>(());
-        //~^ ERROR type arguments are not allowed for this type [E0109]
-        //~| ERROR type arguments are not allowed for this type [E0109]
+        //~^ ERROR type arguments are not allowed on self type [E0109]
+        //~| ERROR type arguments are not allowed on this type [E0109]
     }
 
     fn s_variant() {
         Self::SVariant { v: () };
         //~^ ERROR mismatched types [E0308]
         Self::SVariant::<()> { v: () };
-        //~^ ERROR type arguments are not allowed for this type [E0109]
+        //~^ ERROR type arguments are not allowed on this type [E0109]
         //~| ERROR mismatched types [E0308]
         Self::<()>::SVariant { v: () };
-        //~^ ERROR type arguments are not allowed for this type [E0109]
+        //~^ ERROR type arguments are not allowed on self type [E0109]
         //~| ERROR mismatched types [E0308]
         Self::<()>::SVariant::<()> { v: () };
-        //~^ ERROR type arguments are not allowed for this type [E0109]
-        //~| ERROR type arguments are not allowed for this type [E0109]
+        //~^ ERROR type arguments are not allowed on self type [E0109]
+        //~| ERROR type arguments are not allowed on this type [E0109]
         //~| ERROR mismatched types [E0308]
     }
 
     fn u_variant() {
         Self::UVariant::<()>;
-        //~^ ERROR type arguments are not allowed for this type [E0109]
+        //~^ ERROR type arguments are not allowed on this type [E0109]
         Self::<()>::UVariant;
-        //~^ ERROR type arguments are not allowed for this type [E0109]
+        //~^ ERROR type arguments are not allowed on self type [E0109]
         Self::<()>::UVariant::<()>;
-        //~^ ERROR type arguments are not allowed for this type [E0109]
-        //~| ERROR type arguments are not allowed for this type [E0109]
+        //~^ ERROR type arguments are not allowed on self type [E0109]
+        //~| ERROR type arguments are not allowed on this type [E0109]
     }
 }
 
@@ -52,54 +52,54 @@ fn main() {
     // Tuple struct variant
 
     Enum::<()>::TSVariant::<()>(());
-    //~^ ERROR type arguments are not allowed for this type [E0109]
+    //~^ ERROR type arguments are not allowed on this type [E0109]
 
     Alias::TSVariant::<()>(());
-    //~^ ERROR type arguments are not allowed for this type [E0109]
+    //~^ ERROR type arguments are not allowed on this type [E0109]
     Alias::<()>::TSVariant::<()>(());
-    //~^ ERROR type arguments are not allowed for this type [E0109]
+    //~^ ERROR type arguments are not allowed on this type [E0109]
 
     AliasFixed::TSVariant::<()>(());
-    //~^ ERROR type arguments are not allowed for this type [E0109]
+    //~^ ERROR type arguments are not allowed on this type [E0109]
     AliasFixed::<()>::TSVariant(());
     //~^ ERROR this type alias takes 0 generic arguments but 1 generic argument was supplied [E0107]
     AliasFixed::<()>::TSVariant::<()>(());
-    //~^ ERROR type arguments are not allowed for this type [E0109]
+    //~^ ERROR type arguments are not allowed on this type [E0109]
     //~| ERROR this type alias takes 0 generic arguments but 1 generic argument was supplied [E0107]
 
     // Struct variant
 
     Enum::<()>::SVariant::<()> { v: () };
-    //~^ ERROR type arguments are not allowed for this type [E0109]
+    //~^ ERROR type arguments are not allowed on this type [E0109]
 
     Alias::SVariant::<()> { v: () };
-    //~^ ERROR type arguments are not allowed for this type [E0109]
+    //~^ ERROR type arguments are not allowed on this type [E0109]
     Alias::<()>::SVariant::<()> { v: () };
-    //~^ ERROR type arguments are not allowed for this type [E0109]
+    //~^ ERROR type arguments are not allowed on this type [E0109]
 
     AliasFixed::SVariant::<()> { v: () };
-    //~^ ERROR type arguments are not allowed for this type [E0109]
+    //~^ ERROR type arguments are not allowed on this type [E0109]
     AliasFixed::<()>::SVariant { v: () };
     //~^ ERROR this type alias takes 0 generic arguments but 1 generic argument was supplied [E0107]
     AliasFixed::<()>::SVariant::<()> { v: () };
-    //~^ ERROR type arguments are not allowed for this type [E0109]
+    //~^ ERROR type arguments are not allowed on this type [E0109]
     //~| ERROR this type alias takes 0 generic arguments but 1 generic argument was supplied [E0107]
 
     // Unit variant
 
     Enum::<()>::UVariant::<()>;
-    //~^ ERROR type arguments are not allowed for this type [E0109]
+    //~^ ERROR type arguments are not allowed on this type [E0109]
 
     Alias::UVariant::<()>;
-    //~^ ERROR type arguments are not allowed for this type [E0109]
+    //~^ ERROR type arguments are not allowed on this type [E0109]
     Alias::<()>::UVariant::<()>;
-    //~^ ERROR type arguments are not allowed for this type [E0109]
+    //~^ ERROR type arguments are not allowed on this type [E0109]
 
     AliasFixed::UVariant::<()>;
-    //~^ ERROR type arguments are not allowed for this type [E0109]
+    //~^ ERROR type arguments are not allowed on this type [E0109]
     AliasFixed::<()>::UVariant;
     //~^ ERROR this type alias takes 0 generic arguments but 1 generic argument was supplied [E0107]
     AliasFixed::<()>::UVariant::<()>;
-    //~^ ERROR type arguments are not allowed for this type [E0109]
+    //~^ ERROR type arguments are not allowed on this type [E0109]
     //~| ERROR this type alias takes 0 generic arguments but 1 generic argument was supplied [E0107]
 }
diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr
index 115ecb01376..3e60ab108a8 100644
--- a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr
+++ b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr
@@ -17,17 +17,34 @@ note: tuple variant defined here
 LL | enum Enum<T> { TSVariant(T), SVariant { v: T }, UVariant }
    |                ^^^^^^^^^
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:15:27
    |
 LL |         Self::TSVariant::<()>(());
-   |                           ^^ type argument not allowed
+   |               ---------   ^^ type argument not allowed
+   |               |
+   |               not allowed on this
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on self type
   --> $DIR/enum-variant-generic-args.rs:17:16
    |
 LL |         Self::<()>::TSVariant(());
-   |                ^^ type argument not allowed
+   |         ----   ^^ type argument not allowed
+   |         |
+   |         not allowed on this
+   |
+note: `Self` is of type `Enum<T>`
+  --> $DIR/enum-variant-generic-args.rs:7:6
+   |
+LL | enum Enum<T> { TSVariant(T), SVariant { v: T }, UVariant }
+   |      ^^^^ `Self` corresponds to this type
+...
+LL | impl<T> Enum<T> {
+   | --------------- `Self` is on type `Enum` in this `impl`
+help: the `Self` type doesn't accept type parameters, use the concrete type's name `Enum` instead if you want to specify its type parameters
+   |
+LL |         Enum::<()>::TSVariant(());
+   |         ~~~~
 
 error[E0308]: mismatched types
   --> $DIR/enum-variant-generic-args.rs:17:31
@@ -48,17 +65,34 @@ note: tuple variant defined here
 LL | enum Enum<T> { TSVariant(T), SVariant { v: T }, UVariant }
    |                ^^^^^^^^^
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on self type
   --> $DIR/enum-variant-generic-args.rs:20:16
    |
 LL |         Self::<()>::TSVariant::<()>(());
-   |                ^^ type argument not allowed
+   |         ----   ^^ type argument not allowed
+   |         |
+   |         not allowed on this
+   |
+note: `Self` is of type `Enum<T>`
+  --> $DIR/enum-variant-generic-args.rs:7:6
+   |
+LL | enum Enum<T> { TSVariant(T), SVariant { v: T }, UVariant }
+   |      ^^^^ `Self` corresponds to this type
+...
+LL | impl<T> Enum<T> {
+   | --------------- `Self` is on type `Enum` in this `impl`
+help: the `Self` type doesn't accept type parameters, use the concrete type's name `Enum` instead if you want to specify its type parameters
+   |
+LL |         Enum::<()>::TSVariant::<()>(());
+   |         ~~~~
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:20:33
    |
 LL |         Self::<()>::TSVariant::<()>(());
-   |                                 ^^ type argument not allowed
+   |                     ---------   ^^ type argument not allowed
+   |                     |
+   |                     not allowed on this
 
 error[E0308]: mismatched types
   --> $DIR/enum-variant-generic-args.rs:26:29
@@ -72,11 +106,20 @@ LL |         Self::SVariant { v: () };
    = note: expected type parameter `T`
                    found unit type `()`
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:28:26
    |
 LL |         Self::SVariant::<()> { v: () };
-   |                          ^^ type argument not allowed
+   |               --------   ^^ type argument not allowed
+   |               |
+   |               not allowed on this
+   |
+   = note: enum variants can't have type parameters
+help: you might have meant to specity type parameters on enum `Enum`
+   |
+LL -         Self::SVariant::<()> { v: () };
+LL +         Enum::<()>::SVariant { v: () };
+   | 
 
 error[E0308]: mismatched types
   --> $DIR/enum-variant-generic-args.rs:28:35
@@ -90,11 +133,26 @@ LL |         Self::SVariant::<()> { v: () };
    = note: expected type parameter `T`
                    found unit type `()`
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on self type
   --> $DIR/enum-variant-generic-args.rs:31:16
    |
 LL |         Self::<()>::SVariant { v: () };
-   |                ^^ type argument not allowed
+   |         ----   ^^ type argument not allowed
+   |         |
+   |         not allowed on this
+   |
+note: `Self` is of type `Enum<T>`
+  --> $DIR/enum-variant-generic-args.rs:7:6
+   |
+LL | enum Enum<T> { TSVariant(T), SVariant { v: T }, UVariant }
+   |      ^^^^ `Self` corresponds to this type
+...
+LL | impl<T> Enum<T> {
+   | --------------- `Self` is on type `Enum` in this `impl`
+help: the `Self` type doesn't accept type parameters, use the concrete type's name `Enum` instead if you want to specify its type parameters
+   |
+LL |         Enum::<()>::SVariant { v: () };
+   |         ~~~~
 
 error[E0308]: mismatched types
   --> $DIR/enum-variant-generic-args.rs:31:35
@@ -108,17 +166,41 @@ LL |         Self::<()>::SVariant { v: () };
    = note: expected type parameter `T`
                    found unit type `()`
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on self type
   --> $DIR/enum-variant-generic-args.rs:34:16
    |
 LL |         Self::<()>::SVariant::<()> { v: () };
-   |                ^^ type argument not allowed
+   |         ----   ^^ type argument not allowed
+   |         |
+   |         not allowed on this
+   |
+note: `Self` is of type `Enum<T>`
+  --> $DIR/enum-variant-generic-args.rs:7:6
+   |
+LL | enum Enum<T> { TSVariant(T), SVariant { v: T }, UVariant }
+   |      ^^^^ `Self` corresponds to this type
+...
+LL | impl<T> Enum<T> {
+   | --------------- `Self` is on type `Enum` in this `impl`
+help: the `Self` type doesn't accept type parameters, use the concrete type's name `Enum` instead if you want to specify its type parameters
+   |
+LL |         Enum::<()>::SVariant::<()> { v: () };
+   |         ~~~~
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:34:32
    |
 LL |         Self::<()>::SVariant::<()> { v: () };
-   |                                ^^ type argument not allowed
+   |                     --------   ^^ type argument not allowed
+   |                     |
+   |                     not allowed on this
+   |
+   = note: enum variants can't have type parameters
+help: you might have meant to specity type parameters on enum `Enum`
+   |
+LL -         Self::<()>::SVariant::<()> { v: () };
+LL +         Enum::<()>::SVariant { v: () };
+   | 
 
 error[E0308]: mismatched types
   --> $DIR/enum-variant-generic-args.rs:34:41
@@ -132,53 +214,95 @@ LL |         Self::<()>::SVariant::<()> { v: () };
    = note: expected type parameter `T`
                    found unit type `()`
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:41:26
    |
 LL |         Self::UVariant::<()>;
-   |                          ^^ type argument not allowed
+   |               --------   ^^ type argument not allowed
+   |               |
+   |               not allowed on this
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on self type
   --> $DIR/enum-variant-generic-args.rs:43:16
    |
 LL |         Self::<()>::UVariant;
-   |                ^^ type argument not allowed
+   |         ----   ^^ type argument not allowed
+   |         |
+   |         not allowed on this
+   |
+note: `Self` is of type `Enum<T>`
+  --> $DIR/enum-variant-generic-args.rs:7:6
+   |
+LL | enum Enum<T> { TSVariant(T), SVariant { v: T }, UVariant }
+   |      ^^^^ `Self` corresponds to this type
+...
+LL | impl<T> Enum<T> {
+   | --------------- `Self` is on type `Enum` in this `impl`
+help: the `Self` type doesn't accept type parameters, use the concrete type's name `Enum` instead if you want to specify its type parameters
+   |
+LL |         Enum::<()>::UVariant;
+   |         ~~~~
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on self type
   --> $DIR/enum-variant-generic-args.rs:45:16
    |
 LL |         Self::<()>::UVariant::<()>;
-   |                ^^ type argument not allowed
+   |         ----   ^^ type argument not allowed
+   |         |
+   |         not allowed on this
+   |
+note: `Self` is of type `Enum<T>`
+  --> $DIR/enum-variant-generic-args.rs:7:6
+   |
+LL | enum Enum<T> { TSVariant(T), SVariant { v: T }, UVariant }
+   |      ^^^^ `Self` corresponds to this type
+...
+LL | impl<T> Enum<T> {
+   | --------------- `Self` is on type `Enum` in this `impl`
+help: the `Self` type doesn't accept type parameters, use the concrete type's name `Enum` instead if you want to specify its type parameters
+   |
+LL |         Enum::<()>::UVariant::<()>;
+   |         ~~~~
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:45:32
    |
 LL |         Self::<()>::UVariant::<()>;
-   |                                ^^ type argument not allowed
+   |                     --------   ^^ type argument not allowed
+   |                     |
+   |                     not allowed on this
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:54:29
    |
 LL |     Enum::<()>::TSVariant::<()>(());
-   |                             ^^ type argument not allowed
+   |                 ---------   ^^ type argument not allowed
+   |                 |
+   |                 not allowed on this
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:57:24
    |
 LL |     Alias::TSVariant::<()>(());
-   |                        ^^ type argument not allowed
+   |            ---------   ^^ type argument not allowed
+   |            |
+   |            not allowed on this
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:59:30
    |
 LL |     Alias::<()>::TSVariant::<()>(());
-   |                              ^^ type argument not allowed
+   |                  ---------   ^^ type argument not allowed
+   |                  |
+   |                  not allowed on this
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:62:29
    |
 LL |     AliasFixed::TSVariant::<()>(());
-   |                             ^^ type argument not allowed
+   |                 ---------   ^^ type argument not allowed
+   |                 |
+   |                 not allowed on this
 
 error[E0107]: this type alias takes 0 generic arguments but 1 generic argument was supplied
   --> $DIR/enum-variant-generic-args.rs:64:5
@@ -208,35 +332,68 @@ note: type alias defined here, with 0 generic parameters
 LL | type AliasFixed = Enum<()>;
    |      ^^^^^^^^^^
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:66:35
    |
 LL |     AliasFixed::<()>::TSVariant::<()>(());
-   |                                   ^^ type argument not allowed
+   |                       ---------   ^^ type argument not allowed
+   |                       |
+   |                       not allowed on this
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:72:28
    |
 LL |     Enum::<()>::SVariant::<()> { v: () };
-   |                            ^^ type argument not allowed
+   |                 --------   ^^ type argument not allowed
+   |                 |
+   |                 not allowed on this
+   |
+   = note: enum variants can't have type parameters
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:75:23
    |
 LL |     Alias::SVariant::<()> { v: () };
-   |                       ^^ type argument not allowed
+   |            --------   ^^ type argument not allowed
+   |            |
+   |            not allowed on this
+   |
+   = note: enum variants can't have type parameters
+help: you might have meant to specity type parameters on enum `Enum`
+   |
+LL -     Alias::SVariant::<()> { v: () };
+LL +     Alias::<()>::SVariant { v: () };
+   | 
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:77:29
    |
 LL |     Alias::<()>::SVariant::<()> { v: () };
-   |                             ^^ type argument not allowed
+   |                  --------   ^^ type argument not allowed
+   |                  |
+   |                  not allowed on this
+   |
+   = note: enum variants can't have type parameters
+help: you might have meant to specity type parameters on enum `Enum`
+   |
+LL -     Alias::<()>::SVariant::<()> { v: () };
+LL +     Alias::<()>::SVariant { v: () };
+   | 
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:80:28
    |
 LL |     AliasFixed::SVariant::<()> { v: () };
-   |                            ^^ type argument not allowed
+   |                 --------   ^^ type argument not allowed
+   |                 |
+   |                 not allowed on this
+   |
+   = note: enum variants can't have type parameters
+help: you might have meant to specity type parameters on enum `Enum`
+   |
+LL -     AliasFixed::SVariant::<()> { v: () };
+LL +     AliasFixed::<()>::SVariant { v: () };
+   | 
 
 error[E0107]: this type alias takes 0 generic arguments but 1 generic argument was supplied
   --> $DIR/enum-variant-generic-args.rs:82:5
@@ -266,35 +423,52 @@ note: type alias defined here, with 0 generic parameters
 LL | type AliasFixed = Enum<()>;
    |      ^^^^^^^^^^
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:84:34
    |
 LL |     AliasFixed::<()>::SVariant::<()> { v: () };
-   |                                  ^^ type argument not allowed
+   |                       --------   ^^ type argument not allowed
+   |                       |
+   |                       not allowed on this
+   |
+   = note: enum variants can't have type parameters
+help: you might have meant to specity type parameters on enum `Enum`
+   |
+LL -     AliasFixed::<()>::SVariant::<()> { v: () };
+LL +     AliasFixed::<()>::SVariant { v: () };
+   | 
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:90:28
    |
 LL |     Enum::<()>::UVariant::<()>;
-   |                            ^^ type argument not allowed
+   |                 --------   ^^ type argument not allowed
+   |                 |
+   |                 not allowed on this
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:93:23
    |
 LL |     Alias::UVariant::<()>;
-   |                       ^^ type argument not allowed
+   |            --------   ^^ type argument not allowed
+   |            |
+   |            not allowed on this
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:95:29
    |
 LL |     Alias::<()>::UVariant::<()>;
-   |                             ^^ type argument not allowed
+   |                  --------   ^^ type argument not allowed
+   |                  |
+   |                  not allowed on this
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:98:28
    |
 LL |     AliasFixed::UVariant::<()>;
-   |                            ^^ type argument not allowed
+   |                 --------   ^^ type argument not allowed
+   |                 |
+   |                 not allowed on this
 
 error[E0107]: this type alias takes 0 generic arguments but 1 generic argument was supplied
   --> $DIR/enum-variant-generic-args.rs:100:5
@@ -324,11 +498,13 @@ note: type alias defined here, with 0 generic parameters
 LL | type AliasFixed = Enum<()>;
    |      ^^^^^^^^^^
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:102:34
    |
 LL |     AliasFixed::<()>::UVariant::<()>;
-   |                                  ^^ type argument not allowed
+   |                       --------   ^^ type argument not allowed
+   |                       |
+   |                       not allowed on this
 
 error: aborting due to 39 previous errors
 
diff --git a/src/test/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.rs b/src/test/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.rs
index c1153fa4dc7..872ece0c0f9 100644
--- a/src/test/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.rs
+++ b/src/test/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.rs
@@ -10,5 +10,5 @@ fn main() {
     let _ = Option::<u8>::None; // OK
     let _ = Option::None::<u8>; // OK (Lint in future!)
     let _ = Alias::<u8>::None; // OK
-    let _ = Alias::None::<u8>; //~ ERROR type arguments are not allowed for this type
+    let _ = Alias::None::<u8>; //~ ERROR type arguments are not allowed on this type
 }
diff --git a/src/test/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.stderr b/src/test/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.stderr
index a1064d69251..474548a14a9 100644
--- a/src/test/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.stderr
+++ b/src/test/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.stderr
@@ -1,8 +1,10 @@
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/no-type-application-on-aliased-enum-variant.rs:13:27
    |
 LL |     let _ = Alias::None::<u8>;
-   |                           ^^ type argument not allowed
+   |                    ----   ^^ type argument not allowed
+   |                    |
+   |                    not allowed on this
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type/issue-91268.rs b/src/test/ui/type/issue-91268.rs
index fd2733c1c54..01ed9ea9e23 100644
--- a/src/test/ui/type/issue-91268.rs
+++ b/src/test/ui/type/issue-91268.rs
@@ -1,7 +1,7 @@
 // error-pattern: this file contains an unclosed delimiter
 // error-pattern: cannot find type `ţ` in this scope
 // error-pattern: parenthesized type parameters may only be used with a `Fn` trait
-// error-pattern: type arguments are not allowed for this type
+// error-pattern: type arguments are not allowed on this type
 // error-pattern: mismatched types
 // ignore-tidy-trailing-newlines
 // `ţ` must be the last character in this file, it cannot be followed by a newline
diff --git a/src/test/ui/type/issue-91268.stderr b/src/test/ui/type/issue-91268.stderr
index 2fe6ba6248c..199fd6a23f7 100644
--- a/src/test/ui/type/issue-91268.stderr
+++ b/src/test/ui/type/issue-91268.stderr
@@ -30,11 +30,19 @@ error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
 LL |     0: u8(ţ
    |        ^^^^ only `Fn` traits may use parentheses
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/issue-91268.rs:9:11
    |
 LL |     0: u8(ţ
-   |           ^ type argument not allowed
+   |        -- ^ type argument not allowed
+   |        |
+   |        not allowed on this
+   |
+help: primitive type `u8` doesn't have generic parameters
+   |
+LL -     0: u8(ţ
+LL +     0: u8
+   | 
 
 error[E0308]: mismatched types
   --> $DIR/issue-91268.rs:9:5
diff --git a/src/test/ui/typeck/prim-with-args.fixed b/src/test/ui/typeck/prim-with-args.fixed
new file mode 100644
index 00000000000..1c5fd750867
--- /dev/null
+++ b/src/test/ui/typeck/prim-with-args.fixed
@@ -0,0 +1,28 @@
+// run-rustfix
+fn main() {
+
+let _x: isize; //~ ERROR type arguments are not allowed on this type
+let _x: i8; //~ ERROR type arguments are not allowed on this type
+let _x: i16; //~ ERROR type arguments are not allowed on this type
+let _x: i32; //~ ERROR type arguments are not allowed on this type
+let _x: i64; //~ ERROR type arguments are not allowed on this type
+let _x: usize; //~ ERROR type arguments are not allowed on this type
+let _x: u8; //~ ERROR type arguments are not allowed on this type
+let _x: u16; //~ ERROR type arguments are not allowed on this type
+let _x: u32; //~ ERROR type arguments are not allowed on this type
+let _x: u64; //~ ERROR type arguments are not allowed on this type
+let _x: char; //~ ERROR type arguments are not allowed on this type
+
+let _x: isize; //~ ERROR lifetime arguments are not allowed on this type
+let _x: i8; //~ ERROR lifetime arguments are not allowed on this type
+let _x: i16; //~ ERROR lifetime arguments are not allowed on this type
+let _x: i32; //~ ERROR lifetime arguments are not allowed on this type
+let _x: i64; //~ ERROR lifetime arguments are not allowed on this type
+let _x: usize; //~ ERROR lifetime arguments are not allowed on this type
+let _x: u8; //~ ERROR lifetime arguments are not allowed on this type
+let _x: u16; //~ ERROR lifetime arguments are not allowed on this type
+let _x: u32; //~ ERROR lifetime arguments are not allowed on this type
+let _x: u64; //~ ERROR lifetime arguments are not allowed on this type
+let _x: char; //~ ERROR lifetime arguments are not allowed on this type
+
+}
diff --git a/src/test/ui/typeck/prim-with-args.rs b/src/test/ui/typeck/prim-with-args.rs
index e5beaca6abb..b05d6c1cb4e 100644
--- a/src/test/ui/typeck/prim-with-args.rs
+++ b/src/test/ui/typeck/prim-with-args.rs
@@ -1,27 +1,28 @@
+// run-rustfix
 fn main() {
 
-let x: isize<isize>; //~ ERROR type arguments are not allowed for this type
-let x: i8<isize>; //~ ERROR type arguments are not allowed for this type
-let x: i16<isize>; //~ ERROR type arguments are not allowed for this type
-let x: i32<isize>; //~ ERROR type arguments are not allowed for this type
-let x: i64<isize>; //~ ERROR type arguments are not allowed for this type
-let x: usize<isize>; //~ ERROR type arguments are not allowed for this type
-let x: u8<isize>; //~ ERROR type arguments are not allowed for this type
-let x: u16<isize>; //~ ERROR type arguments are not allowed for this type
-let x: u32<isize>; //~ ERROR type arguments are not allowed for this type
-let x: u64<isize>; //~ ERROR type arguments are not allowed for this type
-let x: char<isize>; //~ ERROR type arguments are not allowed for this type
+let _x: isize<isize>; //~ ERROR type arguments are not allowed on this type
+let _x: i8<isize>; //~ ERROR type arguments are not allowed on this type
+let _x: i16<isize>; //~ ERROR type arguments are not allowed on this type
+let _x: i32<isize>; //~ ERROR type arguments are not allowed on this type
+let _x: i64<isize>; //~ ERROR type arguments are not allowed on this type
+let _x: usize<isize>; //~ ERROR type arguments are not allowed on this type
+let _x: u8<isize>; //~ ERROR type arguments are not allowed on this type
+let _x: u16<isize>; //~ ERROR type arguments are not allowed on this type
+let _x: u32<isize>; //~ ERROR type arguments are not allowed on this type
+let _x: u64<isize>; //~ ERROR type arguments are not allowed on this type
+let _x: char<isize>; //~ ERROR type arguments are not allowed on this type
 
-let x: isize<'static>; //~ ERROR lifetime arguments are not allowed for this type
-let x: i8<'static>; //~ ERROR lifetime arguments are not allowed for this type
-let x: i16<'static>; //~ ERROR lifetime arguments are not allowed for this type
-let x: i32<'static>; //~ ERROR lifetime arguments are not allowed for this type
-let x: i64<'static>; //~ ERROR lifetime arguments are not allowed for this type
-let x: usize<'static>; //~ ERROR lifetime arguments are not allowed for this type
-let x: u8<'static>; //~ ERROR lifetime arguments are not allowed for this type
-let x: u16<'static>; //~ ERROR lifetime arguments are not allowed for this type
-let x: u32<'static>; //~ ERROR lifetime arguments are not allowed for this type
-let x: u64<'static>; //~ ERROR lifetime arguments are not allowed for this type
-let x: char<'static>; //~ ERROR lifetime arguments are not allowed for this type
+let _x: isize<'static>; //~ ERROR lifetime arguments are not allowed on this type
+let _x: i8<'static>; //~ ERROR lifetime arguments are not allowed on this type
+let _x: i16<'static>; //~ ERROR lifetime arguments are not allowed on this type
+let _x: i32<'static>; //~ ERROR lifetime arguments are not allowed on this type
+let _x: i64<'static>; //~ ERROR lifetime arguments are not allowed on this type
+let _x: usize<'static>; //~ ERROR lifetime arguments are not allowed on this type
+let _x: u8<'static>; //~ ERROR lifetime arguments are not allowed on this type
+let _x: u16<'static>; //~ ERROR lifetime arguments are not allowed on this type
+let _x: u32<'static>; //~ ERROR lifetime arguments are not allowed on this type
+let _x: u64<'static>; //~ ERROR lifetime arguments are not allowed on this type
+let _x: char<'static>; //~ ERROR lifetime arguments are not allowed on this type
 
 }
diff --git a/src/test/ui/typeck/prim-with-args.stderr b/src/test/ui/typeck/prim-with-args.stderr
index 4bde981e7f2..7e7bc580b3b 100644
--- a/src/test/ui/typeck/prim-with-args.stderr
+++ b/src/test/ui/typeck/prim-with-args.stderr
@@ -1,134 +1,310 @@
-error[E0109]: type arguments are not allowed for this type
-  --> $DIR/prim-with-args.rs:3:14
+error[E0109]: type arguments are not allowed on this type
+  --> $DIR/prim-with-args.rs:4:15
    |
-LL | let x: isize<isize>;
-   |              ^^^^^ type argument not allowed
-
-error[E0109]: type arguments are not allowed for this type
-  --> $DIR/prim-with-args.rs:4:11
+LL | let _x: isize<isize>;
+   |         ----- ^^^^^ type argument not allowed
+   |         |
+   |         not allowed on this
+   |
+help: primitive type `isize` doesn't have generic parameters
    |
-LL | let x: i8<isize>;
-   |           ^^^^^ type argument not allowed
+LL - let _x: isize<isize>;
+LL + let _x: isize;
+   | 
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/prim-with-args.rs:5:12
    |
-LL | let x: i16<isize>;
-   |            ^^^^^ type argument not allowed
+LL | let _x: i8<isize>;
+   |         -- ^^^^^ type argument not allowed
+   |         |
+   |         not allowed on this
+   |
+help: primitive type `i8` doesn't have generic parameters
+   |
+LL - let _x: i8<isize>;
+LL + let _x: i8;
+   | 
 
-error[E0109]: type arguments are not allowed for this type
-  --> $DIR/prim-with-args.rs:6:12
+error[E0109]: type arguments are not allowed on this type
+  --> $DIR/prim-with-args.rs:6:13
+   |
+LL | let _x: i16<isize>;
+   |         --- ^^^^^ type argument not allowed
+   |         |
+   |         not allowed on this
+   |
+help: primitive type `i16` doesn't have generic parameters
    |
-LL | let x: i32<isize>;
-   |            ^^^^^ type argument not allowed
+LL - let _x: i16<isize>;
+LL + let _x: i16;
+   | 
 
-error[E0109]: type arguments are not allowed for this type
-  --> $DIR/prim-with-args.rs:7:12
+error[E0109]: type arguments are not allowed on this type
+  --> $DIR/prim-with-args.rs:7:13
    |
-LL | let x: i64<isize>;
-   |            ^^^^^ type argument not allowed
+LL | let _x: i32<isize>;
+   |         --- ^^^^^ type argument not allowed
+   |         |
+   |         not allowed on this
+   |
+help: primitive type `i32` doesn't have generic parameters
+   |
+LL - let _x: i32<isize>;
+LL + let _x: i32;
+   | 
 
-error[E0109]: type arguments are not allowed for this type
-  --> $DIR/prim-with-args.rs:8:14
+error[E0109]: type arguments are not allowed on this type
+  --> $DIR/prim-with-args.rs:8:13
+   |
+LL | let _x: i64<isize>;
+   |         --- ^^^^^ type argument not allowed
+   |         |
+   |         not allowed on this
    |
-LL | let x: usize<isize>;
-   |              ^^^^^ type argument not allowed
+help: primitive type `i64` doesn't have generic parameters
+   |
+LL - let _x: i64<isize>;
+LL + let _x: i64;
+   | 
 
-error[E0109]: type arguments are not allowed for this type
-  --> $DIR/prim-with-args.rs:9:11
+error[E0109]: type arguments are not allowed on this type
+  --> $DIR/prim-with-args.rs:9:15
+   |
+LL | let _x: usize<isize>;
+   |         ----- ^^^^^ type argument not allowed
+   |         |
+   |         not allowed on this
+   |
+help: primitive type `usize` doesn't have generic parameters
    |
-LL | let x: u8<isize>;
-   |           ^^^^^ type argument not allowed
+LL - let _x: usize<isize>;
+LL + let _x: usize;
+   | 
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/prim-with-args.rs:10:12
    |
-LL | let x: u16<isize>;
-   |            ^^^^^ type argument not allowed
+LL | let _x: u8<isize>;
+   |         -- ^^^^^ type argument not allowed
+   |         |
+   |         not allowed on this
+   |
+help: primitive type `u8` doesn't have generic parameters
+   |
+LL - let _x: u8<isize>;
+LL + let _x: u8;
+   | 
 
-error[E0109]: type arguments are not allowed for this type
-  --> $DIR/prim-with-args.rs:11:12
+error[E0109]: type arguments are not allowed on this type
+  --> $DIR/prim-with-args.rs:11:13
+   |
+LL | let _x: u16<isize>;
+   |         --- ^^^^^ type argument not allowed
+   |         |
+   |         not allowed on this
    |
-LL | let x: u32<isize>;
-   |            ^^^^^ type argument not allowed
+help: primitive type `u16` doesn't have generic parameters
+   |
+LL - let _x: u16<isize>;
+LL + let _x: u16;
+   | 
 
-error[E0109]: type arguments are not allowed for this type
-  --> $DIR/prim-with-args.rs:12:12
+error[E0109]: type arguments are not allowed on this type
+  --> $DIR/prim-with-args.rs:12:13
+   |
+LL | let _x: u32<isize>;
+   |         --- ^^^^^ type argument not allowed
+   |         |
+   |         not allowed on this
+   |
+help: primitive type `u32` doesn't have generic parameters
    |
-LL | let x: u64<isize>;
-   |            ^^^^^ type argument not allowed
+LL - let _x: u32<isize>;
+LL + let _x: u32;
+   | 
 
-error[E0109]: type arguments are not allowed for this type
+error[E0109]: type arguments are not allowed on this type
   --> $DIR/prim-with-args.rs:13:13
    |
-LL | let x: char<isize>;
-   |             ^^^^^ type argument not allowed
+LL | let _x: u64<isize>;
+   |         --- ^^^^^ type argument not allowed
+   |         |
+   |         not allowed on this
+   |
+help: primitive type `u64` doesn't have generic parameters
+   |
+LL - let _x: u64<isize>;
+LL + let _x: u64;
+   | 
 
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/prim-with-args.rs:15:14
+error[E0109]: type arguments are not allowed on this type
+  --> $DIR/prim-with-args.rs:14:14
+   |
+LL | let _x: char<isize>;
+   |         ---- ^^^^^ type argument not allowed
+   |         |
+   |         not allowed on this
    |
-LL | let x: isize<'static>;
-   |              ^^^^^^^ lifetime argument not allowed
+help: primitive type `char` doesn't have generic parameters
+   |
+LL - let _x: char<isize>;
+LL + let _x: char;
+   | 
 
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/prim-with-args.rs:16:11
+error[E0109]: lifetime arguments are not allowed on this type
+  --> $DIR/prim-with-args.rs:16:15
+   |
+LL | let _x: isize<'static>;
+   |         ----- ^^^^^^^ lifetime argument not allowed
+   |         |
+   |         not allowed on this
    |
-LL | let x: i8<'static>;
-   |           ^^^^^^^ lifetime argument not allowed
+help: primitive type `isize` doesn't have generic parameters
+   |
+LL - let _x: isize<'static>;
+LL + let _x: isize;
+   | 
 
-error[E0109]: lifetime arguments are not allowed for this type
+error[E0109]: lifetime arguments are not allowed on this type
   --> $DIR/prim-with-args.rs:17:12
    |
-LL | let x: i16<'static>;
-   |            ^^^^^^^ lifetime argument not allowed
+LL | let _x: i8<'static>;
+   |         -- ^^^^^^^ lifetime argument not allowed
+   |         |
+   |         not allowed on this
+   |
+help: primitive type `i8` doesn't have generic parameters
+   |
+LL - let _x: i8<'static>;
+LL + let _x: i8;
+   | 
 
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/prim-with-args.rs:18:12
+error[E0109]: lifetime arguments are not allowed on this type
+  --> $DIR/prim-with-args.rs:18:13
    |
-LL | let x: i32<'static>;
-   |            ^^^^^^^ lifetime argument not allowed
+LL | let _x: i16<'static>;
+   |         --- ^^^^^^^ lifetime argument not allowed
+   |         |
+   |         not allowed on this
+   |
+help: primitive type `i16` doesn't have generic parameters
+   |
+LL - let _x: i16<'static>;
+LL + let _x: i16;
+   | 
 
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/prim-with-args.rs:19:12
+error[E0109]: lifetime arguments are not allowed on this type
+  --> $DIR/prim-with-args.rs:19:13
+   |
+LL | let _x: i32<'static>;
+   |         --- ^^^^^^^ lifetime argument not allowed
+   |         |
+   |         not allowed on this
    |
-LL | let x: i64<'static>;
-   |            ^^^^^^^ lifetime argument not allowed
+help: primitive type `i32` doesn't have generic parameters
+   |
+LL - let _x: i32<'static>;
+LL + let _x: i32;
+   | 
 
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/prim-with-args.rs:20:14
+error[E0109]: lifetime arguments are not allowed on this type
+  --> $DIR/prim-with-args.rs:20:13
+   |
+LL | let _x: i64<'static>;
+   |         --- ^^^^^^^ lifetime argument not allowed
+   |         |
+   |         not allowed on this
+   |
+help: primitive type `i64` doesn't have generic parameters
    |
-LL | let x: usize<'static>;
-   |              ^^^^^^^ lifetime argument not allowed
+LL - let _x: i64<'static>;
+LL + let _x: i64;
+   | 
 
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/prim-with-args.rs:21:11
+error[E0109]: lifetime arguments are not allowed on this type
+  --> $DIR/prim-with-args.rs:21:15
    |
-LL | let x: u8<'static>;
-   |           ^^^^^^^ lifetime argument not allowed
+LL | let _x: usize<'static>;
+   |         ----- ^^^^^^^ lifetime argument not allowed
+   |         |
+   |         not allowed on this
+   |
+help: primitive type `usize` doesn't have generic parameters
+   |
+LL - let _x: usize<'static>;
+LL + let _x: usize;
+   | 
 
-error[E0109]: lifetime arguments are not allowed for this type
+error[E0109]: lifetime arguments are not allowed on this type
   --> $DIR/prim-with-args.rs:22:12
    |
-LL | let x: u16<'static>;
-   |            ^^^^^^^ lifetime argument not allowed
+LL | let _x: u8<'static>;
+   |         -- ^^^^^^^ lifetime argument not allowed
+   |         |
+   |         not allowed on this
+   |
+help: primitive type `u8` doesn't have generic parameters
+   |
+LL - let _x: u8<'static>;
+LL + let _x: u8;
+   | 
 
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/prim-with-args.rs:23:12
+error[E0109]: lifetime arguments are not allowed on this type
+  --> $DIR/prim-with-args.rs:23:13
+   |
+LL | let _x: u16<'static>;
+   |         --- ^^^^^^^ lifetime argument not allowed
+   |         |
+   |         not allowed on this
+   |
+help: primitive type `u16` doesn't have generic parameters
    |
-LL | let x: u32<'static>;
-   |            ^^^^^^^ lifetime argument not allowed
+LL - let _x: u16<'static>;
+LL + let _x: u16;
+   | 
 
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/prim-with-args.rs:24:12
+error[E0109]: lifetime arguments are not allowed on this type
+  --> $DIR/prim-with-args.rs:24:13
    |
-LL | let x: u64<'static>;
-   |            ^^^^^^^ lifetime argument not allowed
+LL | let _x: u32<'static>;
+   |         --- ^^^^^^^ lifetime argument not allowed
+   |         |
+   |         not allowed on this
+   |
+help: primitive type `u32` doesn't have generic parameters
+   |
+LL - let _x: u32<'static>;
+LL + let _x: u32;
+   | 
 
-error[E0109]: lifetime arguments are not allowed for this type
+error[E0109]: lifetime arguments are not allowed on this type
   --> $DIR/prim-with-args.rs:25:13
    |
-LL | let x: char<'static>;
-   |             ^^^^^^^ lifetime argument not allowed
+LL | let _x: u64<'static>;
+   |         --- ^^^^^^^ lifetime argument not allowed
+   |         |
+   |         not allowed on this
+   |
+help: primitive type `u64` doesn't have generic parameters
+   |
+LL - let _x: u64<'static>;
+LL + let _x: u64;
+   | 
+
+error[E0109]: lifetime arguments are not allowed on this type
+  --> $DIR/prim-with-args.rs:26:14
+   |
+LL | let _x: char<'static>;
+   |         ---- ^^^^^^^ lifetime argument not allowed
+   |         |
+   |         not allowed on this
+   |
+help: primitive type `char` doesn't have generic parameters
+   |
+LL - let _x: char<'static>;
+LL + let _x: char;
+   | 
 
 error: aborting due to 22 previous errors
 
diff --git a/src/test/ui/usize-generic-argument-parent.rs b/src/test/ui/usize-generic-argument-parent.rs
index 46b06e2b366..6d17ba9b5b2 100644
--- a/src/test/ui/usize-generic-argument-parent.rs
+++ b/src/test/ui/usize-generic-argument-parent.rs
@@ -1,5 +1,5 @@
 fn foo() {
-    let x: usize<foo>; //~ ERROR const arguments are not allowed for this type
+    let x: usize<foo>; //~ ERROR const arguments are not allowed on this type
 }
 
 fn main() {}
diff --git a/src/test/ui/usize-generic-argument-parent.stderr b/src/test/ui/usize-generic-argument-parent.stderr
index f1eae3b5008..c657f0faa0b 100644
--- a/src/test/ui/usize-generic-argument-parent.stderr
+++ b/src/test/ui/usize-generic-argument-parent.stderr
@@ -1,8 +1,16 @@
-error[E0109]: const arguments are not allowed for this type
+error[E0109]: const arguments are not allowed on this type
   --> $DIR/usize-generic-argument-parent.rs:2:18
    |
 LL |     let x: usize<foo>;
-   |                  ^^^ const argument not allowed
+   |            ----- ^^^ const argument not allowed
+   |            |
+   |            not allowed on this
+   |
+help: primitive type `usize` doesn't have generic parameters
+   |
+LL -     let x: usize<foo>;
+LL +     let x: usize;
+   | 
 
 error: aborting due to previous error
 
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index 51d5b510ab9..070c7e59142 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -371,7 +371,7 @@ impl<'a, 'tcx> RefVisitor<'a, 'tcx> {
         if let Some(ref lt) = *lifetime {
             if lt.name == LifetimeName::Static {
                 self.lts.push(RefLt::Static);
-            } else if let LifetimeName::Param(ParamName::Fresh(_)) = lt.name {
+            } else if let LifetimeName::Param(_, ParamName::Fresh) = lt.name {
                 // Fresh lifetimes generated should be ignored.
             } else if lt.is_elided() {
                 self.lts.push(RefLt::Unnamed);
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index 548f7b2528b..0b96f6ff683 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -343,7 +343,7 @@ impl fmt::Display for RefPrefix {
         use fmt::Write;
         f.write_char('&')?;
         match self.lt {
-            LifetimeName::Param(ParamName::Plain(name)) => {
+            LifetimeName::Param(_, ParamName::Plain(name)) => {
                 name.fmt(f)?;
                 f.write_char(' ')?;
             },
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index c440793b90e..fc1a4e1f602 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -902,16 +902,14 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
 
     pub fn hash_lifetime(&mut self, lifetime: Lifetime) {
         std::mem::discriminant(&lifetime.name).hash(&mut self.s);
-        if let LifetimeName::Param(ref name) = lifetime.name {
+        if let LifetimeName::Param(param_id, ref name) = lifetime.name {
             std::mem::discriminant(name).hash(&mut self.s);
+            param_id.hash(&mut self.s);
             match name {
                 ParamName::Plain(ref ident) => {
                     ident.name.hash(&mut self.s);
                 },
-                ParamName::Fresh(ref size) => {
-                    size.hash(&mut self.s);
-                },
-                ParamName::Error => {},
+                ParamName::Fresh | ParamName::Error => {},
             }
         }
     }