about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatryk Wychowaniec <pwychowaniec@pm.me>2021-01-02 19:45:11 +0100
committerPatryk Wychowaniec <pwychowaniec@pm.me>2021-01-10 13:07:40 +0100
commitd2f8e398f19b5b3d38646328ec158f50db6b8b06 (patch)
tree2bda5bffd2730c12e6d4a0104ec720f76f17a9ae
parent34628e5b533d35840b61c5db0665cf7633ed3c5a (diff)
downloadrust-d2f8e398f19b5b3d38646328ec158f50db6b8b06.tar.gz
rust-d2f8e398f19b5b3d38646328ec158f50db6b8b06.zip
Rework diagnostics for wrong number of generic args
-rw-r--r--compiler/rustc_ast/src/ast.rs11
-rw-r--r--compiler/rustc_ast/src/lib.rs1
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/path.rs6
-rw-r--r--compiler/rustc_hir/src/hir.rs55
-rw-r--r--compiler/rustc_hir/src/lang_items.rs2
-rw-r--r--compiler/rustc_hir/src/lib.rs1
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs16
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs14
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs3
-rw-r--r--compiler/rustc_middle/src/query/mod.rs9
-rw-r--r--compiler/rustc_middle/src/ty/error.rs2
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs22
-rw-r--r--compiler/rustc_parse/src/parser/path.rs3
-rw-r--r--compiler/rustc_resolve/src/late/lifetimes.rs2
-rw-r--r--compiler/rustc_span/src/source_map.rs29
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs5
-rw-r--r--compiler/rustc_typeck/src/astconv/errors.rs4
-rw-r--r--compiler/rustc_typeck/src/astconv/generics.rs231
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs48
-rw-r--r--compiler/rustc_typeck/src/check/cast.rs15
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs13
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/checks.rs33
-rw-r--r--compiler/rustc_typeck/src/check/method/confirm.rs10
-rw-r--r--compiler/rustc_typeck/src/collect.rs6
-rw-r--r--compiler/rustc_typeck/src/structured_errors.rs147
-rw-r--r--compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs58
-rw-r--r--compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs57
-rw-r--r--compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs393
-rw-r--r--library/core/src/slice/raw.rs2
-rw-r--r--src/librustdoc/clean/mod.rs4
-rw-r--r--src/test/ui/async-await/issues/issue-65159.rs3
-rw-r--r--src/test/ui/async-await/issues/issue-65159.stderr18
-rw-r--r--src/test/ui/bad/bad-mid-path-type-params.rs11
-rw-r--r--src/test/ui/bad/bad-mid-path-type-params.stderr74
-rw-r--r--src/test/ui/const-generics/incorrect-number-of-const-args.full.stderr30
-rw-r--r--src/test/ui/const-generics/incorrect-number-of-const-args.min.stderr30
-rw-r--r--src/test/ui/const-generics/incorrect-number-of-const-args.rs7
-rw-r--r--src/test/ui/const-generics/invalid-const-arg-for-type-param.rs11
-rw-r--r--src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr30
-rw-r--r--src/test/ui/const-generics/invalid-constant-in-args.rs2
-rw-r--r--src/test/ui/const-generics/invalid-constant-in-args.stderr14
-rw-r--r--src/test/ui/const-generics/issues/issue-76595.rs2
-rw-r--r--src/test/ui/const-generics/issues/issue-76595.stderr16
-rw-r--r--src/test/ui/constructor-lifetime-args.rs8
-rw-r--r--src/test/ui/constructor-lifetime-args.stderr62
-rw-r--r--src/test/ui/error-codes/E0107.rs15
-rw-r--r--src/test/ui/error-codes/E0107.stderr46
-rw-r--r--src/test/ui/generic-associated-types/parameter_number_and_kind.rs6
-rw-r--r--src/test/ui/generic-associated-types/parameter_number_and_kind.stderr44
-rw-r--r--src/test/ui/generics/generic-arg-mismatch-recover.rs8
-rw-r--r--src/test/ui/generics/generic-arg-mismatch-recover.stderr42
-rw-r--r--src/test/ui/generics/generic-impl-less-params-with-defaults.rs2
-rw-r--r--src/test/ui/generics/generic-impl-less-params-with-defaults.stderr16
-rw-r--r--src/test/ui/generics/generic-impl-more-params-with-defaults.rs2
-rw-r--r--src/test/ui/generics/generic-impl-more-params-with-defaults.stderr14
-rw-r--r--src/test/ui/generics/generic-type-less-params-with-defaults.rs2
-rw-r--r--src/test/ui/generics/generic-type-less-params-with-defaults.stderr12
-rw-r--r--src/test/ui/generics/generic-type-more-params-with-defaults.rs2
-rw-r--r--src/test/ui/generics/generic-type-more-params-with-defaults.stderr14
-rw-r--r--src/test/ui/generics/wrong-number-of-args.rs161
-rw-r--r--src/test/ui/generics/wrong-number-of-args.stderr449
-rw-r--r--src/test/ui/issues/issue-14092.rs2
-rw-r--r--src/test/ui/issues/issue-14092.stderr14
-rw-r--r--src/test/ui/issues/issue-16939.stderr6
-rw-r--r--src/test/ui/issues/issue-18423.rs6
-rw-r--r--src/test/ui/issues/issue-18423.stderr14
-rw-r--r--src/test/ui/issues/issue-23024.rs2
-rw-r--r--src/test/ui/issues/issue-23024.stderr12
-rw-r--r--src/test/ui/issues/issue-3044.stderr6
-rw-r--r--src/test/ui/issues/issue-3214.rs2
-rw-r--r--src/test/ui/issues/issue-3214.stderr14
-rw-r--r--src/test/ui/issues/issue-53251.rs8
-rw-r--r--src/test/ui/issues/issue-53251.stderr26
-rw-r--r--src/test/ui/issues/issue-60622.rs4
-rw-r--r--src/test/ui/issues/issue-60622.stderr14
-rw-r--r--src/test/ui/methods/method-call-lifetime-args-fail.rs10
-rw-r--r--src/test/ui/methods/method-call-lifetime-args-fail.stderr120
-rw-r--r--src/test/ui/mismatched_types/overloaded-calls-bad.stderr12
-rw-r--r--src/test/ui/resolve/resolve-primitive-fallback.stderr6
-rw-r--r--src/test/ui/seq-args.rs16
-rw-r--r--src/test/ui/seq-args.stderr30
-rw-r--r--src/test/ui/structs/structure-constructor-type-mismatch.rs6
-rw-r--r--src/test/ui/structs/structure-constructor-type-mismatch.stderr50
-rw-r--r--src/test/ui/suggestions/missing-lifetime-specifier.rs16
-rw-r--r--src/test/ui/suggestions/missing-lifetime-specifier.stderr128
-rw-r--r--src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.rs2
-rw-r--r--src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr16
-rw-r--r--src/test/ui/tag-type-args.rs2
-rw-r--r--src/test/ui/tag-type-args.stderr12
-rw-r--r--src/test/ui/traits/trait-object-vs-lifetime.rs4
-rw-r--r--src/test/ui/traits/trait-object-vs-lifetime.stderr28
-rw-r--r--src/test/ui/traits/trait-test-2.rs6
-rw-r--r--src/test/ui/traits/trait-test-2.stderr32
-rw-r--r--src/test/ui/type-alias-enum-variants/enum-variant-generic-args.rs26
-rw-r--r--src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr84
-rw-r--r--src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr6
-rw-r--r--src/test/ui/type/ascription/issue-34255-1.rs2
-rw-r--r--src/test/ui/type/ascription/issue-34255-1.stderr14
-rw-r--r--src/test/ui/type/type-ascription-instead-of-initializer.stderr6
-rw-r--r--src/test/ui/typeck/typeck-builtin-bound-type-parameters.rs16
-rw-r--r--src/test/ui/typeck/typeck-builtin-bound-type-parameters.stderr84
-rw-r--r--src/test/ui/typeck/typeck_type_placeholder_lifetime_1.rs2
-rw-r--r--src/test/ui/typeck/typeck_type_placeholder_lifetime_1.stderr14
-rw-r--r--src/test/ui/typeck/typeck_type_placeholder_lifetime_2.rs2
-rw-r--r--src/test/ui/typeck/typeck_type_placeholder_lifetime_2.stderr14
-rw-r--r--src/test/ui/ufcs/ufcs-qpath-missing-params.rs6
-rw-r--r--src/test/ui/ufcs/ufcs-qpath-missing-params.stderr48
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closure-sugar-region.rs2
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closure-sugar-region.stderr10
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs2
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr14
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs2
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr14
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs2
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr12
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.rs24
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr92
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.rs4
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr12
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/hir_utils.rs2
121 files changed, 2760 insertions, 739 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 8601da6fa06..e933eb434a1 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -242,12 +242,21 @@ impl Into<Option<P<GenericArgs>>> for ParenthesizedArgs {
 /// A path like `Foo(A, B) -> C`.
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct ParenthesizedArgs {
-    /// Overall span
+    /// ```text
+    /// Foo(A, B) -> C
+    /// ^^^^^^^^^^^^^^
+    /// ```
     pub span: Span,
 
     /// `(A, B)`
     pub inputs: Vec<P<Ty>>,
 
+    /// ```text
+    /// Foo(A, B) -> C
+    ///    ^^^^^^
+    /// ```
+    pub inputs_span: Span,
+
     /// `C`
     pub output: FnRetTy,
 }
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index 8a20dd79685..08695491de7 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -13,6 +13,7 @@
 #![feature(const_fn_transmute)]
 #![feature(const_panic)]
 #![feature(crate_visibility_modifier)]
+#![feature(iterator_fold_self)]
 #![feature(label_break_value)]
 #![feature(nll)]
 #![feature(or_patterns)]
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 575552c4dce..35de744d274 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -565,7 +565,7 @@ pub fn noop_visit_parenthesized_parameter_data<T: MutVisitor>(
     args: &mut ParenthesizedArgs,
     vis: &mut T,
 ) {
-    let ParenthesizedArgs { inputs, output, span } = args;
+    let ParenthesizedArgs { inputs, output, span, .. } = args;
     visit_vec(inputs, |input| vis.visit_ty(input));
     noop_visit_fn_ret_ty(output, vis);
     vis.visit_span(span);
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 6afed355dc3..9325d4c4139 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -401,15 +401,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         // compatibility, even in contexts like an impl header where
         // we generally don't permit such things (see #51008).
         self.with_anonymous_lifetime_mode(AnonymousLifetimeMode::PassThrough, |this| {
-            let &ParenthesizedArgs { ref inputs, ref output, span } = data;
+            let ParenthesizedArgs { span, inputs, inputs_span, output } = data;
             let inputs = this.arena.alloc_from_iter(
                 inputs.iter().map(|ty| this.lower_ty_direct(ty, ImplTraitContext::disallowed())),
             );
             let output_ty = match output {
                 FnRetTy::Ty(ty) => this.lower_ty(&ty, ImplTraitContext::disallowed()),
-                FnRetTy::Default(_) => this.arena.alloc(this.ty_tup(span, &[])),
+                FnRetTy::Default(_) => this.arena.alloc(this.ty_tup(*span, &[])),
             };
-            let args = smallvec![GenericArg::Type(this.ty_tup(span, inputs))];
+            let args = smallvec![GenericArg::Type(this.ty_tup(*inputs_span, inputs))];
             let binding = this.output_ty_binding(output_ty.span, output_ty);
             (
                 GenericArgsCtor { args, bindings: arena_vec![this; binding], parenthesized: true },
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index acd254ae85c..003ca258c27 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -11,9 +11,9 @@ pub use rustc_ast::{CaptureBy, Movability, Mutability};
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
 use rustc_macros::HashStable_Generic;
-use rustc_span::def_id::LocalDefId;
-use rustc_span::source_map::Spanned;
+use rustc_span::source_map::{SourceMap, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::{def_id::LocalDefId, BytePos};
 use rustc_span::{MultiSpan, Span, DUMMY_SP};
 use rustc_target::asm::InlineAsmRegOrRegClass;
 use rustc_target::spec::abi::Abi;
@@ -231,7 +231,11 @@ impl<'hir> PathSegment<'hir> {
         PathSegment { ident, hir_id: None, res: None, infer_args: true, args: None }
     }
 
-    pub fn generic_args(&self) -> &GenericArgs<'hir> {
+    pub fn invalid() -> Self {
+        Self::from_ident(Ident::invalid())
+    }
+
+    pub fn args(&self) -> &GenericArgs<'hir> {
         if let Some(ref args) = self.args {
             args
         } else {
@@ -275,19 +279,15 @@ impl GenericArg<'_> {
         matches!(self, GenericArg::Const(_))
     }
 
-    pub fn descr(&self) -> &'static str {
-        match self {
-            GenericArg::Lifetime(_) => "lifetime",
-            GenericArg::Type(_) => "type",
-            GenericArg::Const(_) => "constant",
-        }
+    pub fn is_synthetic(&self) -> bool {
+        matches!(self, GenericArg::Lifetime(lifetime) if lifetime.name.ident() == Ident::invalid())
     }
 
-    pub fn short_descr(&self) -> &'static str {
+    pub fn descr(&self) -> &'static str {
         match self {
             GenericArg::Lifetime(_) => "lifetime",
             GenericArg::Type(_) => "type",
-            GenericArg::Const(_) => "const",
+            GenericArg::Const(_) => "constant",
         }
     }
 
@@ -352,6 +352,39 @@ impl GenericArgs<'_> {
 
         own_counts
     }
+
+    pub fn span(&self) -> Option<Span> {
+        self.args
+            .iter()
+            .filter(|arg| !arg.is_synthetic())
+            .map(|arg| arg.span())
+            .fold_first(|span1, span2| span1.to(span2))
+    }
+
+    /// Returns span encompassing arguments and their surrounding `<>` or `()`
+    pub fn span_ext(&self, sm: &SourceMap) -> Option<Span> {
+        let mut span = self.span()?;
+
+        let (o, c) = if self.parenthesized { ('(', ')') } else { ('<', '>') };
+
+        if let Ok(snippet) = sm.span_to_snippet(span) {
+            let snippet = snippet.as_bytes();
+
+            if snippet[0] != (o as u8) || snippet[snippet.len() - 1] != (c as u8) {
+                span = sm.span_extend_to_prev_char(span, o, true);
+                span = span.with_lo(span.lo() - BytePos(1));
+
+                span = sm.span_extend_to_next_char(span, c, true);
+                span = span.with_hi(span.hi() + BytePos(1));
+            }
+        }
+
+        Some(span)
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.args.is_empty()
+    }
 }
 
 /// A modifier on a bound, currently this is only used for `?Sized`, where the
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 3e4eb9eafd7..e82ea310b8c 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -157,7 +157,7 @@ where
 }
 
 language_item_table! {
-//  Variant name,            Name,                    Method name,             Target;
+//  Variant name,            Name,                     Method name,                Target;
     Bool,                    sym::bool,                bool_impl,                  Target::Impl;
     Char,                    sym::char,                char_impl,                  Target::Impl;
     Str,                     sym::str,                 str_impl,                   Target::Impl;
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
index 9d931b3a9e1..8b55ec6c705 100644
--- a/compiler/rustc_hir/src/lib.rs
+++ b/compiler/rustc_hir/src/lib.rs
@@ -7,6 +7,7 @@
 #![feature(const_fn)] // For the unsizing cast on `&[]`
 #![feature(const_panic)]
 #![feature(in_band_lifetimes)]
+#![feature(iterator_fold_self)]
 #![feature(once_cell)]
 #![feature(or_patterns)]
 #![recursion_limit = "256"]
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index a9aa192bbcc..e5438ddb85d 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1213,7 +1213,7 @@ impl<'a> State<'a> {
         self.s.word(".");
         self.print_ident(segment.ident);
 
-        let generic_args = segment.generic_args();
+        let generic_args = segment.args();
         if !generic_args.args.is_empty() || !generic_args.bindings.is_empty() {
             self.print_generic_args(generic_args, segment.infer_args, true);
         }
@@ -1661,11 +1661,7 @@ impl<'a> State<'a> {
             }
             if segment.ident.name != kw::PathRoot {
                 self.print_ident(segment.ident);
-                self.print_generic_args(
-                    segment.generic_args(),
-                    segment.infer_args,
-                    colons_before_params,
-                );
+                self.print_generic_args(segment.args(), segment.infer_args, colons_before_params);
             }
         }
     }
@@ -1673,7 +1669,7 @@ impl<'a> State<'a> {
     pub fn print_path_segment(&mut self, segment: &hir::PathSegment<'_>) {
         if segment.ident.name != kw::PathRoot {
             self.print_ident(segment.ident);
-            self.print_generic_args(segment.generic_args(), segment.infer_args, false);
+            self.print_generic_args(segment.args(), segment.infer_args, false);
         }
     }
 
@@ -1693,7 +1689,7 @@ impl<'a> State<'a> {
                     if segment.ident.name != kw::PathRoot {
                         self.print_ident(segment.ident);
                         self.print_generic_args(
-                            segment.generic_args(),
+                            segment.args(),
                             segment.infer_args,
                             colons_before_params,
                         );
@@ -1705,7 +1701,7 @@ impl<'a> State<'a> {
                 let item_segment = path.segments.last().unwrap();
                 self.print_ident(item_segment.ident);
                 self.print_generic_args(
-                    item_segment.generic_args(),
+                    item_segment.args(),
                     item_segment.infer_args,
                     colons_before_params,
                 )
@@ -1725,7 +1721,7 @@ impl<'a> State<'a> {
                 self.s.word("::");
                 self.print_ident(item_segment.ident);
                 self.print_generic_args(
-                    item_segment.generic_args(),
+                    item_segment.args(),
                     item_segment.infer_args,
                     colons_before_params,
                 )
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 6e381fd2965..e0b4eabf954 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -721,21 +721,25 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         &self.raw_proc_macros.unwrap()[pos]
     }
 
-    fn item_ident(&self, item_index: DefIndex, sess: &Session) -> Ident {
+    fn try_item_ident(&self, item_index: DefIndex, sess: &Session) -> Result<Ident, String> {
         let name = self
             .def_key(item_index)
             .disambiguated_data
             .data
             .get_opt_name()
-            .expect("no name in item_ident");
+            .ok_or_else(|| format!("Missing opt name for {:?}", item_index))?;
         let span = self
             .root
             .tables
             .ident_span
             .get(self, item_index)
-            .map(|data| data.decode((self, sess)))
-            .unwrap_or_else(|| panic!("Missing ident span for {:?} ({:?})", name, item_index));
-        Ident::new(name, span)
+            .ok_or_else(|| format!("Missing ident span for {:?} ({:?})", name, item_index))?
+            .decode((self, sess));
+        Ok(Ident::new(name, span))
+    }
+
+    fn item_ident(&self, item_index: DefIndex, sess: &Session) -> Ident {
+        self.try_item_ident(item_index, sess).unwrap()
     }
 
     fn def_kind(&self, index: DefIndex) -> DefKind {
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index b7f22885217..d01ef14e713 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -128,6 +128,9 @@ provide! { <'tcx> tcx, def_id, other, cdata,
     generator_kind => { cdata.generator_kind(def_id.index) }
     def_kind => { cdata.def_kind(def_id.index) }
     def_span => { cdata.get_span(def_id.index, &tcx.sess) }
+    def_ident_span => {
+        cdata.try_item_ident(def_id.index, &tcx.sess).ok().map(|ident| ident.span)
+    }
     lookup_stability => {
         cdata.get_stability(def_id.index).map(|s| tcx.intern_stability(s))
     }
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 1e836d0a842..ff84bbfe284 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -873,6 +873,7 @@ rustc_queries! {
         query def_kind(def_id: DefId) -> DefKind {
             desc { |tcx| "looking up definition kind of `{}`", tcx.def_path_str(def_id) }
         }
+
         query def_span(def_id: DefId) -> Span {
             desc { |tcx| "looking up span for `{}`", tcx.def_path_str(def_id) }
             // FIXME(mw): DefSpans are not really inputs since they are derived from
@@ -882,15 +883,23 @@ rustc_queries! {
             // regardless of HIR hashing.
             eval_always
         }
+
+        query def_ident_span(def_id: DefId) -> Option<Span> {
+            desc { |tcx| "looking up span for `{}`'s identifier", tcx.def_path_str(def_id) }
+        }
+
         query lookup_stability(def_id: DefId) -> Option<&'tcx attr::Stability> {
             desc { |tcx| "looking up stability of `{}`", tcx.def_path_str(def_id) }
         }
+
         query lookup_const_stability(def_id: DefId) -> Option<&'tcx attr::ConstStability> {
             desc { |tcx| "looking up const stability of `{}`", tcx.def_path_str(def_id) }
         }
+
         query lookup_deprecation_entry(def_id: DefId) -> Option<DeprecationEntry> {
             desc { |tcx| "checking whether `{}` is deprecated", tcx.def_path_str(def_id) }
         }
+
         query item_attrs(def_id: DefId) -> &'tcx [ast::Attribute] {
             desc { |tcx| "collecting attributes of `{}`", tcx.def_path_str(def_id) }
         }
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index fe20925b387..ebdf0dd1d29 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -846,7 +846,7 @@ fn foo(&self) -> Self::T { String::new() }
     }
 
     /// Given a slice of `hir::GenericBound`s, if any of them corresponds to the `trait_ref`
-    /// requirement, provide a strucuted suggestion to constrain it to a given type `ty`.
+    /// requirement, provide a structured suggestion to constrain it to a given type `ty`.
     fn constrain_generic_bound_associated_type_structured_suggestion(
         self,
         db: &mut DiagnosticBuilder<'_>,
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 59a3ac94634..15c12394c69 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -871,19 +871,37 @@ impl<'tcx> Generics {
         // We could cache this as a property of `GenericParamCount`, but
         // the aim is to refactor this away entirely eventually and the
         // presence of this method will be a constant reminder.
-        let mut own_counts: GenericParamCount = Default::default();
+        let mut own_counts = GenericParamCount::default();
 
         for param in &self.params {
             match param.kind {
                 GenericParamDefKind::Lifetime => own_counts.lifetimes += 1,
                 GenericParamDefKind::Type { .. } => own_counts.types += 1,
                 GenericParamDefKind::Const => own_counts.consts += 1,
-            };
+            }
         }
 
         own_counts
     }
 
+    pub fn own_defaults(&self) -> GenericParamCount {
+        let mut own_defaults = GenericParamCount::default();
+
+        for param in &self.params {
+            match param.kind {
+                GenericParamDefKind::Lifetime => (),
+                GenericParamDefKind::Type { has_default, .. } => {
+                    own_defaults.types += has_default as usize;
+                }
+                GenericParamDefKind::Const => {
+                    // FIXME(const_generics:defaults)
+                }
+            }
+        }
+
+        own_defaults
+    }
+
     pub fn requires_monomorphization(&self, tcx: TyCtxt<'tcx>) -> bool {
         if self.own_requires_monomorphization() {
             return true;
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 43dee391c17..dd36122f6a1 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -230,10 +230,11 @@ impl<'a> Parser<'a> {
                 } else {
                     // `(T, U) -> R`
                     let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?;
+                    let inputs_span = lo.to(self.prev_token.span);
                     let span = ident.span.to(self.prev_token.span);
                     let output =
                         self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
-                    ParenthesizedArgs { inputs, output, span }.into()
+                    ParenthesizedArgs { span, inputs, inputs_span, output }.into()
                 };
 
                 PathSegment { ident, args, id: ast::DUMMY_NODE_ID }
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs
index d5ba6f3b53b..c07efad8298 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_resolve/src/late/lifetimes.rs
@@ -1433,7 +1433,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                     hir::TyKind::Path(ref qpath) => {
                         if let QPath::Resolved(_, path) = qpath {
                             let last_segment = &path.segments[path.segments.len() - 1];
-                            let generics = last_segment.generic_args();
+                            let generics = last_segment.args();
                             for arg in generics.args.iter() {
                                 if let GenericArg::Lifetime(lt) = arg {
                                     if lt.name.ident() == name {
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 6635d44496c..f8144c3cf53 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -582,9 +582,9 @@ impl SourceMap {
     /// Extracts the source surrounding the given `Span` using the `extract_source` function. The
     /// extract function takes three arguments: a string slice containing the source, an index in
     /// the slice for the beginning of the span and an index in the slice for the end of the span.
-    fn span_to_source<F>(&self, sp: Span, extract_source: F) -> Result<String, SpanSnippetError>
+    fn span_to_source<F, T>(&self, sp: Span, extract_source: F) -> Result<T, SpanSnippetError>
     where
-        F: Fn(&str, usize, usize) -> Result<String, SpanSnippetError>,
+        F: Fn(&str, usize, usize) -> Result<T, SpanSnippetError>,
     {
         let local_begin = self.lookup_byte_offset(sp.lo());
         let local_end = self.lookup_byte_offset(sp.hi());
@@ -648,10 +648,10 @@ impl SourceMap {
 
     /// Extends the given `Span` to just after the previous occurrence of `c`. Return the same span
     /// if no character could be found or if an error occurred while retrieving the code snippet.
-    pub fn span_extend_to_prev_char(&self, sp: Span, c: char) -> Span {
+    pub fn span_extend_to_prev_char(&self, sp: Span, c: char, accept_newlines: bool) -> Span {
         if let Ok(prev_source) = self.span_to_prev_source(sp) {
-            let prev_source = prev_source.rsplit(c).next().unwrap_or("").trim_start();
-            if !prev_source.is_empty() && !prev_source.contains('\n') {
+            let prev_source = prev_source.rsplit(c).next().unwrap_or("");
+            if !prev_source.is_empty() && (!prev_source.contains('\n') || accept_newlines) {
                 return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32));
             }
         }
@@ -682,6 +682,25 @@ impl SourceMap {
         sp
     }
 
+    /// Returns the source snippet as `String` after the given `Span`.
+    pub fn span_to_next_source(&self, sp: Span) -> Result<String, SpanSnippetError> {
+        self.span_to_source(sp, |src, _, end_index| {
+            src.get(end_index..).map(|s| s.to_string()).ok_or(SpanSnippetError::IllFormedSpan(sp))
+        })
+    }
+
+    /// Extends the given `Span` to just after the next occurrence of `c`.
+    pub fn span_extend_to_next_char(&self, sp: Span, c: char, accept_newlines: bool) -> Span {
+        if let Ok(next_source) = self.span_to_next_source(sp) {
+            let next_source = next_source.split(c).next().unwrap_or("");
+            if !next_source.is_empty() && (!next_source.contains('\n') || accept_newlines) {
+                return sp.with_hi(BytePos(sp.hi().0 + next_source.len() as u32));
+            }
+        }
+
+        sp
+    }
+
     /// Given a `Span`, tries to get a shorter span ending before the first occurrence of `char`
     /// `c`.
     pub fn span_until_char(&self, sp: Span, c: char) -> Span {
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index aa1de6d51cb..a09e5d371bc 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -221,6 +221,10 @@ fn def_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span {
     tcx.hir().span_if_local(def_id).unwrap()
 }
 
+fn def_ident_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
+    tcx.hir().get_if_local(def_id).and_then(|node| node.ident()).map(|ident| ident.span)
+}
+
 /// If the given `DefId` describes an item belonging to a trait,
 /// returns the `DefId` of the trait that the trait item belongs to;
 /// otherwise, returns `None`.
@@ -491,6 +495,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
         associated_items,
         adt_sized_constraint,
         def_span,
+        def_ident_span,
         param_env,
         param_env_reveal_all_normalized,
         trait_of_item,
diff --git a/compiler/rustc_typeck/src/astconv/errors.rs b/compiler/rustc_typeck/src/astconv/errors.rs
index b04acd9660d..545c30169b9 100644
--- a/compiler/rustc_typeck/src/astconv/errors.rs
+++ b/compiler/rustc_typeck/src/astconv/errors.rs
@@ -96,7 +96,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let trait_def = self.tcx().trait_def(trait_def_id);
 
         if !self.tcx().features().unboxed_closures
-            && trait_segment.generic_args().parenthesized != trait_def.paren_sugar
+            && trait_segment.args().parenthesized != trait_def.paren_sugar
         {
             let sess = &self.tcx().sess.parse_sess;
             // For now, require that parenthetical notation be used only with `Fn()` etc.
@@ -126,7 +126,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             })
                             .unwrap_or_else(|| "()".to_string()),
                         trait_segment
-                            .generic_args()
+                            .args()
                             .bindings
                             .iter()
                             .find_map(|b| match (b.ident.name == sym::Output, &b.kind) {
diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs
index 1100401ed12..0797c956362 100644
--- a/compiler/rustc_typeck/src/astconv/generics.rs
+++ b/compiler/rustc_typeck/src/astconv/generics.rs
@@ -1,10 +1,12 @@
+use super::IsMethodCall;
 use crate::astconv::{
     AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
     GenericArgCountResult, GenericArgPosition,
 };
 use crate::errors::AssocTypeBindingNotAllowed;
+use crate::structured_errors::{StructuredDiagnostic, WrongNumberOfGenericArgs};
 use rustc_ast::ast::ParamKindOrd;
-use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorReported};
+use rustc_errors::{struct_span_err, Applicability, ErrorReported};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::GenericArg;
@@ -13,7 +15,6 @@ use rustc_middle::ty::{
 };
 use rustc_session::lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS;
 use rustc_span::{symbol::kw, MultiSpan, Span};
-
 use smallvec::SmallVec;
 
 impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
@@ -353,20 +354,25 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     pub fn check_generic_arg_count_for_call(
         tcx: TyCtxt<'_>,
         span: Span,
-        def: &ty::Generics,
+        def_id: DefId,
+        generics: &ty::Generics,
         seg: &hir::PathSegment<'_>,
-        is_method_call: bool,
+        is_method_call: IsMethodCall,
     ) -> GenericArgCountResult {
         let empty_args = hir::GenericArgs::none();
-        let suppress_mismatch = Self::check_impl_trait(tcx, seg, &def);
+        let suppress_mismatch = Self::check_impl_trait(tcx, seg, &generics);
+
+        let gen_args = seg.args.unwrap_or(&empty_args);
+        let gen_pos = if is_method_call == IsMethodCall::Yes {
+            GenericArgPosition::MethodCall
+        } else {
+            GenericArgPosition::Value
+        };
+        let has_self = generics.parent.is_none() && generics.has_self;
+        let infer_args = seg.infer_args || suppress_mismatch;
+
         Self::check_generic_arg_count(
-            tcx,
-            span,
-            def,
-            if let Some(ref args) = seg.args { args } else { &empty_args },
-            if is_method_call { GenericArgPosition::MethodCall } else { GenericArgPosition::Value },
-            def.parent.is_none() && def.has_self, // `has_self`
-            seg.infer_args || suppress_mismatch,  // `infer_args`
+            tcx, span, def_id, seg, generics, gen_args, gen_pos, has_self, infer_args,
         )
     }
 
@@ -375,156 +381,109 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     pub(crate) fn check_generic_arg_count(
         tcx: TyCtxt<'_>,
         span: Span,
-        def: &ty::Generics,
-        args: &hir::GenericArgs<'_>,
-        position: GenericArgPosition,
+        def_id: DefId,
+        seg: &hir::PathSegment<'_>,
+        gen_params: &ty::Generics,
+        gen_args: &hir::GenericArgs<'_>,
+        gen_pos: GenericArgPosition,
         has_self: bool,
         infer_args: bool,
     ) -> GenericArgCountResult {
-        // At this stage we are guaranteed that the generic arguments are in the correct order, e.g.
-        // that lifetimes will proceed types. So it suffices to check the number of each generic
-        // arguments in order to validate them with respect to the generic parameters.
-        let param_counts = def.own_counts();
+        let default_counts = gen_params.own_defaults();
+        let param_counts = gen_params.own_counts();
         let named_type_param_count = param_counts.types - has_self as usize;
-        let arg_counts = args.own_counts();
-        let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0;
+        let arg_counts = gen_args.own_counts();
+        let infer_lifetimes = gen_pos != GenericArgPosition::Type && arg_counts.lifetimes == 0;
 
-        let mut defaults: ty::GenericParamCount = Default::default();
-        for param in &def.params {
-            match param.kind {
-                GenericParamDefKind::Lifetime => {}
-                GenericParamDefKind::Type { has_default, .. } => {
-                    defaults.types += has_default as usize
-                }
-                GenericParamDefKind::Const => {
-                    // FIXME(const_generics_defaults)
-                }
-            };
-        }
-
-        if position != GenericArgPosition::Type && !args.bindings.is_empty() {
-            AstConv::prohibit_assoc_ty_binding(tcx, args.bindings[0].span);
+        if gen_pos != GenericArgPosition::Type && !gen_args.bindings.is_empty() {
+            Self::prohibit_assoc_ty_binding(tcx, gen_args.bindings[0].span);
         }
 
         let explicit_late_bound =
-            Self::prohibit_explicit_late_bound_lifetimes(tcx, def, args, position);
-
-        let check_kind_count = |kind,
-                                required,
-                                permitted,
-                                provided,
-                                offset,
-                                unexpected_spans: &mut Vec<Span>,
-                                silent| {
-            debug!(
-                "check_kind_count: kind: {} required: {} permitted: {} provided: {} offset: {}",
-                kind, required, permitted, provided, offset
-            );
-            // We enforce the following: `required` <= `provided` <= `permitted`.
-            // For kinds without defaults (e.g.., lifetimes), `required == permitted`.
-            // For other kinds (i.e., types), `permitted` may be greater than `required`.
-            if required <= provided && provided <= permitted {
-                return true;
-            }
+            Self::prohibit_explicit_late_bound_lifetimes(tcx, gen_params, gen_args, gen_pos);
 
-            if silent {
-                return false;
-            }
+        let mut invalid_args = vec![];
 
-            // Unfortunately lifetime and type parameter mismatches are typically styled
-            // differently in diagnostics, which means we have a few cases to consider here.
-            let (bound, quantifier) = if required != permitted {
-                if provided < required {
-                    (required, "at least ")
-                } else {
-                    // provided > permitted
-                    (permitted, "at most ")
+        let mut check_generics =
+            |kind, expected_min, expected_max, provided, params_offset, args_offset, silent| {
+                if (expected_min..=expected_max).contains(&provided) {
+                    return true;
                 }
-            } else {
-                (required, "")
-            };
 
-            let (spans, labels) = if provided > permitted {
-                // In the case when the user has provided too many arguments,
-                // we want to point to the unexpected arguments.
-                let (spans, labels): (Vec<Span>, Vec<String>) = args.args
-                    [offset + permitted..offset + provided]
-                    .iter()
-                    .map(|arg| (arg.span(), format!("unexpected {} argument", arg.short_descr())))
-                    .unzip();
-                unexpected_spans.extend(spans.clone());
-                (spans, labels)
-            } else {
-                (
-                    vec![span],
-                    vec![format!(
-                        "expected {}{} {} argument{}",
-                        quantifier,
-                        bound,
-                        kind,
-                        pluralize!(bound),
-                    )],
-                )
-            };
+                if silent {
+                    return false;
+                }
 
-            let mut err = tcx.sess.struct_span_err_with_code(
-                spans.clone(),
-                &format!(
-                    "wrong number of {} arguments: expected {}{}, found {}",
-                    kind, quantifier, bound, provided,
-                ),
-                DiagnosticId::Error("E0107".into()),
-            );
-            for (span, label) in spans.into_iter().zip(labels) {
-                err.span_label(span, label.as_str());
-            }
-            err.emit();
-            false
-        };
+                if provided > expected_max {
+                    invalid_args.extend(
+                        gen_args.args[args_offset + expected_max..args_offset + provided]
+                            .iter()
+                            .map(|arg| arg.span()),
+                    );
+                };
+
+                WrongNumberOfGenericArgs {
+                    tcx,
+                    kind,
+                    expected_min,
+                    expected_max,
+                    provided,
+                    params_offset,
+                    args_offset,
+                    path_segment: seg,
+                    gen_params,
+                    gen_args,
+                    def_id,
+                    span,
+                }
+                .diagnostic()
+                .emit();
 
-        let mut unexpected_spans = vec![];
+                false
+            };
 
-        let lifetime_count_correct = check_kind_count(
+        let lifetimes_correct = check_generics(
             "lifetime",
             if infer_lifetimes { 0 } else { param_counts.lifetimes },
             param_counts.lifetimes,
             arg_counts.lifetimes,
+            has_self as usize,
             0,
-            &mut unexpected_spans,
             explicit_late_bound == ExplicitLateBound::Yes,
         );
 
-        let kind_str = if param_counts.consts + arg_counts.consts == 0 {
-            "type"
-        } else if named_type_param_count + arg_counts.types == 0 {
-            "const"
-        } else {
-            "generic"
-        };
+        let args_correct = {
+            let kind = if param_counts.consts + arg_counts.consts == 0 {
+                "type"
+            } else if named_type_param_count + arg_counts.types == 0 {
+                "const"
+            } else {
+                "generic"
+            };
 
-        let arg_count_correct = check_kind_count(
-            kind_str,
-            if infer_args {
+            let expected_min = if infer_args {
                 0
             } else {
-                param_counts.consts + named_type_param_count - defaults.types
-            },
-            param_counts.consts + named_type_param_count,
-            arg_counts.consts + arg_counts.types,
-            arg_counts.lifetimes,
-            &mut unexpected_spans,
-            false,
-        );
+                param_counts.consts + named_type_param_count - default_counts.types
+            };
+
+            check_generics(
+                kind,
+                expected_min,
+                param_counts.consts + named_type_param_count,
+                arg_counts.consts + arg_counts.types,
+                param_counts.lifetimes + has_self as usize,
+                arg_counts.lifetimes,
+                false,
+            )
+        };
 
         GenericArgCountResult {
             explicit_late_bound,
-            correct: if lifetime_count_correct && arg_count_correct {
+            correct: if lifetimes_correct && args_correct {
                 Ok(())
             } else {
-                Err(GenericArgCountMismatch {
-                    reported: Some(ErrorReported),
-                    invalid_args: unexpected_spans,
-                })
+                Err(GenericArgCountMismatch { reported: Some(ErrorReported), invalid_args })
             },
         }
     }
@@ -549,7 +508,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         if explicit && impl_trait {
             let spans = seg
-                .generic_args()
+                .args()
                 .args
                 .iter()
                 .filter_map(|arg| match arg {
@@ -594,12 +553,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0;
 
         if infer_lifetimes {
-            ExplicitLateBound::No
-        } else if let Some(span_late) = def.has_late_bound_regions {
+            return ExplicitLateBound::No;
+        }
+
+        if let Some(span_late) = def.has_late_bound_regions {
             let msg = "cannot specify lifetime arguments explicitly \
                        if late bound lifetime parameters are present";
             let note = "the late bound lifetime parameter is introduced here";
             let span = args.args[0].span();
+
             if position == GenericArgPosition::Value
                 && arg_counts.lifetimes != param_counts.lifetimes
             {
@@ -616,6 +578,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     |lint| lint.build(msg).emit(),
                 );
             }
+
             ExplicitLateBound::Yes
         } else {
             ExplicitLateBound::No
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 878993d512c..d0e99ffd2f5 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -138,6 +138,12 @@ pub enum ExplicitLateBound {
     No,
 }
 
+#[derive(Copy, Clone, PartialEq)]
+pub enum IsMethodCall {
+    Yes,
+    No,
+}
+
 /// Denotes the "position" of a generic argument, indicating if it is a generic type,
 /// generic function or generic method call.
 #[derive(Copy, Clone, PartialEq)]
@@ -252,7 +258,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             span,
             def_id,
             &[],
-            item_segment.generic_args(),
+            item_segment,
+            item_segment.args(),
             item_segment.infer_args,
             None,
         );
@@ -300,6 +307,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         span: Span,
         def_id: DefId,
         parent_substs: &[subst::GenericArg<'tcx>],
+        seg: &hir::PathSegment<'_>,
         generic_args: &'a hir::GenericArgs<'_>,
         infer_args: bool,
         self_ty: Option<Ty<'tcx>>,
@@ -314,10 +322,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         );
 
         let tcx = self.tcx();
-        let generic_params = tcx.generics_of(def_id);
+        let generics = tcx.generics_of(def_id);
 
-        if generic_params.has_self {
-            if generic_params.parent.is_some() {
+        if generics.has_self {
+            if generics.parent.is_some() {
                 // The parent is a trait so it should have at least one subst
                 // for the `Self` type.
                 assert!(!parent_substs.is_empty())
@@ -332,7 +340,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let arg_count = Self::check_generic_arg_count(
             tcx,
             span,
-            &generic_params,
+            def_id,
+            seg,
+            &generics,
             &generic_args,
             GenericArgPosition::Type,
             self_ty.is_some(),
@@ -343,7 +353,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         // Traits always have `Self` as a generic parameter, which means they will not return early
         // here and so associated type bindings will be handled regardless of whether there are any
         // non-`Self` generic parameters.
-        if generic_params.params.len() == 0 {
+        if generics.params.len() == 0 {
             return (tcx.intern_substs(&[]), vec![], arg_count);
         }
 
@@ -553,7 +563,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         debug!(
             "create_substs_for_ast_path(generic_params={:?}, self_ty={:?}) -> {:?}",
-            generic_params, self_ty, substs
+            generics, self_ty, substs
         );
 
         (substs, assoc_bindings, arg_count)
@@ -576,7 +586,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 span,
                 item_def_id,
                 parent_substs,
-                item_segment.generic_args(),
+                item_segment,
+                item_segment.args(),
                 item_segment.infer_args,
                 None,
             )
@@ -701,8 +712,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     ) {
         let trait_def_id = self.tcx().require_lang_item(lang_item, Some(span));
 
-        let (substs, assoc_bindings, _) =
-            self.create_substs_for_ast_path(span, trait_def_id, &[], args, false, Some(self_ty));
+        let (substs, assoc_bindings, _) = self.create_substs_for_ast_path(
+            span,
+            trait_def_id,
+            &[],
+            &hir::PathSegment::invalid(),
+            args,
+            false,
+            Some(self_ty),
+        );
         let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs));
         bounds.trait_bounds.push((poly_trait_ref, span, Constness::NotConst));
 
@@ -750,7 +768,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             span,
             trait_def_id,
             &[],
-            trait_segment.generic_args(),
+            trait_segment,
+            trait_segment.args(),
             trait_segment.infer_args,
             Some(self_ty),
         )
@@ -1076,7 +1095,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 dummy_self,
                 &mut bounds,
             ) {
-                potential_assoc_types.extend(cur_potential_assoc_types.into_iter());
+                potential_assoc_types.extend(cur_potential_assoc_types);
             }
         }
 
@@ -1753,7 +1772,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         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.generic_args().args {
+            for arg in segment.args().args {
                 let (span, kind) = match arg {
                     hir::GenericArg::Lifetime(lt) => {
                         if err_for_lt {
@@ -1795,7 +1814,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
 
             // Only emit the first error to avoid overloading the user with error messages.
-            if let [binding, ..] = segment.generic_args().bindings {
+            if let [binding, ..] = segment.args().bindings {
                 has_err = true;
                 Self::prohibit_assoc_ty_binding(self.tcx(), binding.span);
             }
@@ -2132,6 +2151,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     span,
                     def_id,
                     &[],
+                    &hir::PathSegment::invalid(),
                     &GenericArgs::none(),
                     true,
                     None,
diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs
index 36240a9b41e..39dac0a909f 100644
--- a/compiler/rustc_typeck/src/check/cast.rs
+++ b/compiler/rustc_typeck/src/check/cast.rs
@@ -418,13 +418,14 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                 err.emit();
             }
             CastError::SizedUnsizedCast => {
-                use crate::structured_errors::{SizedUnsizedCastError, StructuredDiagnostic};
-                SizedUnsizedCastError::new(
-                    &fcx.tcx.sess,
-                    self.span,
-                    self.expr_ty,
-                    fcx.ty_to_string(self.cast_ty),
-                )
+                use crate::structured_errors::{SizedUnsizedCast, StructuredDiagnostic};
+
+                SizedUnsizedCast {
+                    sess: &fcx.tcx.sess,
+                    span: self.span,
+                    expr_ty: self.expr_ty,
+                    cast_ty: fcx.ty_to_string(self.cast_ty),
+                }
                 .diagnostic()
                 .emit();
             }
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
index 7126b624059..c3166ce8164 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
@@ -1,6 +1,6 @@
 use crate::astconv::{
     AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
-    GenericArgCountResult, PathSeg,
+    GenericArgCountResult, IsMethodCall, PathSeg,
 };
 use crate::check::callee::{self, DeferredCallResolution};
 use crate::check::method::{self, MethodCallee, SelfSource};
@@ -1219,18 +1219,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // a problem.
 
         let mut infer_args_for_err = FxHashSet::default();
+
         for &PathSeg(def_id, index) in &path_segs {
             let seg = &segments[index];
             let generics = tcx.generics_of(def_id);
+
             // Argument-position `impl Trait` is treated as a normal generic
             // parameter internally, but we don't allow users to specify the
             // parameter's value explicitly, so we have to do some error-
             // checking here.
             if let GenericArgCountResult {
-                correct: Err(GenericArgCountMismatch { reported: Some(ErrorReported), .. }),
+                correct: Err(GenericArgCountMismatch { reported: Some(_), .. }),
                 ..
             } = AstConv::check_generic_arg_count_for_call(
-                tcx, span, &generics, &seg, false, // `is_method_call`
+                tcx,
+                span,
+                def_id,
+                &generics,
+                seg,
+                IsMethodCall::No,
             ) {
                 infer_args_for_err.insert(index);
                 self.set_tainted_by_errors(); // See issue #53251.
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
index 3e60924d6fc..94f8bfa3fc0 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -22,6 +22,7 @@ use rustc_span::symbol::{sym, Ident};
 use rustc_span::{self, MultiSpan, Span};
 use rustc_trait_selection::traits::{self, ObligationCauseCode, StatementAsExpression};
 
+use crate::structured_errors::StructuredDiagnostic;
 use std::mem::replace;
 use std::slice;
 
@@ -173,18 +174,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
 
             if let Some(def_id) = def_id {
-                if let Some(node) = tcx.hir().get_if_local(def_id) {
-                    let mut spans: MultiSpan = node
-                        .ident()
-                        .map(|ident| ident.span)
-                        .unwrap_or_else(|| tcx.hir().span(node.hir_id().unwrap()))
-                        .into();
-
-                    if let Some(id) = node.body_id() {
-                        let body = tcx.hir().body(id);
-                        for param in body.params {
-                            spans.push_span_label(param.span, String::new());
-                        }
+                if let Some(def_span) = tcx.def_ident_span(def_id) {
+                    let mut spans: MultiSpan = def_span.into();
+
+                    let params = tcx
+                        .hir()
+                        .get_if_local(def_id)
+                        .and_then(|node| node.body_id())
+                        .into_iter()
+                        .map(|id| tcx.hir().body(id).params)
+                        .flatten();
+
+                    for param in params {
+                        spans.push_span_label(param.span, String::new());
                     }
 
                     let def_kind = tcx.def_kind(def_id);
@@ -358,9 +360,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // We also need to make sure we at least write the ty of the other
         // arguments which we skipped above.
         if c_variadic {
-            fn variadic_error<'tcx>(s: &Session, span: Span, t: Ty<'tcx>, cast_ty: &str) {
-                use crate::structured_errors::{StructuredDiagnostic, VariadicError};
-                VariadicError::new(s, span, t, cast_ty).diagnostic().emit();
+            fn variadic_error<'tcx>(sess: &Session, span: Span, ty: Ty<'tcx>, cast_ty: &str) {
+                use crate::structured_errors::MissingCastForVariadicArg;
+
+                MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit()
             }
 
             for arg in args.iter().skip(expected_arg_count) {
diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs
index 8ef723d5902..e604419f413 100644
--- a/compiler/rustc_typeck/src/check/method/confirm.rs
+++ b/compiler/rustc_typeck/src/check/method/confirm.rs
@@ -1,6 +1,6 @@
 use super::{probe, MethodCallee};
 
-use crate::astconv::{AstConv, CreateSubstsForGenericArgsCtxt};
+use crate::astconv::{AstConv, CreateSubstsForGenericArgsCtxt, IsMethodCall};
 use crate::check::{callee, FnCtxt};
 use crate::hir::def_id::DefId;
 use crate::hir::GenericArg;
@@ -298,8 +298,14 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         // If they were not explicitly supplied, just construct fresh
         // variables.
         let generics = self.tcx.generics_of(pick.item.def_id);
+
         let arg_count_correct = AstConv::check_generic_arg_count_for_call(
-            self.tcx, self.span, &generics, &seg, true, // `is_method_call`
+            self.tcx,
+            self.span,
+            pick.item.def_id,
+            &generics,
+            seg,
+            IsMethodCall::Yes,
         );
 
         // Create subst for early-bound lifetime parameters, combining
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index ae97fa3f7e4..1ec05e1cb1f 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -1497,13 +1497,11 @@ fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool {
         Ptr(mut_ty) | Rptr(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty),
         OpaqueDef(_, generic_args) => are_suggestable_generic_args(generic_args),
         Path(hir::QPath::TypeRelative(ty, segment)) => {
-            is_suggestable_infer_ty(ty) || are_suggestable_generic_args(segment.generic_args().args)
+            is_suggestable_infer_ty(ty) || are_suggestable_generic_args(segment.args().args)
         }
         Path(hir::QPath::Resolved(ty_opt, hir::Path { segments, .. })) => {
             ty_opt.map_or(false, is_suggestable_infer_ty)
-                || segments
-                    .iter()
-                    .any(|segment| are_suggestable_generic_args(segment.generic_args().args))
+                || segments.iter().any(|segment| are_suggestable_generic_args(segment.args().args))
         }
         _ => false,
     }
diff --git a/compiler/rustc_typeck/src/structured_errors.rs b/compiler/rustc_typeck/src/structured_errors.rs
index 83125a3e2fe..04d04304e70 100644
--- a/compiler/rustc_typeck/src/structured_errors.rs
+++ b/compiler/rustc_typeck/src/structured_errors.rs
@@ -1,149 +1,36 @@
-use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId};
-use rustc_middle::ty::{Ty, TypeFoldable};
+mod missing_cast_for_variadic_arg;
+mod sized_unsized_cast;
+mod wrong_number_of_generic_args;
+
+pub use self::{
+    missing_cast_for_variadic_arg::*, sized_unsized_cast::*, wrong_number_of_generic_args::*,
+};
+
+use rustc_errors::{DiagnosticBuilder, DiagnosticId};
 use rustc_session::Session;
-use rustc_span::Span;
 
 pub trait StructuredDiagnostic<'tcx> {
     fn session(&self) -> &Session;
 
     fn code(&self) -> DiagnosticId;
 
-    fn common(&self) -> DiagnosticBuilder<'tcx>;
-
     fn diagnostic(&self) -> DiagnosticBuilder<'tcx> {
-        let err = self.common();
-        if self.session().teach(&self.code()) { self.extended(err) } else { self.regular(err) }
-    }
-
-    fn regular(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
-        err
-    }
-
-    fn extended(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
-        err
-    }
-}
-
-pub struct VariadicError<'tcx> {
-    sess: &'tcx Session,
-    span: Span,
-    t: Ty<'tcx>,
-    cast_ty: &'tcx str,
-}
-
-impl<'tcx> VariadicError<'tcx> {
-    pub fn new(
-        sess: &'tcx Session,
-        span: Span,
-        t: Ty<'tcx>,
-        cast_ty: &'tcx str,
-    ) -> VariadicError<'tcx> {
-        VariadicError { sess, span, t, cast_ty }
-    }
-}
-
-impl<'tcx> StructuredDiagnostic<'tcx> for VariadicError<'tcx> {
-    fn session(&self) -> &Session {
-        self.sess
-    }
-
-    fn code(&self) -> DiagnosticId {
-        rustc_errors::error_code!(E0617)
-    }
+        let err = self.diagnostic_common();
 
-    fn common(&self) -> DiagnosticBuilder<'tcx> {
-        let mut err = if self.t.references_error() {
-            self.sess.diagnostic().struct_dummy()
+        if self.session().teach(&self.code()) {
+            self.diagnostic_extended(err)
         } else {
-            self.sess.struct_span_fatal_with_code(
-                self.span,
-                &format!("can't pass `{}` to variadic function", self.t),
-                self.code(),
-            )
-        };
-        if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.span) {
-            err.span_suggestion(
-                self.span,
-                &format!("cast the value to `{}`", self.cast_ty),
-                format!("{} as {}", snippet, self.cast_ty),
-                Applicability::MachineApplicable,
-            );
-        } else {
-            err.help(&format!("cast the value to `{}`", self.cast_ty));
+            self.diagnostic_regular(err)
         }
-        err
-    }
-
-    fn extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
-        err.note(&format!(
-            "certain types, like `{}`, must be cast before passing them to a \
-                           variadic function, because of arcane ABI rules dictated by the C \
-                           standard",
-            self.t
-        ));
-        err
-    }
-}
-
-pub struct SizedUnsizedCastError<'tcx> {
-    sess: &'tcx Session,
-    span: Span,
-    expr_ty: Ty<'tcx>,
-    cast_ty: String,
-}
-
-impl<'tcx> SizedUnsizedCastError<'tcx> {
-    pub fn new(
-        sess: &'tcx Session,
-        span: Span,
-        expr_ty: Ty<'tcx>,
-        cast_ty: String,
-    ) -> SizedUnsizedCastError<'tcx> {
-        SizedUnsizedCastError { sess, span, expr_ty, cast_ty }
     }
-}
 
-impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCastError<'tcx> {
-    fn session(&self) -> &Session {
-        self.sess
-    }
+    fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx>;
 
-    fn code(&self) -> DiagnosticId {
-        rustc_errors::error_code!(E0607)
-    }
-
-    fn common(&self) -> DiagnosticBuilder<'tcx> {
-        if self.expr_ty.references_error() {
-            self.sess.diagnostic().struct_dummy()
-        } else {
-            self.sess.struct_span_fatal_with_code(
-                self.span,
-                &format!(
-                    "cannot cast thin pointer `{}` to fat pointer `{}`",
-                    self.expr_ty, self.cast_ty
-                ),
-                self.code(),
-            )
-        }
+    fn diagnostic_regular(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
+        err
     }
 
-    fn extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
-        err.help(
-            "Thin pointers are \"simple\" pointers: they are purely a reference to a
-memory address.
-
-Fat pointers are pointers referencing \"Dynamically Sized Types\" (also
-called DST). DST don't have a statically known size, therefore they can
-only exist behind some kind of pointers that contain additional
-information. Slices and trait objects are DSTs. In the case of slices,
-the additional information the fat pointer holds is their size.
-
-To fix this error, don't try to cast directly between thin and fat
-pointers.
-
-For more information about casts, take a look at The Book:
-https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions",
-        );
+    fn diagnostic_extended(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
         err
     }
 }
diff --git a/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs b/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs
new file mode 100644
index 00000000000..674b0e463f5
--- /dev/null
+++ b/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs
@@ -0,0 +1,58 @@
+use crate::structured_errors::StructuredDiagnostic;
+use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId};
+use rustc_middle::ty::{Ty, TypeFoldable};
+use rustc_session::Session;
+use rustc_span::Span;
+
+pub struct MissingCastForVariadicArg<'tcx> {
+    pub sess: &'tcx Session,
+    pub span: Span,
+    pub ty: Ty<'tcx>,
+    pub cast_ty: &'tcx str,
+}
+
+impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx> {
+    fn session(&self) -> &Session {
+        self.sess
+    }
+
+    fn code(&self) -> DiagnosticId {
+        rustc_errors::error_code!(E0617)
+    }
+
+    fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> {
+        let mut err = if self.ty.references_error() {
+            self.sess.diagnostic().struct_dummy()
+        } else {
+            self.sess.struct_span_fatal_with_code(
+                self.span,
+                &format!("can't pass `{}` to variadic function", self.ty),
+                self.code(),
+            )
+        };
+
+        if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.span) {
+            err.span_suggestion(
+                self.span,
+                &format!("cast the value to `{}`", self.cast_ty),
+                format!("{} as {}", snippet, self.cast_ty),
+                Applicability::MachineApplicable,
+            );
+        } else {
+            err.help(&format!("cast the value to `{}`", self.cast_ty));
+        }
+
+        err
+    }
+
+    fn diagnostic_extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
+        err.note(&format!(
+            "certain types, like `{}`, must be casted before passing them to a \
+                variadic function, because of arcane ABI rules dictated by the C \
+                standard",
+            self.ty
+        ));
+
+        err
+    }
+}
diff --git a/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs b/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs
new file mode 100644
index 00000000000..d0477a3e748
--- /dev/null
+++ b/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs
@@ -0,0 +1,57 @@
+use crate::structured_errors::StructuredDiagnostic;
+use rustc_errors::{DiagnosticBuilder, DiagnosticId};
+use rustc_middle::ty::{Ty, TypeFoldable};
+use rustc_session::Session;
+use rustc_span::Span;
+
+pub struct SizedUnsizedCast<'tcx> {
+    pub sess: &'tcx Session,
+    pub span: Span,
+    pub expr_ty: Ty<'tcx>,
+    pub cast_ty: String,
+}
+
+impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> {
+    fn session(&self) -> &Session {
+        self.sess
+    }
+
+    fn code(&self) -> DiagnosticId {
+        rustc_errors::error_code!(E0607)
+    }
+
+    fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> {
+        if self.expr_ty.references_error() {
+            self.sess.diagnostic().struct_dummy()
+        } else {
+            self.sess.struct_span_fatal_with_code(
+                self.span,
+                &format!(
+                    "cannot cast thin pointer `{}` to fat pointer `{}`",
+                    self.expr_ty, self.cast_ty
+                ),
+                self.code(),
+            )
+        }
+    }
+
+    fn diagnostic_extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
+        err.help(
+            "Thin pointers are \"simple\" pointers: they are purely a reference to a
+memory address.
+
+Fat pointers are pointers referencing \"Dynamically Sized Types\" (also
+called DST). DST don't have a statically known size, therefore they can
+only exist behind some kind of pointers that contain additional
+information. Slices and trait objects are DSTs. In the case of slices,
+the additional information the fat pointer holds is their size.
+
+To fix this error, don't try to cast directly between thin and fat
+pointers.
+
+For more information about casts, take a look at The Book:
+https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions",
+        );
+        err
+    }
+}
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
new file mode 100644
index 00000000000..e35c1557466
--- /dev/null
+++ b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
@@ -0,0 +1,393 @@
+use crate::structured_errors::StructuredDiagnostic;
+use hir::def::DefKind;
+use rustc_errors::{pluralize, Applicability, DiagnosticBuilder, DiagnosticId};
+use rustc_hir as hir;
+use rustc_middle::ty::{self as ty, TyCtxt};
+use rustc_session::Session;
+use rustc_span::Span;
+use rustc_span::{def_id::DefId, MultiSpan};
+
+/// Handles the `wrong number of type / lifetime / ... arguments` family of error messages.
+pub struct WrongNumberOfGenericArgs<'a, 'tcx> {
+    crate tcx: TyCtxt<'tcx>,
+
+    /// "type", "lifetime" etc., put verbatim into the message
+    crate kind: &'static str,
+
+    /// Minimum number of expected generic arguments (e.g. `2` for `HashMap`)
+    crate expected_min: usize,
+
+    /// Maximum number of expected generic arguments (e.g. `3` for `HashMap`)
+    crate expected_max: usize,
+
+    /// Number of generic arguments provided by the user
+    crate provided: usize,
+
+    /// Offset into `gen_params` - depends on the `kind`; might be different than `args_offset` when
+    /// user passed e.g. more arguments than was actually expected
+    crate params_offset: usize,
+
+    /// Offset into `gen_args` - depends on the `kind`
+    crate args_offset: usize,
+
+    /// Offending path segment
+    crate path_segment: &'a hir::PathSegment<'a>,
+
+    /// Generic parameters as expected by type or trait
+    crate gen_params: &'a ty::Generics,
+
+    /// Generic arguments as provided by user
+    crate gen_args: &'a hir::GenericArgs<'a>,
+
+    /// DefId of the generic type
+    crate def_id: DefId,
+
+    /// Offending place where the generic type has been misused
+    crate span: Span,
+}
+
+impl<'tcx> WrongNumberOfGenericArgs<'_, 'tcx> {
+    fn quantifier_and_bound(&self) -> (&'static str, usize) {
+        if self.expected_min == self.expected_max {
+            ("", self.expected_min)
+        } else if self.provided < self.expected_min {
+            ("at least ", self.expected_min)
+        } else {
+            ("at most ", self.expected_max)
+        }
+    }
+
+    fn start_diagnostics(&self) -> DiagnosticBuilder<'tcx> {
+        let span = self.path_segment.ident.span;
+
+        let msg = {
+            let def_path = self.tcx.def_path_str(self.def_id);
+            let def_kind = self.tcx.def_kind(self.def_id).descr(self.def_id);
+            let (quantifier, bound) = self.quantifier_and_bound();
+
+            if self.gen_args.span().is_some() {
+                format!(
+                    "this {} takes {}{} {} argument{} but {}{} {} argument{} {} supplied",
+                    def_kind,
+                    quantifier,
+                    bound,
+                    self.kind,
+                    pluralize!(bound),
+                    if self.provided > 0 && self.provided < self.expected_min {
+                        "only "
+                    } else {
+                        ""
+                    },
+                    self.provided,
+                    self.kind,
+                    pluralize!(self.provided),
+                    if self.provided == 1 { "was" } else { "were" },
+                )
+            } else {
+                format!("missing generics for {} `{}`", def_kind, def_path)
+            }
+        };
+
+        self.tcx.sess.struct_span_err_with_code(span, &msg, self.code())
+    }
+
+    /// Builds the `expected 1 type argument / supplied 2 type arguments` message.
+    fn notify(&self, err: &mut DiagnosticBuilder<'_>) {
+        let (quantifier, bound) = self.quantifier_and_bound();
+
+        err.span_label(
+            self.path_segment.ident.span,
+            format!(
+                "expected {}{} {} argument{}",
+                quantifier,
+                bound,
+                self.kind,
+                pluralize!(bound),
+            ),
+        );
+
+        // When user's provided too many arguments, we don't highlight each of them, because it
+        // would overlap with the suggestion to remove them:
+        //
+        // ```
+        // type Foo = Bar<usize, usize>;
+        //                -----  ----- supplied 2 type arguments
+        //                     ^^^^^^^ remove this type argument
+        // ```
+        if self.provided > self.expected_max {
+            return;
+        }
+
+        let args = self.gen_args.args.iter().skip(self.args_offset).take(self.provided).enumerate();
+
+        for (i, arg) in args {
+            err.span_label(
+                arg.span(),
+                if i + 1 == self.provided {
+                    format!(
+                        "supplied {} {} argument{}",
+                        self.provided,
+                        self.kind,
+                        pluralize!(self.provided)
+                    )
+                } else {
+                    String::new()
+                },
+            );
+        }
+    }
+
+    fn suggest(&self, err: &mut DiagnosticBuilder<'_>) {
+        if self.provided == 0 {
+            if self.gen_args.span().is_some() {
+                self.suggest_adding_args(err);
+            } else {
+                self.suggest_creating_generics(err);
+            }
+        } else if self.provided < self.expected_min {
+            self.suggest_adding_args(err);
+        } else {
+            self.suggest_removing_args_or_generics(err);
+        }
+    }
+
+    /// Suggests to create generics (`<...>`) when current invocation site contains no generics at
+    /// all:
+    ///
+    /// ```text
+    /// type Map = HashMap;
+    /// ```
+    fn suggest_creating_generics(&self, err: &mut DiagnosticBuilder<'_>) {
+        let params = self
+            .gen_params
+            .params
+            .iter()
+            .skip(self.params_offset)
+            .take(self.expected_min)
+            .map(|param| param.name.to_string())
+            .collect::<Vec<_>>()
+            .join(", ");
+
+        let def_kind = self.tcx.def_kind(self.def_id);
+
+        let sugg = if matches!(def_kind, DefKind::Fn | DefKind::AssocFn) {
+            format!("::<{}>", params)
+        } else {
+            format!("<{}>", params)
+        };
+
+        let msg = format!(
+            "use angle brackets to add missing {} argument{}",
+            self.kind,
+            pluralize!(self.expected_min),
+        );
+
+        err.span_suggestion_verbose(
+            self.path_segment.ident.span.shrink_to_hi(),
+            &msg,
+            sugg,
+            Applicability::HasPlaceholders,
+        );
+    }
+
+    /// Suggests to add missing argument(s) when current invocation site already contains some
+    /// generics:
+    ///
+    /// ```text
+    /// type Map = HashMap<String>;
+    /// ```
+    fn suggest_adding_args(&self, err: &mut DiagnosticBuilder<'_>) {
+        assert!(!self.gen_args.is_empty());
+
+        if self.gen_args.parenthesized {
+            return;
+        }
+
+        let missing_arg_count = self.expected_min - self.provided;
+
+        let (span, sugg_prefix) = if self.args_offset + self.provided == 0 {
+            let span = self.gen_args.args[0].span().shrink_to_lo();
+            (span, "")
+        } else {
+            let span =
+                self.gen_args.args[self.args_offset + self.provided - 1].span().shrink_to_hi();
+            (span, ", ")
+        };
+
+        let msg = format!("add missing {} argument{}", self.kind, pluralize!(missing_arg_count));
+
+        let sugg = self
+            .gen_params
+            .params
+            .iter()
+            .skip(self.params_offset + self.provided)
+            .take(missing_arg_count)
+            .map(|param| param.name.to_string())
+            .collect::<Vec<_>>()
+            .join(", ");
+
+        let sugg = format!("{}{}", sugg_prefix, sugg);
+
+        err.span_suggestion_verbose(span, &msg, sugg, Applicability::HasPlaceholders);
+    }
+
+    /// Suggests to remove redundant argument(s):
+    ///
+    /// ```text
+    /// type Map = HashMap<String, String, String, String>;
+    /// ```
+    fn suggest_removing_args_or_generics(&self, err: &mut DiagnosticBuilder<'_>) {
+        assert!(self.provided > 0);
+
+        let redundant_args_count = self.provided - self.expected_max;
+        let remove_entire_generics = redundant_args_count >= self.gen_args.args.len();
+
+        let (span, msg) = if remove_entire_generics {
+            let sm = self.tcx.sess.source_map();
+
+            let span = self
+                .path_segment
+                .args
+                .unwrap()
+                .span_ext(sm)
+                .unwrap()
+                .with_lo(self.path_segment.ident.span.hi());
+
+            let msg = format!(
+                "remove these {}generics",
+                if self.gen_args.parenthesized { "parenthetical " } else { "" },
+            );
+
+            (span, msg)
+        } else {
+            // When it comes to removing particular argument(s) from the generics, there are two
+            // edge cases we have to consider:
+            //
+            // When the first redundant argument is at the beginning or in the middle of the
+            // generics, like so:
+            //
+            // ```
+            // type Map = HashMap<String, String, String, String>;
+            //                    ^^^^^^^^^^^^^^^^
+            //                    | span must start with the argument
+            // ```
+            //
+            // When the last redundant argument is at the ending of the generics, like so:
+            //
+            // ```
+            // type Map = HashMap<String, String, String, String>;
+            //                                  ^^^^^^^^^^^^^^^^
+            //                                  | span must start with the comma
+            // ```
+
+            // Index of the first redundant argument
+            let from_idx = self.args_offset + self.expected_max;
+
+            // Index of the last redundant argument
+            let to_idx = self.args_offset + self.provided - 1;
+
+            assert!(from_idx <= to_idx);
+
+            let (from, comma_eaten) = {
+                let first_argument_starts_generics = from_idx == 0;
+                let last_argument_ends_generics = to_idx + 1 == self.gen_args.args.len();
+
+                if !first_argument_starts_generics && last_argument_ends_generics {
+                    (self.gen_args.args[from_idx - 1].span().hi(), true)
+                } else {
+                    (self.gen_args.args[from_idx].span().lo(), false)
+                }
+            };
+
+            let to = {
+                let hi = self.gen_args.args[to_idx].span().hi();
+
+                if comma_eaten {
+                    hi
+                } else {
+                    self.gen_args.args.get(to_idx + 1).map(|arg| arg.span().lo()).unwrap_or(hi)
+                }
+            };
+
+            let span = Span::new(from, to, self.span.ctxt());
+
+            let msg = format!(
+                "remove {} {} argument{}",
+                if redundant_args_count == 1 { "this" } else { "these" },
+                self.kind,
+                pluralize!(redundant_args_count),
+            );
+
+            (span, msg)
+        };
+
+        err.span_suggestion(span, &msg, String::new(), Applicability::MaybeIncorrect);
+    }
+
+    /// Builds the `type defined here` message.
+    fn show_definition(&self, err: &mut DiagnosticBuilder<'_>) {
+        let mut spans: MultiSpan = if let Some(def_span) = self.tcx.def_ident_span(self.def_id) {
+            def_span.into()
+        } else {
+            return;
+        };
+
+        let msg = {
+            let def_kind = self.tcx.def_kind(self.def_id).descr(self.def_id);
+            let (quantifier, bound) = self.quantifier_and_bound();
+
+            let params = if bound == 0 {
+                String::new()
+            } else {
+                let params = self
+                    .gen_params
+                    .params
+                    .iter()
+                    .skip(self.params_offset)
+                    .take(bound)
+                    .map(|param| {
+                        let span = self.tcx.def_span(param.def_id);
+                        spans.push_span_label(span, String::new());
+                        param
+                    })
+                    .map(|param| format!("`{}`", param.name))
+                    .collect::<Vec<_>>()
+                    .join(", ");
+
+                format!(": {}", params)
+            };
+
+            format!(
+                "{} defined here, with {}{} {} parameter{}{}",
+                def_kind,
+                quantifier,
+                bound,
+                self.kind,
+                pluralize!(bound),
+                params,
+            )
+        };
+
+        err.span_note(spans, &msg);
+    }
+}
+
+impl<'tcx> StructuredDiagnostic<'tcx> for WrongNumberOfGenericArgs<'_, 'tcx> {
+    fn session(&self) -> &Session {
+        self.tcx.sess
+    }
+
+    fn code(&self) -> DiagnosticId {
+        rustc_errors::error_code!(E0107)
+    }
+
+    fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> {
+        let mut err = self.start_diagnostics();
+
+        self.notify(&mut err);
+        self.suggest(&mut err);
+        self.show_definition(&mut err);
+
+        err
+    }
+}
diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs
index 09209306c9d..117db6e3e3b 100644
--- a/library/core/src/slice/raw.rs
+++ b/library/core/src/slice/raw.rs
@@ -103,7 +103,7 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
 ///
 /// Behavior is undefined if any of the following conditions are violated:
 ///
-/// * `data` must be [valid] for boths reads and writes for `len * mem::size_of::<T>()` many bytes,
+/// * `data` must be [valid] for both reads and writes for `len * mem::size_of::<T>()` many bytes,
 ///   and it must be properly aligned. This means in particular:
 ///
 ///     * The entire memory range of this slice must be contained within a single allocated object!
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 14564e7f64a..8dbc36cf0cb 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1328,7 +1328,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &DocContext<'_>) -> Type {
                 let mut ty_substs = FxHashMap::default();
                 let mut lt_substs = FxHashMap::default();
                 let mut ct_substs = FxHashMap::default();
-                let generic_args = provided_params.generic_args();
+                let generic_args = provided_params.args();
                 {
                     let mut indices: GenericParamCount = Default::default();
                     for param in generics.params.iter() {
@@ -1943,7 +1943,7 @@ impl Clean<GenericArgs> for hir::GenericArgs<'_> {
 
 impl Clean<PathSegment> for hir::PathSegment<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> PathSegment {
-        PathSegment { name: self.ident.name, args: self.generic_args().clean(cx) }
+        PathSegment { name: self.ident.name, args: self.args().clean(cx) }
     }
 }
 
diff --git a/src/test/ui/async-await/issues/issue-65159.rs b/src/test/ui/async-await/issues/issue-65159.rs
index 4f160fccc01..ce3fa9180cb 100644
--- a/src/test/ui/async-await/issues/issue-65159.rs
+++ b/src/test/ui/async-await/issues/issue-65159.rs
@@ -2,7 +2,8 @@
 //
 // edition:2018
 
-async fn copy() -> Result<()> //~ ERROR wrong number of type arguments
+async fn copy() -> Result<()>
+//~^ ERROR this enum takes 2 type arguments but only 1 type argument was supplied
 {
     Ok(())
     //~^ ERROR type annotations needed
diff --git a/src/test/ui/async-await/issues/issue-65159.stderr b/src/test/ui/async-await/issues/issue-65159.stderr
index 04cfa524998..bcb4c292e26 100644
--- a/src/test/ui/async-await/issues/issue-65159.stderr
+++ b/src/test/ui/async-await/issues/issue-65159.stderr
@@ -1,11 +1,23 @@
-error[E0107]: wrong number of type arguments: expected 2, found 1
+error[E0107]: this enum takes 2 type arguments but only 1 type argument was supplied
   --> $DIR/issue-65159.rs:5:20
    |
 LL | async fn copy() -> Result<()>
-   |                    ^^^^^^^^^^ expected 2 type arguments
+   |                    ^^^^^^ -- supplied 1 type argument
+   |                    |
+   |                    expected 2 type arguments
+   |
+note: enum defined here, with 2 type parameters: `T`, `E`
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+   |
+LL | pub enum Result<T, E> {
+   |          ^^^^^^ -  -
+help: add missing type argument
+   |
+LL | async fn copy() -> Result<(), E>
+   |                             ^^^
 
 error[E0282]: type annotations needed
-  --> $DIR/issue-65159.rs:7:5
+  --> $DIR/issue-65159.rs:8:5
    |
 LL |     Ok(())
    |     ^^ cannot infer type for type parameter `E` declared on the enum `Result`
diff --git a/src/test/ui/bad/bad-mid-path-type-params.rs b/src/test/ui/bad/bad-mid-path-type-params.rs
index 016b1d617e0..c42ce602e99 100644
--- a/src/test/ui/bad/bad-mid-path-type-params.rs
+++ b/src/test/ui/bad/bad-mid-path-type-params.rs
@@ -28,16 +28,17 @@ impl Trait<isize> for S2 {
 
 fn foo<'a>() {
     let _ = S::new::<isize,f64>(1, 1.0);
-    //~^ ERROR wrong number of type arguments
+    //~^ ERROR this associated function takes 1 type argument but 2 type arguments were supplied
 
     let _ = S::<'a,isize>::new::<f64>(1, 1.0);
-    //~^ ERROR wrong number of lifetime arguments
+    //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
 
     let _: S2 = Trait::new::<isize,f64>(1, 1.0);
-    //~^ ERROR wrong number of type arguments
+    //~^ ERROR this associated function takes 1 type argument but 2 type arguments were supplied
 
-    let _: S2 = Trait::<'a,isize>::new::<f64>(1, 1.0);
-    //~^ ERROR wrong number of lifetime arguments
+    let _: S2 = Trait::<'a,isize>::new::<f64,f64>(1, 1.0);
+    //~^ ERROR this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
+    //~| ERROR this associated function takes 1 type argument but 2 type arguments were supplied
 }
 
 fn main() {}
diff --git a/src/test/ui/bad/bad-mid-path-type-params.stderr b/src/test/ui/bad/bad-mid-path-type-params.stderr
index ef53c9a38c7..dd96856e563 100644
--- a/src/test/ui/bad/bad-mid-path-type-params.stderr
+++ b/src/test/ui/bad/bad-mid-path-type-params.stderr
@@ -1,27 +1,73 @@
-error[E0107]: wrong number of type arguments: expected 1, found 2
-  --> $DIR/bad-mid-path-type-params.rs:30:28
+error[E0107]: this associated function takes 1 type argument but 2 type arguments were supplied
+  --> $DIR/bad-mid-path-type-params.rs:30:16
    |
 LL |     let _ = S::new::<isize,f64>(1, 1.0);
-   |                            ^^^ unexpected type argument
+   |                ^^^        ---- help: remove this type argument
+   |                |
+   |                expected 1 type argument
+   |
+note: associated function defined here, with 1 type parameter: `U`
+  --> $DIR/bad-mid-path-type-params.rs:6:8
+   |
+LL |     fn new<U>(x: T, _: U) -> S<T> {
+   |        ^^^ -
 
-error[E0107]: wrong number of lifetime arguments: expected 0, found 1
-  --> $DIR/bad-mid-path-type-params.rs:33:17
+error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/bad-mid-path-type-params.rs:33:13
    |
 LL |     let _ = S::<'a,isize>::new::<f64>(1, 1.0);
-   |                 ^^ unexpected lifetime argument
+   |             ^   --- help: remove this lifetime argument
+   |             |
+   |             expected 0 lifetime arguments
+   |
+note: struct defined here, with 0 lifetime parameters
+  --> $DIR/bad-mid-path-type-params.rs:1:8
+   |
+LL | struct S<T> {
+   |        ^
 
-error[E0107]: wrong number of type arguments: expected 1, found 2
-  --> $DIR/bad-mid-path-type-params.rs:36:36
+error[E0107]: this associated function takes 1 type argument but 2 type arguments were supplied
+  --> $DIR/bad-mid-path-type-params.rs:36:24
    |
 LL |     let _: S2 = Trait::new::<isize,f64>(1, 1.0);
-   |                                    ^^^ unexpected type argument
+   |                        ^^^        ---- help: remove this type argument
+   |                        |
+   |                        expected 1 type argument
+   |
+note: associated function defined here, with 1 type parameter: `U`
+  --> $DIR/bad-mid-path-type-params.rs:14:8
+   |
+LL |     fn new<U>(x: T, y: U) -> Self;
+   |        ^^^ -
 
-error[E0107]: wrong number of lifetime arguments: expected 0, found 1
-  --> $DIR/bad-mid-path-type-params.rs:39:25
+error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/bad-mid-path-type-params.rs:39:17
+   |
+LL |     let _: S2 = Trait::<'a,isize>::new::<f64,f64>(1, 1.0);
+   |                 ^^^^^   --- help: remove this lifetime argument
+   |                 |
+   |                 expected 0 lifetime arguments
+   |
+note: trait defined here, with 0 lifetime parameters
+  --> $DIR/bad-mid-path-type-params.rs:13:7
+   |
+LL | trait Trait<T> {
+   |       ^^^^^
+
+error[E0107]: this associated function takes 1 type argument but 2 type arguments were supplied
+  --> $DIR/bad-mid-path-type-params.rs:39:36
+   |
+LL |     let _: S2 = Trait::<'a,isize>::new::<f64,f64>(1, 1.0);
+   |                                    ^^^      ---- help: remove this type argument
+   |                                    |
+   |                                    expected 1 type argument
+   |
+note: associated function defined here, with 1 type parameter: `U`
+  --> $DIR/bad-mid-path-type-params.rs:14:8
    |
-LL |     let _: S2 = Trait::<'a,isize>::new::<f64>(1, 1.0);
-   |                         ^^ unexpected lifetime argument
+LL |     fn new<U>(x: T, y: U) -> Self;
+   |        ^^^ -
 
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/const-generics/incorrect-number-of-const-args.full.stderr b/src/test/ui/const-generics/incorrect-number-of-const-args.full.stderr
index 9c8359b08a5..dd7e63480eb 100644
--- a/src/test/ui/const-generics/incorrect-number-of-const-args.full.stderr
+++ b/src/test/ui/const-generics/incorrect-number-of-const-args.full.stderr
@@ -1,14 +1,34 @@
-error[E0107]: wrong number of const arguments: expected 2, found 1
+error[E0107]: this function takes 2 const arguments but only 1 const argument was supplied
   --> $DIR/incorrect-number-of-const-args.rs:11:5
    |
 LL |     foo::<0>();
-   |     ^^^^^^^^ expected 2 const arguments
+   |     ^^^   - supplied 1 const argument
+   |     |
+   |     expected 2 const arguments
+   |
+note: function defined here, with 2 const parameters: `X`, `Y`
+  --> $DIR/incorrect-number-of-const-args.rs:6:4
+   |
+LL | fn foo<const X: usize, const Y: usize>() -> usize {
+   |    ^^^       -               -
+help: add missing const argument
+   |
+LL |     foo::<0, Y>();
+   |            ^^^
 
-error[E0107]: wrong number of const arguments: expected 2, found 3
-  --> $DIR/incorrect-number-of-const-args.rs:12:17
+error[E0107]: this function takes 2 const arguments but 3 const arguments were supplied
+  --> $DIR/incorrect-number-of-const-args.rs:14:5
    |
 LL |     foo::<0, 0, 0>();
-   |                 ^ unexpected const argument
+   |     ^^^       --- help: remove this const argument
+   |     |
+   |     expected 2 const arguments
+   |
+note: function defined here, with 2 const parameters: `X`, `Y`
+  --> $DIR/incorrect-number-of-const-args.rs:6:4
+   |
+LL | fn foo<const X: usize, const Y: usize>() -> usize {
+   |    ^^^       -               -
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/incorrect-number-of-const-args.min.stderr b/src/test/ui/const-generics/incorrect-number-of-const-args.min.stderr
index 9c8359b08a5..dd7e63480eb 100644
--- a/src/test/ui/const-generics/incorrect-number-of-const-args.min.stderr
+++ b/src/test/ui/const-generics/incorrect-number-of-const-args.min.stderr
@@ -1,14 +1,34 @@
-error[E0107]: wrong number of const arguments: expected 2, found 1
+error[E0107]: this function takes 2 const arguments but only 1 const argument was supplied
   --> $DIR/incorrect-number-of-const-args.rs:11:5
    |
 LL |     foo::<0>();
-   |     ^^^^^^^^ expected 2 const arguments
+   |     ^^^   - supplied 1 const argument
+   |     |
+   |     expected 2 const arguments
+   |
+note: function defined here, with 2 const parameters: `X`, `Y`
+  --> $DIR/incorrect-number-of-const-args.rs:6:4
+   |
+LL | fn foo<const X: usize, const Y: usize>() -> usize {
+   |    ^^^       -               -
+help: add missing const argument
+   |
+LL |     foo::<0, Y>();
+   |            ^^^
 
-error[E0107]: wrong number of const arguments: expected 2, found 3
-  --> $DIR/incorrect-number-of-const-args.rs:12:17
+error[E0107]: this function takes 2 const arguments but 3 const arguments were supplied
+  --> $DIR/incorrect-number-of-const-args.rs:14:5
    |
 LL |     foo::<0, 0, 0>();
-   |                 ^ unexpected const argument
+   |     ^^^       --- help: remove this const argument
+   |     |
+   |     expected 2 const arguments
+   |
+note: function defined here, with 2 const parameters: `X`, `Y`
+  --> $DIR/incorrect-number-of-const-args.rs:6:4
+   |
+LL | fn foo<const X: usize, const Y: usize>() -> usize {
+   |    ^^^       -               -
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/incorrect-number-of-const-args.rs b/src/test/ui/const-generics/incorrect-number-of-const-args.rs
index 3c4290df056..3114e716845 100644
--- a/src/test/ui/const-generics/incorrect-number-of-const-args.rs
+++ b/src/test/ui/const-generics/incorrect-number-of-const-args.rs
@@ -8,6 +8,9 @@ fn foo<const X: usize, const Y: usize>() -> usize {
 }
 
 fn main() {
-    foo::<0>(); //~ ERROR wrong number of const arguments: expected 2, found 1
-    foo::<0, 0, 0>(); //~ ERROR wrong number of const arguments: expected 2, found 3
+    foo::<0>();
+    //~^ ERROR this function takes 2 const arguments but only 1 const argument was supplied
+
+    foo::<0, 0, 0>();
+    //~^ ERROR this function takes 2 const arguments but 3 const arguments were supplied
 }
diff --git a/src/test/ui/const-generics/invalid-const-arg-for-type-param.rs b/src/test/ui/const-generics/invalid-const-arg-for-type-param.rs
index b069cd89680..b67a1f153ff 100644
--- a/src/test/ui/const-generics/invalid-const-arg-for-type-param.rs
+++ b/src/test/ui/const-generics/invalid-const-arg-for-type-param.rs
@@ -3,7 +3,12 @@ use std::convert::TryInto;
 struct S;
 
 fn main() {
-    let _: u32 = 5i32.try_into::<32>().unwrap(); //~ ERROR wrong number of const arguments
-    S.f::<0>(); //~ ERROR no method named `f`
-    S::<0>; //~ ERROR  wrong number of const arguments
+    let _: u32 = 5i32.try_into::<32>().unwrap();
+    //~^ ERROR this associated function takes 0 const arguments but 1 const argument was supplied
+
+    S.f::<0>();
+    //~^ ERROR no method named `f`
+
+    S::<0>;
+    //~^ ERROR this struct takes 0 const arguments but 1 const argument was supplied
 }
diff --git a/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr b/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr
index 19e7d2036bf..a75da91caa8 100644
--- a/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr
+++ b/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr
@@ -1,11 +1,19 @@
-error[E0107]: wrong number of const arguments: expected 0, found 1
-  --> $DIR/invalid-const-arg-for-type-param.rs:6:34
+error[E0107]: this associated function takes 0 const arguments but 1 const argument was supplied
+  --> $DIR/invalid-const-arg-for-type-param.rs:6:23
    |
 LL |     let _: u32 = 5i32.try_into::<32>().unwrap();
-   |                                  ^^ unexpected const argument
+   |                       ^^^^^^^^------ help: remove these generics
+   |                       |
+   |                       expected 0 const arguments
+   |
+note: associated function defined here, with 0 const parameters
+  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
+   |
+LL |     fn try_into(self) -> Result<T, Self::Error>;
+   |        ^^^^^^^^
 
 error[E0599]: no method named `f` found for struct `S` in the current scope
-  --> $DIR/invalid-const-arg-for-type-param.rs:7:7
+  --> $DIR/invalid-const-arg-for-type-param.rs:9:7
    |
 LL | struct S;
    | --------- method `f` not found for this
@@ -13,11 +21,19 @@ LL | struct S;
 LL |     S.f::<0>();
    |       ^ method not found in `S`
 
-error[E0107]: wrong number of const arguments: expected 0, found 1
-  --> $DIR/invalid-const-arg-for-type-param.rs:8:9
+error[E0107]: this struct takes 0 const arguments but 1 const argument was supplied
+  --> $DIR/invalid-const-arg-for-type-param.rs:12:5
    |
 LL |     S::<0>;
-   |         ^ unexpected const argument
+   |     ^----- help: remove these generics
+   |     |
+   |     expected 0 const arguments
+   |
+note: struct defined here, with 0 const parameters
+  --> $DIR/invalid-const-arg-for-type-param.rs:3:8
+   |
+LL | struct S;
+   |        ^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/const-generics/invalid-constant-in-args.rs b/src/test/ui/const-generics/invalid-constant-in-args.rs
index 0bd9cbf4f47..7419d4a25ce 100644
--- a/src/test/ui/const-generics/invalid-constant-in-args.rs
+++ b/src/test/ui/const-generics/invalid-constant-in-args.rs
@@ -2,5 +2,5 @@ use std::cell::Cell;
 
 fn main() {
     let _: Cell<&str, "a"> = Cell::new("");
-    //~^ ERROR wrong number of generic arguments
+    //~^ ERROR this struct takes 1 generic argument but 2 generic arguments were supplied
 }
diff --git a/src/test/ui/const-generics/invalid-constant-in-args.stderr b/src/test/ui/const-generics/invalid-constant-in-args.stderr
index 9b8a5d1ae4f..57c1af36d61 100644
--- a/src/test/ui/const-generics/invalid-constant-in-args.stderr
+++ b/src/test/ui/const-generics/invalid-constant-in-args.stderr
@@ -1,8 +1,16 @@
-error[E0107]: wrong number of generic arguments: expected 1, found 2
-  --> $DIR/invalid-constant-in-args.rs:4:23
+error[E0107]: this struct takes 1 generic argument but 2 generic arguments were supplied
+  --> $DIR/invalid-constant-in-args.rs:4:12
    |
 LL |     let _: Cell<&str, "a"> = Cell::new("");
-   |                       ^^^ unexpected const argument
+   |            ^^^^     ----- help: remove this generic argument
+   |            |
+   |            expected 1 generic argument
+   |
+note: struct defined here, with 1 generic parameter: `T`
+  --> $SRC_DIR/core/src/cell.rs:LL:COL
+   |
+LL | pub struct Cell<T: ?Sized> {
+   |            ^^^^ -
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issues/issue-76595.rs b/src/test/ui/const-generics/issues/issue-76595.rs
index 04c01901517..d95d675ddad 100644
--- a/src/test/ui/const-generics/issues/issue-76595.rs
+++ b/src/test/ui/const-generics/issues/issue-76595.rs
@@ -13,5 +13,5 @@ fn test<T, const P: usize>() where Bool<{core::mem::size_of::<T>() > 4}>: True {
 
 fn main() {
     test::<2>();
-    //~^ ERROR wrong number of generic arguments
+    //~^ ERROR this function takes 2 generic arguments but only 1 generic argument was supplied
 }
diff --git a/src/test/ui/const-generics/issues/issue-76595.stderr b/src/test/ui/const-generics/issues/issue-76595.stderr
index 1e37f9dcb19..9d95e5a014d 100644
--- a/src/test/ui/const-generics/issues/issue-76595.stderr
+++ b/src/test/ui/const-generics/issues/issue-76595.stderr
@@ -1,8 +1,20 @@
-error[E0107]: wrong number of generic arguments: expected 2, found 1
+error[E0107]: this function takes 2 generic arguments but only 1 generic argument was supplied
   --> $DIR/issue-76595.rs:15:5
    |
 LL |     test::<2>();
-   |     ^^^^^^^^^ expected 2 generic arguments
+   |     ^^^^   - supplied 1 generic argument
+   |     |
+   |     expected 2 generic arguments
+   |
+note: function defined here, with 2 generic parameters: `T`, `P`
+  --> $DIR/issue-76595.rs:10:4
+   |
+LL | fn test<T, const P: usize>() where Bool<{core::mem::size_of::<T>() > 4}>: True {
+   |    ^^^^ -        -
+help: add missing generic argument
+   |
+LL |     test::<2, P>();
+   |             ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/constructor-lifetime-args.rs b/src/test/ui/constructor-lifetime-args.rs
index 6af5f6d56e7..d038269382b 100644
--- a/src/test/ui/constructor-lifetime-args.rs
+++ b/src/test/ui/constructor-lifetime-args.rs
@@ -15,12 +15,12 @@ enum E<'a, 'b> {
 fn main() {
     S(&0, &0); // OK
     S::<'static>(&0, &0);
-    //~^ ERROR wrong number of lifetime arguments: expected 2, found 1
+    //~^ ERROR this struct takes 2 lifetime arguments but only 1 lifetime argument was supplied
     S::<'static, 'static, 'static>(&0, &0);
-    //~^ ERROR wrong number of lifetime arguments: expected 2, found 3
+    //~^ ERROR this struct takes 2 lifetime arguments but 3 lifetime arguments were supplied
     E::V(&0); // OK
     E::V::<'static>(&0);
-    //~^ ERROR wrong number of lifetime arguments: expected 2, found 1
+    //~^ ERROR this enum takes 2 lifetime arguments but only 1 lifetime argument was supplied
     E::V::<'static, 'static, 'static>(&0);
-    //~^ ERROR wrong number of lifetime arguments: expected 2, found 3
+    //~^ ERROR this enum takes 2 lifetime arguments but 3 lifetime arguments were supplied
 }
diff --git a/src/test/ui/constructor-lifetime-args.stderr b/src/test/ui/constructor-lifetime-args.stderr
index ec8ed9288cc..378b07694e6 100644
--- a/src/test/ui/constructor-lifetime-args.stderr
+++ b/src/test/ui/constructor-lifetime-args.stderr
@@ -1,26 +1,66 @@
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: this struct takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/constructor-lifetime-args.rs:17:5
    |
 LL |     S::<'static>(&0, &0);
-   |     ^^^^^^^^^^^^ expected 2 lifetime arguments
+   |     ^   ------- supplied 1 lifetime argument
+   |     |
+   |     expected 2 lifetime arguments
+   |
+note: struct defined here, with 2 lifetime parameters: `'a`, `'b`
+  --> $DIR/constructor-lifetime-args.rs:9:8
+   |
+LL | struct S<'a, 'b>(&'a u8, &'b u8);
+   |        ^ --  --
+help: add missing lifetime argument
+   |
+LL |     S::<'static, 'b>(&0, &0);
+   |                ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 3
-  --> $DIR/constructor-lifetime-args.rs:19:27
+error[E0107]: this struct takes 2 lifetime arguments but 3 lifetime arguments were supplied
+  --> $DIR/constructor-lifetime-args.rs:19:5
    |
 LL |     S::<'static, 'static, 'static>(&0, &0);
-   |                           ^^^^^^^ unexpected lifetime argument
+   |     ^                   --------- help: remove this lifetime argument
+   |     |
+   |     expected 2 lifetime arguments
+   |
+note: struct defined here, with 2 lifetime parameters: `'a`, `'b`
+  --> $DIR/constructor-lifetime-args.rs:9:8
+   |
+LL | struct S<'a, 'b>(&'a u8, &'b u8);
+   |        ^ --  --
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
-  --> $DIR/constructor-lifetime-args.rs:22:5
+error[E0107]: this enum takes 2 lifetime arguments but only 1 lifetime argument was supplied
+  --> $DIR/constructor-lifetime-args.rs:22:8
    |
 LL |     E::V::<'static>(&0);
-   |     ^^^^^^^^^^^^^^^ expected 2 lifetime arguments
+   |        ^   ------- supplied 1 lifetime argument
+   |        |
+   |        expected 2 lifetime arguments
+   |
+note: enum defined here, with 2 lifetime parameters: `'a`, `'b`
+  --> $DIR/constructor-lifetime-args.rs:10:6
+   |
+LL | enum E<'a, 'b> {
+   |      ^ --  --
+help: add missing lifetime argument
+   |
+LL |     E::V::<'static, 'b>(&0);
+   |                   ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 3
-  --> $DIR/constructor-lifetime-args.rs:24:30
+error[E0107]: this enum takes 2 lifetime arguments but 3 lifetime arguments were supplied
+  --> $DIR/constructor-lifetime-args.rs:24:8
    |
 LL |     E::V::<'static, 'static, 'static>(&0);
-   |                              ^^^^^^^ unexpected lifetime argument
+   |        ^                   --------- help: remove this lifetime argument
+   |        |
+   |        expected 2 lifetime arguments
+   |
+note: enum defined here, with 2 lifetime parameters: `'a`, `'b`
+  --> $DIR/constructor-lifetime-args.rs:10:6
+   |
+LL | enum E<'a, 'b> {
+   |      ^ --  --
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/error-codes/E0107.rs b/src/test/ui/error-codes/E0107.rs
index 35173dcce30..c3dde72599b 100644
--- a/src/test/ui/error-codes/E0107.rs
+++ b/src/test/ui/error-codes/E0107.rs
@@ -9,15 +9,16 @@ enum Bar {
 
 struct Baz<'a, 'b, 'c> {
     buzz: Buzz<'a>,
-    //~^ ERROR E0107
-    //~| expected 2 lifetime arguments
+    //~^ ERROR this struct takes 2 lifetime arguments but only 1 lifetime argument was supplied
+    //~| HELP add missing lifetime argument
+
     bar: Bar<'a>,
-    //~^ ERROR E0107
-    //~| unexpected lifetime argument
+    //~^ ERROR this enum takes 0 lifetime arguments but 1 lifetime argument was supplied
+    //~| HELP remove these generics
+
     foo2: Foo<'a, 'b, 'c>,
-    //~^ ERROR E0107
-    //~| unexpected lifetime argument
-    //~| unexpected lifetime argument
+    //~^ ERROR this struct takes 1 lifetime argument but 3 lifetime arguments were supplied
+    //~| HELP remove these lifetime arguments
 }
 
 fn main() {}
diff --git a/src/test/ui/error-codes/E0107.stderr b/src/test/ui/error-codes/E0107.stderr
index 486810ab113..30a2768d060 100644
--- a/src/test/ui/error-codes/E0107.stderr
+++ b/src/test/ui/error-codes/E0107.stderr
@@ -1,22 +1,48 @@
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: this struct takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/E0107.rs:11:11
    |
 LL |     buzz: Buzz<'a>,
-   |           ^^^^^^^^ expected 2 lifetime arguments
+   |           ^^^^ -- supplied 1 lifetime argument
+   |           |
+   |           expected 2 lifetime arguments
+   |
+note: struct defined here, with 2 lifetime parameters: `'a`, `'b`
+  --> $DIR/E0107.rs:2:8
+   |
+LL | struct Buzz<'a, 'b>(&'a str, &'b str);
+   |        ^^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     buzz: Buzz<'a, 'b>,
+   |                  ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 0, found 1
-  --> $DIR/E0107.rs:14:14
+error[E0107]: this enum takes 0 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/E0107.rs:15:10
    |
 LL |     bar: Bar<'a>,
-   |              ^^ unexpected lifetime argument
+   |          ^^^---- help: remove these generics
+   |          |
+   |          expected 0 lifetime arguments
+   |
+note: enum defined here, with 0 lifetime parameters
+  --> $DIR/E0107.rs:4:6
+   |
+LL | enum Bar {
+   |      ^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 1, found 3
-  --> $DIR/E0107.rs:17:19
+error[E0107]: this struct takes 1 lifetime argument but 3 lifetime arguments were supplied
+  --> $DIR/E0107.rs:19:11
    |
 LL |     foo2: Foo<'a, 'b, 'c>,
-   |                   ^^  ^^ unexpected lifetime argument
-   |                   |
-   |                   unexpected lifetime argument
+   |           ^^^   -------- help: remove these lifetime arguments
+   |           |
+   |           expected 1 lifetime argument
+   |
+note: struct defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/E0107.rs:1:8
+   |
+LL | struct Foo<'a>(&'a str);
+   |        ^^^ --
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/generic-associated-types/parameter_number_and_kind.rs b/src/test/ui/generic-associated-types/parameter_number_and_kind.rs
index f4d09fc1539..9d7ef88b767 100644
--- a/src/test/ui/generic-associated-types/parameter_number_and_kind.rs
+++ b/src/test/ui/generic-associated-types/parameter_number_and_kind.rs
@@ -11,10 +11,10 @@ trait Foo {
     // Test parameters in default values
     type FOk<T> = Self::E<'static, T>;
     type FErr1 = Self::E<'static, 'static>;
-    //~^ ERROR wrong number of lifetime arguments: expected 1, found 2
-    //~| ERROR wrong number of type arguments: expected 1, found 0
+    //~^ ERROR this associated type takes 1 lifetime argument but 2 lifetime arguments were supplied
+    //~| ERROR this associated type takes 1 type argument but 0 type arguments were supplied
     type FErr2<T> = Self::E<'static, T, u32>;
-    //~^ ERROR wrong number of type arguments: expected 1, found 2
+    //~^ ERROR this associated type takes 1 type argument but 2 type arguments were supplied
 }
 
 fn main() {}
diff --git a/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr b/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr
index ed090e302ce..d021889c084 100644
--- a/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr
+++ b/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr
@@ -1,20 +1,46 @@
-error[E0107]: wrong number of lifetime arguments: expected 1, found 2
-  --> $DIR/parameter_number_and_kind.rs:13:35
+error[E0107]: this associated type takes 1 lifetime argument but 2 lifetime arguments were supplied
+  --> $DIR/parameter_number_and_kind.rs:13:24
    |
 LL |     type FErr1 = Self::E<'static, 'static>;
-   |                                   ^^^^^^^ unexpected lifetime argument
+   |                        ^        --------- help: remove this lifetime argument
+   |                        |
+   |                        expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/parameter_number_and_kind.rs:10:10
+   |
+LL |     type E<'a, T>;
+   |          ^ --
 
-error[E0107]: wrong number of type arguments: expected 1, found 0
-  --> $DIR/parameter_number_and_kind.rs:13:18
+error[E0107]: this associated type takes 1 type argument but 0 type arguments were supplied
+  --> $DIR/parameter_number_and_kind.rs:13:24
    |
 LL |     type FErr1 = Self::E<'static, 'static>;
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 type argument
+   |                        ^ expected 1 type argument
+   |
+note: associated type defined here, with 1 type parameter: `T`
+  --> $DIR/parameter_number_and_kind.rs:10:10
+   |
+LL |     type E<'a, T>;
+   |          ^     -
+help: add missing type argument
+   |
+LL |     type FErr1 = Self::E<'static, 'static, T>;
+   |                                          ^^^
 
-error[E0107]: wrong number of type arguments: expected 1, found 2
-  --> $DIR/parameter_number_and_kind.rs:16:41
+error[E0107]: this associated type takes 1 type argument but 2 type arguments were supplied
+  --> $DIR/parameter_number_and_kind.rs:16:27
    |
 LL |     type FErr2<T> = Self::E<'static, T, u32>;
-   |                                         ^^^ unexpected type argument
+   |                           ^           ----- help: remove this type argument
+   |                           |
+   |                           expected 1 type argument
+   |
+note: associated type defined here, with 1 type parameter: `T`
+  --> $DIR/parameter_number_and_kind.rs:10:10
+   |
+LL |     type E<'a, T>;
+   |          ^     -
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/generics/generic-arg-mismatch-recover.rs b/src/test/ui/generics/generic-arg-mismatch-recover.rs
index 3e5e2e601f5..0e0d1daec5f 100644
--- a/src/test/ui/generics/generic-arg-mismatch-recover.rs
+++ b/src/test/ui/generics/generic-arg-mismatch-recover.rs
@@ -3,8 +3,10 @@ struct Foo<'a, T: 'a>(&'a T);
 struct Bar<'a>(&'a ());
 
 fn main() {
-    Foo::<'static, 'static, ()>(&0); //~ ERROR wrong number of lifetime arguments
+    Foo::<'static, 'static, ()>(&0);
+    //~^ ERROR this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
 
-    Bar::<'static, 'static, ()>(&()); //~ ERROR wrong number of lifetime arguments
-    //~^ ERROR wrong number of type arguments
+    Bar::<'static, 'static, ()>(&());
+    //~^ ERROR this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
+    //~| ERROR this struct takes 0 type arguments but 1 type argument was supplied
 }
diff --git a/src/test/ui/generics/generic-arg-mismatch-recover.stderr b/src/test/ui/generics/generic-arg-mismatch-recover.stderr
index 99adb352685..ca73b82737d 100644
--- a/src/test/ui/generics/generic-arg-mismatch-recover.stderr
+++ b/src/test/ui/generics/generic-arg-mismatch-recover.stderr
@@ -1,20 +1,44 @@
-error[E0107]: wrong number of lifetime arguments: expected 1, found 2
-  --> $DIR/generic-arg-mismatch-recover.rs:6:20
+error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
+  --> $DIR/generic-arg-mismatch-recover.rs:6:5
    |
 LL |     Foo::<'static, 'static, ()>(&0);
-   |                    ^^^^^^^ unexpected lifetime argument
+   |     ^^^            --------- help: remove this lifetime argument
+   |     |
+   |     expected 1 lifetime argument
+   |
+note: struct defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/generic-arg-mismatch-recover.rs:1:8
+   |
+LL | struct Foo<'a, T: 'a>(&'a T);
+   |        ^^^ --
 
-error[E0107]: wrong number of lifetime arguments: expected 1, found 2
-  --> $DIR/generic-arg-mismatch-recover.rs:8:20
+error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
+  --> $DIR/generic-arg-mismatch-recover.rs:9:5
    |
 LL |     Bar::<'static, 'static, ()>(&());
-   |                    ^^^^^^^ unexpected lifetime argument
+   |     ^^^            --------- help: remove this lifetime argument
+   |     |
+   |     expected 1 lifetime argument
+   |
+note: struct defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/generic-arg-mismatch-recover.rs:3:8
+   |
+LL | struct Bar<'a>(&'a ());
+   |        ^^^ --
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/generic-arg-mismatch-recover.rs:8:29
+error[E0107]: this struct takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/generic-arg-mismatch-recover.rs:9:5
    |
 LL |     Bar::<'static, 'static, ()>(&());
-   |                             ^^ unexpected type argument
+   |     ^^^                   ---- help: remove this type argument
+   |     |
+   |     expected 0 type arguments
+   |
+note: struct defined here, with 0 type parameters
+  --> $DIR/generic-arg-mismatch-recover.rs:3:8
+   |
+LL | struct Bar<'a>(&'a ());
+   |        ^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/generics/generic-impl-less-params-with-defaults.rs b/src/test/ui/generics/generic-impl-less-params-with-defaults.rs
index abbf6405820..01964f652ee 100644
--- a/src/test/ui/generics/generic-impl-less-params-with-defaults.rs
+++ b/src/test/ui/generics/generic-impl-less-params-with-defaults.rs
@@ -9,5 +9,5 @@ impl<A, B, C> Foo<A, B, C> {
 
 fn main() {
     Foo::<isize>::new();
-    //~^ ERROR wrong number of type arguments
+    //~^ ERROR this struct takes at least 2 type arguments but only 1 type argument was supplied
 }
diff --git a/src/test/ui/generics/generic-impl-less-params-with-defaults.stderr b/src/test/ui/generics/generic-impl-less-params-with-defaults.stderr
index 22b00e1dea4..a8a17876ee0 100644
--- a/src/test/ui/generics/generic-impl-less-params-with-defaults.stderr
+++ b/src/test/ui/generics/generic-impl-less-params-with-defaults.stderr
@@ -1,8 +1,20 @@
-error[E0107]: wrong number of type arguments: expected at least 2, found 1
+error[E0107]: this struct takes at least 2 type arguments but only 1 type argument was supplied
   --> $DIR/generic-impl-less-params-with-defaults.rs:11:5
    |
 LL |     Foo::<isize>::new();
-   |     ^^^^^^^^^^^^^^^^^ expected at least 2 type arguments
+   |     ^^^   ----- supplied 1 type argument
+   |     |
+   |     expected at least 2 type arguments
+   |
+note: struct defined here, with at least 2 type parameters: `A`, `B`
+  --> $DIR/generic-impl-less-params-with-defaults.rs:3:8
+   |
+LL | struct Foo<A, B, C = (A, B)>(
+   |        ^^^ -  -
+help: add missing type argument
+   |
+LL |     Foo::<isize, B>::new();
+   |                ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generics/generic-impl-more-params-with-defaults.rs b/src/test/ui/generics/generic-impl-more-params-with-defaults.rs
index a14fb7064c9..24c41a9088b 100644
--- a/src/test/ui/generics/generic-impl-more-params-with-defaults.rs
+++ b/src/test/ui/generics/generic-impl-more-params-with-defaults.rs
@@ -11,5 +11,5 @@ impl<T, A> Vec<T, A> {
 
 fn main() {
     Vec::<isize, Heap, bool>::new();
-    //~^ ERROR wrong number of type arguments
+    //~^ ERROR this struct takes at most 2 type arguments but 3 type arguments were supplied
 }
diff --git a/src/test/ui/generics/generic-impl-more-params-with-defaults.stderr b/src/test/ui/generics/generic-impl-more-params-with-defaults.stderr
index 380e9209e6c..8ba86afe91e 100644
--- a/src/test/ui/generics/generic-impl-more-params-with-defaults.stderr
+++ b/src/test/ui/generics/generic-impl-more-params-with-defaults.stderr
@@ -1,8 +1,16 @@
-error[E0107]: wrong number of type arguments: expected at most 2, found 3
-  --> $DIR/generic-impl-more-params-with-defaults.rs:13:24
+error[E0107]: this struct takes at most 2 type arguments but 3 type arguments were supplied
+  --> $DIR/generic-impl-more-params-with-defaults.rs:13:5
    |
 LL |     Vec::<isize, Heap, bool>::new();
-   |                        ^^^^ unexpected type argument
+   |     ^^^              ------ help: remove this type argument
+   |     |
+   |     expected at most 2 type arguments
+   |
+note: struct defined here, with at most 2 type parameters: `T`, `A`
+  --> $DIR/generic-impl-more-params-with-defaults.rs:5:8
+   |
+LL | struct Vec<T, A = Heap>(
+   |        ^^^ -  -
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generics/generic-type-less-params-with-defaults.rs b/src/test/ui/generics/generic-type-less-params-with-defaults.rs
index 3aa03392ff2..6b877ab8aee 100644
--- a/src/test/ui/generics/generic-type-less-params-with-defaults.rs
+++ b/src/test/ui/generics/generic-type-less-params-with-defaults.rs
@@ -7,5 +7,5 @@ struct Vec<T, A = Heap>(
 
 fn main() {
     let _: Vec;
-    //~^ ERROR wrong number of type arguments: expected at least 1, found 0 [E0107]
+    //~^ ERROR missing generics for struct `Vec`
 }
diff --git a/src/test/ui/generics/generic-type-less-params-with-defaults.stderr b/src/test/ui/generics/generic-type-less-params-with-defaults.stderr
index a4cc8325a04..93f7a24d877 100644
--- a/src/test/ui/generics/generic-type-less-params-with-defaults.stderr
+++ b/src/test/ui/generics/generic-type-less-params-with-defaults.stderr
@@ -1,8 +1,18 @@
-error[E0107]: wrong number of type arguments: expected at least 1, found 0
+error[E0107]: missing generics for struct `Vec`
   --> $DIR/generic-type-less-params-with-defaults.rs:9:12
    |
 LL |     let _: Vec;
    |            ^^^ expected at least 1 type argument
+   |
+note: struct defined here, with at least 1 type parameter: `T`
+  --> $DIR/generic-type-less-params-with-defaults.rs:5:8
+   |
+LL | struct Vec<T, A = Heap>(
+   |        ^^^ -
+help: use angle brackets to add missing type argument
+   |
+LL |     let _: Vec<T>;
+   |               ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generics/generic-type-more-params-with-defaults.rs b/src/test/ui/generics/generic-type-more-params-with-defaults.rs
index 2713f088dcb..c421774ebba 100644
--- a/src/test/ui/generics/generic-type-more-params-with-defaults.rs
+++ b/src/test/ui/generics/generic-type-more-params-with-defaults.rs
@@ -7,5 +7,5 @@ struct Vec<T, A = Heap>(
 
 fn main() {
     let _: Vec<isize, Heap, bool>;
-    //~^ ERROR wrong number of type arguments: expected at most 2, found 3 [E0107]
+    //~^ ERROR this struct takes at most 2 type arguments but 3 type arguments were supplied
 }
diff --git a/src/test/ui/generics/generic-type-more-params-with-defaults.stderr b/src/test/ui/generics/generic-type-more-params-with-defaults.stderr
index cc296b5105a..e331481390b 100644
--- a/src/test/ui/generics/generic-type-more-params-with-defaults.stderr
+++ b/src/test/ui/generics/generic-type-more-params-with-defaults.stderr
@@ -1,8 +1,16 @@
-error[E0107]: wrong number of type arguments: expected at most 2, found 3
-  --> $DIR/generic-type-more-params-with-defaults.rs:9:29
+error[E0107]: this struct takes at most 2 type arguments but 3 type arguments were supplied
+  --> $DIR/generic-type-more-params-with-defaults.rs:9:12
    |
 LL |     let _: Vec<isize, Heap, bool>;
-   |                             ^^^^ unexpected type argument
+   |            ^^^            ------ help: remove this type argument
+   |            |
+   |            expected at most 2 type arguments
+   |
+note: struct defined here, with at most 2 type parameters: `T`, `A`
+  --> $DIR/generic-type-more-params-with-defaults.rs:5:8
+   |
+LL | struct Vec<T, A = Heap>(
+   |        ^^^ -  -
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generics/wrong-number-of-args.rs b/src/test/ui/generics/wrong-number-of-args.rs
new file mode 100644
index 00000000000..6b99865202e
--- /dev/null
+++ b/src/test/ui/generics/wrong-number-of-args.rs
@@ -0,0 +1,161 @@
+mod no_generics {
+    struct Ty;
+
+    type A = Ty;
+
+    type B = Ty<'static>;
+    //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+    //~| HELP remove these generics
+
+    type C = Ty<'static, usize>;
+    //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+    //~| ERROR this struct takes 0 type arguments but 1 type argument was supplied
+    //~| HELP remove this lifetime argument
+    //~| HELP remove this type argument
+
+    type D = Ty<'static, usize, { 0 }>;
+    //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+    //~| ERROR this struct takes 0 generic arguments but 2 generic arguments were supplied
+    //~| HELP remove this lifetime argument
+    //~| HELP remove these generic arguments
+}
+
+mod type_and_type {
+    struct Ty<A, B>;
+
+    type A = Ty;
+    //~^ ERROR missing generics for struct `type_and_type::Ty`
+    //~| HELP use angle brackets
+
+    type B = Ty<usize>;
+    //~^ ERROR this struct takes 2 type arguments but only 1 type argument was supplied
+    //~| HELP add missing type argument
+
+    type C = Ty<usize, String>;
+
+    type D = Ty<usize, String, char>;
+    //~^ ERROR this struct takes 2 type arguments but 3 type arguments were supplied
+    //~| HELP remove this type argument
+}
+
+mod lifetime_and_type {
+    struct Ty<'a, T>;
+
+    type A = Ty;
+    //~^ ERROR missing generics for struct `lifetime_and_type::Ty`
+    //~| ERROR missing lifetime specifier
+    //~| HELP consider introducing
+    //~| HELP use angle brackets
+
+    type B = Ty<'static>;
+    //~^ ERROR this struct takes 1 type argument but 0 type arguments were supplied
+    //~| HELP add missing type argument
+
+    type C = Ty<usize>;
+    //~^ ERROR missing lifetime specifier
+    //~| HELP consider introducing
+
+    type D = Ty<'static, usize>;
+}
+
+mod type_and_type_and_type {
+    struct Ty<A, B, C = &'static str>;
+
+    type A = Ty;
+    //~^ ERROR missing generics for struct `type_and_type_and_type::Ty`
+    //~| HELP use angle brackets
+
+    type B = Ty<usize>;
+    //~^ ERROR this struct takes at least 2 type arguments but only 1 type argument was supplied
+    //~| HELP add missing type argument
+
+    type C = Ty<usize, String>;
+
+    type D = Ty<usize, String, char>;
+
+    type E = Ty<usize, String, char, f64>;
+    //~^ ERROR this struct takes at most 3 type arguments but 4 type arguments were supplied
+    //~| HELP remove
+}
+
+// Traits have an implicit `Self` type - these tests ensure we don't accidentally return it
+// somewhere in the message
+mod r#trait {
+    trait NonGeneric {
+        //
+    }
+
+    trait GenericLifetime<'a> {
+        //
+    }
+
+    trait GenericType<A> {
+        //
+    }
+
+    type A = Box<dyn NonGeneric<usize>>;
+    //~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
+    //~| HELP remove
+
+    type B = Box<dyn GenericLifetime>;
+    //~^ ERROR missing lifetime specifier
+    //~| HELP consider introducing
+
+    type C = Box<dyn GenericLifetime<'static, 'static>>;
+    //~^ ERROR this trait takes 1 lifetime argument but 2 lifetime arguments were supplied
+    //~| HELP remove
+
+    type D = Box<dyn GenericType>;
+    //~^ ERROR missing generics for trait `GenericType`
+    //~| HELP use angle brackets
+
+    type E = Box<dyn GenericType<String, usize>>;
+    //~^ ERROR this trait takes 1 type argument but 2 type arguments were supplied
+    //~| HELP remove
+}
+
+mod stdlib {
+    mod hash_map {
+        use std::collections::HashMap;
+
+        type A = HashMap;
+        //~^ ERROR missing generics for struct `HashMap`
+        //~| HELP use angle brackets
+
+        type B = HashMap<String>;
+        //~^ ERROR this struct takes at least 2 type arguments but only 1 type argument was supplied
+        //~| HELP add missing type argument
+
+        type C = HashMap<'static>;
+        //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+        //~| HELP remove these generics
+        //~| ERROR this struct takes at least 2 type arguments but 0 type arguments were supplied
+        //~| HELP add missing type arguments
+
+        type D = HashMap<usize, String, char, f64>;
+        //~^ ERROR this struct takes at most 3 type arguments but 4 type arguments were supplied
+        //~| HELP remove this type argument
+    }
+
+    mod result {
+        type A = Result;
+        //~^ ERROR missing generics for enum `std::result::Result`
+        //~| HELP use angle brackets
+
+        type B = Result<String>;
+        //~^ ERROR this enum takes 2 type arguments but only 1 type argument was supplied
+        //~| HELP add missing type argument
+
+        type C = Result<'static>;
+        //~^ ERROR this enum takes 0 lifetime arguments but 1 lifetime argument was supplied
+        //~| HELP remove these generics
+        //~| ERROR this enum takes 2 type arguments but 0 type arguments were supplied
+        //~| HELP add missing type arguments
+
+        type D = Result<usize, String, char>;
+        //~^ ERROR this enum takes 2 type arguments but 3 type arguments were supplied
+        //~| HELP remove
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/generics/wrong-number-of-args.stderr b/src/test/ui/generics/wrong-number-of-args.stderr
new file mode 100644
index 00000000000..2a34fba2c48
--- /dev/null
+++ b/src/test/ui/generics/wrong-number-of-args.stderr
@@ -0,0 +1,449 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/wrong-number-of-args.rs:44:14
+   |
+LL |     type A = Ty;
+   |              ^^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |     type A<'a> = Ty<'a>;
+   |           ^^^^   ^^^^^^
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/wrong-number-of-args.rs:54:17
+   |
+LL |     type C = Ty<usize>;
+   |                 ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |     type C<'a> = Ty<'a, usize>;
+   |           ^^^^      ^^^
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/wrong-number-of-args.rs:100:22
+   |
+LL |     type B = Box<dyn GenericLifetime>;
+   |                      ^^^^^^^^^^^^^^^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |     type B<'a> = Box<dyn GenericLifetime<'a>>;
+   |           ^^^^           ^^^^^^^^^^^^^^^^^^^
+
+error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/wrong-number-of-args.rs:6:14
+   |
+LL |     type B = Ty<'static>;
+   |              ^^--------- help: remove these generics
+   |              |
+   |              expected 0 lifetime arguments
+   |
+note: struct defined here, with 0 lifetime parameters
+  --> $DIR/wrong-number-of-args.rs:2:12
+   |
+LL |     struct Ty;
+   |            ^^
+
+error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/wrong-number-of-args.rs:10:14
+   |
+LL |     type C = Ty<'static, usize>;
+   |              ^^ --------- help: remove this lifetime argument
+   |              |
+   |              expected 0 lifetime arguments
+   |
+note: struct defined here, with 0 lifetime parameters
+  --> $DIR/wrong-number-of-args.rs:2:12
+   |
+LL |     struct Ty;
+   |            ^^
+
+error[E0107]: this struct takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/wrong-number-of-args.rs:10:14
+   |
+LL |     type C = Ty<'static, usize>;
+   |              ^^        ------- help: remove this type argument
+   |              |
+   |              expected 0 type arguments
+   |
+note: struct defined here, with 0 type parameters
+  --> $DIR/wrong-number-of-args.rs:2:12
+   |
+LL |     struct Ty;
+   |            ^^
+
+error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/wrong-number-of-args.rs:16:14
+   |
+LL |     type D = Ty<'static, usize, { 0 }>;
+   |              ^^ --------- help: remove this lifetime argument
+   |              |
+   |              expected 0 lifetime arguments
+   |
+note: struct defined here, with 0 lifetime parameters
+  --> $DIR/wrong-number-of-args.rs:2:12
+   |
+LL |     struct Ty;
+   |            ^^
+
+error[E0107]: this struct takes 0 generic arguments but 2 generic arguments were supplied
+  --> $DIR/wrong-number-of-args.rs:16:14
+   |
+LL |     type D = Ty<'static, usize, { 0 }>;
+   |              ^^        -------------- help: remove these generic arguments
+   |              |
+   |              expected 0 generic arguments
+   |
+note: struct defined here, with 0 generic parameters
+  --> $DIR/wrong-number-of-args.rs:2:12
+   |
+LL |     struct Ty;
+   |            ^^
+
+error[E0107]: missing generics for struct `type_and_type::Ty`
+  --> $DIR/wrong-number-of-args.rs:26:14
+   |
+LL |     type A = Ty;
+   |              ^^ expected 2 type arguments
+   |
+note: struct defined here, with 2 type parameters: `A`, `B`
+  --> $DIR/wrong-number-of-args.rs:24:12
+   |
+LL |     struct Ty<A, B>;
+   |            ^^ -  -
+help: use angle brackets to add missing type arguments
+   |
+LL |     type A = Ty<A, B>;
+   |                ^^^^^^
+
+error[E0107]: this struct takes 2 type arguments but only 1 type argument was supplied
+  --> $DIR/wrong-number-of-args.rs:30:14
+   |
+LL |     type B = Ty<usize>;
+   |              ^^ ----- supplied 1 type argument
+   |              |
+   |              expected 2 type arguments
+   |
+note: struct defined here, with 2 type parameters: `A`, `B`
+  --> $DIR/wrong-number-of-args.rs:24:12
+   |
+LL |     struct Ty<A, B>;
+   |            ^^ -  -
+help: add missing type argument
+   |
+LL |     type B = Ty<usize, B>;
+   |                      ^^^
+
+error[E0107]: this struct takes 2 type arguments but 3 type arguments were supplied
+  --> $DIR/wrong-number-of-args.rs:36:14
+   |
+LL |     type D = Ty<usize, String, char>;
+   |              ^^              ------ help: remove this type argument
+   |              |
+   |              expected 2 type arguments
+   |
+note: struct defined here, with 2 type parameters: `A`, `B`
+  --> $DIR/wrong-number-of-args.rs:24:12
+   |
+LL |     struct Ty<A, B>;
+   |            ^^ -  -
+
+error[E0107]: missing generics for struct `lifetime_and_type::Ty`
+  --> $DIR/wrong-number-of-args.rs:44:14
+   |
+LL |     type A = Ty;
+   |              ^^ expected 1 type argument
+   |
+note: struct defined here, with 1 type parameter: `T`
+  --> $DIR/wrong-number-of-args.rs:42:12
+   |
+LL |     struct Ty<'a, T>;
+   |            ^^     -
+help: use angle brackets to add missing type argument
+   |
+LL |     type A = Ty<T>;
+   |                ^^^
+
+error[E0107]: this struct takes 1 type argument but 0 type arguments were supplied
+  --> $DIR/wrong-number-of-args.rs:50:14
+   |
+LL |     type B = Ty<'static>;
+   |              ^^ expected 1 type argument
+   |
+note: struct defined here, with 1 type parameter: `T`
+  --> $DIR/wrong-number-of-args.rs:42:12
+   |
+LL |     struct Ty<'a, T>;
+   |            ^^     -
+help: add missing type argument
+   |
+LL |     type B = Ty<'static, T>;
+   |                        ^^^
+
+error[E0107]: missing generics for struct `type_and_type_and_type::Ty`
+  --> $DIR/wrong-number-of-args.rs:64:14
+   |
+LL |     type A = Ty;
+   |              ^^ expected at least 2 type arguments
+   |
+note: struct defined here, with at least 2 type parameters: `A`, `B`
+  --> $DIR/wrong-number-of-args.rs:62:12
+   |
+LL |     struct Ty<A, B, C = &'static str>;
+   |            ^^ -  -
+help: use angle brackets to add missing type arguments
+   |
+LL |     type A = Ty<A, B>;
+   |                ^^^^^^
+
+error[E0107]: this struct takes at least 2 type arguments but only 1 type argument was supplied
+  --> $DIR/wrong-number-of-args.rs:68:14
+   |
+LL |     type B = Ty<usize>;
+   |              ^^ ----- supplied 1 type argument
+   |              |
+   |              expected at least 2 type arguments
+   |
+note: struct defined here, with at least 2 type parameters: `A`, `B`
+  --> $DIR/wrong-number-of-args.rs:62:12
+   |
+LL |     struct Ty<A, B, C = &'static str>;
+   |            ^^ -  -
+help: add missing type argument
+   |
+LL |     type B = Ty<usize, B>;
+   |                      ^^^
+
+error[E0107]: this struct takes at most 3 type arguments but 4 type arguments were supplied
+  --> $DIR/wrong-number-of-args.rs:76:14
+   |
+LL |     type E = Ty<usize, String, char, f64>;
+   |              ^^                    ----- help: remove this type argument
+   |              |
+   |              expected at most 3 type arguments
+   |
+note: struct defined here, with at most 3 type parameters: `A`, `B`, `C`
+  --> $DIR/wrong-number-of-args.rs:62:12
+   |
+LL |     struct Ty<A, B, C = &'static str>;
+   |            ^^ -  -  -
+
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/wrong-number-of-args.rs:96:22
+   |
+LL |     type A = Box<dyn NonGeneric<usize>>;
+   |                      ^^^^^^^^^^------- help: remove these generics
+   |                      |
+   |                      expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $DIR/wrong-number-of-args.rs:84:11
+   |
+LL |     trait NonGeneric {
+   |           ^^^^^^^^^^
+
+error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied
+  --> $DIR/wrong-number-of-args.rs:104:22
+   |
+LL |     type C = Box<dyn GenericLifetime<'static, 'static>>;
+   |                      ^^^^^^^^^^^^^^^        --------- help: remove this lifetime argument
+   |                      |
+   |                      expected 1 lifetime argument
+   |
+note: trait defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/wrong-number-of-args.rs:88:11
+   |
+LL |     trait GenericLifetime<'a> {
+   |           ^^^^^^^^^^^^^^^ --
+
+error[E0107]: missing generics for trait `GenericType`
+  --> $DIR/wrong-number-of-args.rs:108:22
+   |
+LL |     type D = Box<dyn GenericType>;
+   |                      ^^^^^^^^^^^ expected 1 type argument
+   |
+note: trait defined here, with 1 type parameter: `A`
+  --> $DIR/wrong-number-of-args.rs:92:11
+   |
+LL |     trait GenericType<A> {
+   |           ^^^^^^^^^^^ -
+help: use angle brackets to add missing type argument
+   |
+LL |     type D = Box<dyn GenericType<A>>;
+   |                                 ^^^
+
+error[E0107]: this trait takes 1 type argument but 2 type arguments were supplied
+  --> $DIR/wrong-number-of-args.rs:112:22
+   |
+LL |     type E = Box<dyn GenericType<String, usize>>;
+   |                      ^^^^^^^^^^^       ------- help: remove this type argument
+   |                      |
+   |                      expected 1 type argument
+   |
+note: trait defined here, with 1 type parameter: `A`
+  --> $DIR/wrong-number-of-args.rs:92:11
+   |
+LL |     trait GenericType<A> {
+   |           ^^^^^^^^^^^ -
+
+error[E0107]: missing generics for struct `HashMap`
+  --> $DIR/wrong-number-of-args.rs:121:18
+   |
+LL |         type A = HashMap;
+   |                  ^^^^^^^ expected at least 2 type arguments
+   |
+note: struct defined here, with at least 2 type parameters: `K`, `V`
+  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
+   |
+LL | pub struct HashMap<K, V, S = RandomState> {
+   |            ^^^^^^^ -  -
+help: use angle brackets to add missing type arguments
+   |
+LL |         type A = HashMap<K, V>;
+   |                         ^^^^^^
+
+error[E0107]: this struct takes at least 2 type arguments but only 1 type argument was supplied
+  --> $DIR/wrong-number-of-args.rs:125:18
+   |
+LL |         type B = HashMap<String>;
+   |                  ^^^^^^^ ------ supplied 1 type argument
+   |                  |
+   |                  expected at least 2 type arguments
+   |
+note: struct defined here, with at least 2 type parameters: `K`, `V`
+  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
+   |
+LL | pub struct HashMap<K, V, S = RandomState> {
+   |            ^^^^^^^ -  -
+help: add missing type argument
+   |
+LL |         type B = HashMap<String, V>;
+   |                                ^^^
+
+error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/wrong-number-of-args.rs:129:18
+   |
+LL |         type C = HashMap<'static>;
+   |                  ^^^^^^^--------- help: remove these generics
+   |                  |
+   |                  expected 0 lifetime arguments
+   |
+note: struct defined here, with 0 lifetime parameters
+  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
+   |
+LL | pub struct HashMap<K, V, S = RandomState> {
+   |            ^^^^^^^
+
+error[E0107]: this struct takes at least 2 type arguments but 0 type arguments were supplied
+  --> $DIR/wrong-number-of-args.rs:129:18
+   |
+LL |         type C = HashMap<'static>;
+   |                  ^^^^^^^ expected at least 2 type arguments
+   |
+note: struct defined here, with at least 2 type parameters: `K`, `V`
+  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
+   |
+LL | pub struct HashMap<K, V, S = RandomState> {
+   |            ^^^^^^^ -  -
+help: add missing type arguments
+   |
+LL |         type C = HashMap<'static, K, V>;
+   |                                 ^^^^^^
+
+error[E0107]: this struct takes at most 3 type arguments but 4 type arguments were supplied
+  --> $DIR/wrong-number-of-args.rs:135:18
+   |
+LL |         type D = HashMap<usize, String, char, f64>;
+   |                  ^^^^^^^                    ----- help: remove this type argument
+   |                  |
+   |                  expected at most 3 type arguments
+   |
+note: struct defined here, with at most 3 type parameters: `K`, `V`, `S`
+  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
+   |
+LL | pub struct HashMap<K, V, S = RandomState> {
+   |            ^^^^^^^ -  -  -
+
+error[E0107]: missing generics for enum `std::result::Result`
+  --> $DIR/wrong-number-of-args.rs:141:18
+   |
+LL |         type A = Result;
+   |                  ^^^^^^ expected 2 type arguments
+   |
+note: enum defined here, with 2 type parameters: `T`, `E`
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+   |
+LL | pub enum Result<T, E> {
+   |          ^^^^^^ -  -
+help: use angle brackets to add missing type arguments
+   |
+LL |         type A = Result<T, E>;
+   |                        ^^^^^^
+
+error[E0107]: this enum takes 2 type arguments but only 1 type argument was supplied
+  --> $DIR/wrong-number-of-args.rs:145:18
+   |
+LL |         type B = Result<String>;
+   |                  ^^^^^^ ------ supplied 1 type argument
+   |                  |
+   |                  expected 2 type arguments
+   |
+note: enum defined here, with 2 type parameters: `T`, `E`
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+   |
+LL | pub enum Result<T, E> {
+   |          ^^^^^^ -  -
+help: add missing type argument
+   |
+LL |         type B = Result<String, E>;
+   |                               ^^^
+
+error[E0107]: this enum takes 0 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/wrong-number-of-args.rs:149:18
+   |
+LL |         type C = Result<'static>;
+   |                  ^^^^^^--------- help: remove these generics
+   |                  |
+   |                  expected 0 lifetime arguments
+   |
+note: enum defined here, with 0 lifetime parameters
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+   |
+LL | pub enum Result<T, E> {
+   |          ^^^^^^
+
+error[E0107]: this enum takes 2 type arguments but 0 type arguments were supplied
+  --> $DIR/wrong-number-of-args.rs:149:18
+   |
+LL |         type C = Result<'static>;
+   |                  ^^^^^^ expected 2 type arguments
+   |
+note: enum defined here, with 2 type parameters: `T`, `E`
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+   |
+LL | pub enum Result<T, E> {
+   |          ^^^^^^ -  -
+help: add missing type arguments
+   |
+LL |         type C = Result<'static, T, E>;
+   |                                ^^^^^^
+
+error[E0107]: this enum takes 2 type arguments but 3 type arguments were supplied
+  --> $DIR/wrong-number-of-args.rs:155:18
+   |
+LL |         type D = Result<usize, String, char>;
+   |                  ^^^^^^              ------ help: remove this type argument
+   |                  |
+   |                  expected 2 type arguments
+   |
+note: enum defined here, with 2 type parameters: `T`, `E`
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+   |
+LL | pub enum Result<T, E> {
+   |          ^^^^^^ -  -
+
+error: aborting due to 30 previous errors
+
+Some errors have detailed explanations: E0106, E0107.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/src/test/ui/issues/issue-14092.rs b/src/test/ui/issues/issue-14092.rs
index 3cfaa20a8b5..67c2a42eafb 100644
--- a/src/test/ui/issues/issue-14092.rs
+++ b/src/test/ui/issues/issue-14092.rs
@@ -1,4 +1,4 @@
 fn fn1(0: Box) {}
-        //~^ ERROR wrong number of type arguments: expected at least 1, found 0 [E0107]
+//~^ ERROR missing generics for struct `Box`
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-14092.stderr b/src/test/ui/issues/issue-14092.stderr
index b749c44780d..5cacce751c9 100644
--- a/src/test/ui/issues/issue-14092.stderr
+++ b/src/test/ui/issues/issue-14092.stderr
@@ -1,8 +1,20 @@
-error[E0107]: wrong number of type arguments: expected at least 1, found 0
+error[E0107]: missing generics for struct `Box`
   --> $DIR/issue-14092.rs:1:11
    |
 LL | fn fn1(0: Box) {}
    |           ^^^ expected at least 1 type argument
+   |
+note: struct defined here, with at least 1 type parameter: `T`
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+   |
+LL | pub struct Box<
+   |            ^^^
+LL |     T: ?Sized,
+   |     -
+help: use angle brackets to add missing type argument
+   |
+LL | fn fn1(0: Box<T>) {}
+   |              ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-16939.stderr b/src/test/ui/issues/issue-16939.stderr
index 103f56fa04d..8e4237039fa 100644
--- a/src/test/ui/issues/issue-16939.stderr
+++ b/src/test/ui/issues/issue-16939.stderr
@@ -5,6 +5,12 @@ LL |     |t| f(t);
    |         ^ - supplied 1 argument
    |         |
    |         expected 0 arguments
+   |
+note: associated function defined here
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL |     extern "rust-call" fn call(&self, args: Args) -> Self::Output;
+   |                           ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-18423.rs b/src/test/ui/issues/issue-18423.rs
index c072e6b5d22..a81b32f050c 100644
--- a/src/test/ui/issues/issue-18423.rs
+++ b/src/test/ui/issues/issue-18423.rs
@@ -1,8 +1,8 @@
 // Test that `Box` cannot be used with a lifetime argument.
 
 struct Foo<'a> {
-    x: Box<'a, isize> //~ ERROR wrong number of lifetime arguments
+    x: Box<'a, isize>
+    //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
 }
 
-pub fn main() {
-}
+fn main() { }
diff --git a/src/test/ui/issues/issue-18423.stderr b/src/test/ui/issues/issue-18423.stderr
index 141fd27be36..f9006235234 100644
--- a/src/test/ui/issues/issue-18423.stderr
+++ b/src/test/ui/issues/issue-18423.stderr
@@ -1,8 +1,16 @@
-error[E0107]: wrong number of lifetime arguments: expected 0, found 1
-  --> $DIR/issue-18423.rs:4:12
+error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/issue-18423.rs:4:8
    |
 LL |     x: Box<'a, isize>
-   |            ^^ unexpected lifetime argument
+   |        ^^^ ---- help: remove this lifetime argument
+   |        |
+   |        expected 0 lifetime arguments
+   |
+note: struct defined here, with 0 lifetime parameters
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+   |
+LL | pub struct Box<
+   |            ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-23024.rs b/src/test/ui/issues/issue-23024.rs
index ddeb516a4b0..e92273bd409 100644
--- a/src/test/ui/issues/issue-23024.rs
+++ b/src/test/ui/issues/issue-23024.rs
@@ -8,6 +8,6 @@ fn main()
     vfnfer.push(box h);
     println!("{:?}",(vfnfer[0] as dyn Fn)(3));
     //~^ ERROR the precise format of `Fn`-family traits'
-    //~| ERROR wrong number of type arguments: expected 1, found 0 [E0107]
+    //~| ERROR missing generics for trait `Fn`
     //~| ERROR the value of the associated type `Output` (from trait `FnOnce`)
 }
diff --git a/src/test/ui/issues/issue-23024.stderr b/src/test/ui/issues/issue-23024.stderr
index fdb68ff7126..1b876090ad6 100644
--- a/src/test/ui/issues/issue-23024.stderr
+++ b/src/test/ui/issues/issue-23024.stderr
@@ -7,11 +7,21 @@ LL |     println!("{:?}",(vfnfer[0] as dyn Fn)(3));
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
-error[E0107]: wrong number of type arguments: expected 1, found 0
+error[E0107]: missing generics for trait `Fn`
   --> $DIR/issue-23024.rs:9:39
    |
 LL |     println!("{:?}",(vfnfer[0] as dyn Fn)(3));
    |                                       ^^ expected 1 type argument
+   |
+note: trait defined here, with 1 type parameter: `Args`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL | pub trait Fn<Args>: FnMut<Args> {
+   |           ^^ ----
+help: use angle brackets to add missing type argument
+   |
+LL |     println!("{:?}",(vfnfer[0] as dyn Fn<Args>)(3));
+   |                                         ^^^^^^
 
 error[E0191]: the value of the associated type `Output` (from trait `FnOnce`) must be specified
   --> $DIR/issue-23024.rs:9:39
diff --git a/src/test/ui/issues/issue-3044.stderr b/src/test/ui/issues/issue-3044.stderr
index d2c010659ed..b93aeade95e 100644
--- a/src/test/ui/issues/issue-3044.stderr
+++ b/src/test/ui/issues/issue-3044.stderr
@@ -7,6 +7,12 @@ LL |       needlesArr.iter().fold(|x, y| {
    | |                       expected 2 arguments
 LL | |     });
    | |_____- supplied 1 argument
+   |
+note: associated function defined here
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   |
+LL |     fn fold<B, F>(mut self, init: B, mut f: F) -> B
+   |        ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-3214.rs b/src/test/ui/issues/issue-3214.rs
index 030677c879f..9bb164f1ddd 100644
--- a/src/test/ui/issues/issue-3214.rs
+++ b/src/test/ui/issues/issue-3214.rs
@@ -6,7 +6,7 @@ fn foo<T>() {
     }
 
     impl<T> Drop for Foo<T> {
-        //~^ ERROR wrong number of type arguments
+        //~^ ERROR this struct takes 0 type arguments but 1 type argument was supplied
         //~| ERROR the type parameter `T` is not constrained by the impl trait, self type, or predicates
         fn drop(&mut self) {}
     }
diff --git a/src/test/ui/issues/issue-3214.stderr b/src/test/ui/issues/issue-3214.stderr
index 30bc6cb115f..c2268924bc4 100644
--- a/src/test/ui/issues/issue-3214.stderr
+++ b/src/test/ui/issues/issue-3214.stderr
@@ -9,11 +9,19 @@ LL |     struct Foo {
 LL |         x: T,
    |            ^ use of generic parameter from outer function
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/issue-3214.rs:8:26
+error[E0107]: this struct takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/issue-3214.rs:8:22
    |
 LL |     impl<T> Drop for Foo<T> {
-   |                          ^ unexpected type argument
+   |                      ^^^--- help: remove these generics
+   |                      |
+   |                      expected 0 type arguments
+   |
+note: struct defined here, with 0 type parameters
+  --> $DIR/issue-3214.rs:4:12
+   |
+LL |     struct Foo {
+   |            ^^^
 
 error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
   --> $DIR/issue-3214.rs:8:10
diff --git a/src/test/ui/issues/issue-53251.rs b/src/test/ui/issues/issue-53251.rs
index b5d55141b75..309b9800b7d 100644
--- a/src/test/ui/issues/issue-53251.rs
+++ b/src/test/ui/issues/issue-53251.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-linelength
+
 struct S;
 
 impl S {
@@ -9,8 +11,8 @@ macro_rules! impl_add {
         $(
             fn $n() {
                 S::f::<i64>();
-                //~^ ERROR wrong number of type arguments
-                //~| ERROR wrong number of type arguments
+                //~^ ERROR this associated function takes 0 type arguments but 1 type argument was supplied
+                //~| ERROR this associated function takes 0 type arguments but 1 type argument was supplied
             }
         )*
     }
@@ -18,4 +20,4 @@ macro_rules! impl_add {
 
 impl_add!(a b);
 
-fn main() {}
+fn main() { }
diff --git a/src/test/ui/issues/issue-53251.stderr b/src/test/ui/issues/issue-53251.stderr
index cd5030f7619..5d1a6d4a522 100644
--- a/src/test/ui/issues/issue-53251.stderr
+++ b/src/test/ui/issues/issue-53251.stderr
@@ -1,23 +1,37 @@
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/issue-53251.rs:11:24
+error[E0107]: this associated function takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/issue-53251.rs:13:20
    |
 LL |                 S::f::<i64>();
-   |                        ^^^ unexpected type argument
+   |                    ^------- help: remove these generics
+   |                    |
+   |                    expected 0 type arguments
 ...
 LL | impl_add!(a b);
    | --------------- in this macro invocation
    |
+note: associated function defined here, with 0 type parameters
+  --> $DIR/issue-53251.rs:6:8
+   |
+LL |     fn f() {}
+   |        ^
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/issue-53251.rs:11:24
+error[E0107]: this associated function takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/issue-53251.rs:13:20
    |
 LL |                 S::f::<i64>();
-   |                        ^^^ unexpected type argument
+   |                    ^------- help: remove these generics
+   |                    |
+   |                    expected 0 type arguments
 ...
 LL | impl_add!(a b);
    | --------------- in this macro invocation
    |
+note: associated function defined here, with 0 type parameters
+  --> $DIR/issue-53251.rs:6:8
+   |
+LL |     fn f() {}
+   |        ^
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/issues/issue-60622.rs b/src/test/ui/issues/issue-60622.rs
index d6a0189c3e0..1d9bd2dd2dc 100644
--- a/src/test/ui/issues/issue-60622.rs
+++ b/src/test/ui/issues/issue-60622.rs
@@ -11,8 +11,8 @@ impl Borked {
 fn run_wild<T>(b: &Borked) {
     b.a::<'_, T>();
     //~^ ERROR cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-    //~^^ ERROR wrong number of type arguments: expected 0, found 1
-    //~^^^ WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+    //~| ERROR this associated function takes 0 type arguments but 1 type argument was supplied
+    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-60622.stderr b/src/test/ui/issues/issue-60622.stderr
index 79cb6cfc354..47f2f181f2d 100644
--- a/src/test/ui/issues/issue-60622.stderr
+++ b/src/test/ui/issues/issue-60622.stderr
@@ -16,11 +16,19 @@ LL | #![deny(warnings)]
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/issue-60622.rs:12:15
+error[E0107]: this associated function takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/issue-60622.rs:12:7
    |
 LL |     b.a::<'_, T>();
-   |               ^ unexpected type argument
+   |       ^     --- help: remove this type argument
+   |       |
+   |       expected 0 type arguments
+   |
+note: associated function defined here, with 0 type parameters
+  --> $DIR/issue-60622.rs:8:8
+   |
+LL |     fn a(&self) {}
+   |        ^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/methods/method-call-lifetime-args-fail.rs b/src/test/ui/methods/method-call-lifetime-args-fail.rs
index 938a7f5575e..8a840ba62cc 100644
--- a/src/test/ui/methods/method-call-lifetime-args-fail.rs
+++ b/src/test/ui/methods/method-call-lifetime-args-fail.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-linelength
+
 struct S;
 
 impl S {
@@ -14,9 +16,9 @@ impl S {
 fn method_call() {
     S.early(); // OK
     S.early::<'static>();
-    //~^ ERROR wrong number of lifetime arguments: expected 2, found 1
+    //~^ ERROR this associated function takes 2 lifetime arguments but only 1 lifetime argument was supplied
     S.early::<'static, 'static, 'static>();
-    //~^ ERROR wrong number of lifetime arguments: expected 2, found 3
+    //~^ ERROR this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied
     let _: &u8 = S.life_and_type::<'static>();
     S.life_and_type::<u8>();
     S.life_and_type::<'static, u8>();
@@ -61,9 +63,9 @@ fn ufcs() {
 
     S::early(S); // OK
     S::early::<'static>(S);
-    //~^ ERROR wrong number of lifetime arguments: expected 2, found 1
+    //~^ ERROR this associated function takes 2 lifetime arguments but only 1 lifetime argument was supplied
     S::early::<'static, 'static, 'static>(S);
-    //~^ ERROR wrong number of lifetime arguments: expected 2, found 3
+    //~^ ERROR this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied
     let _: &u8 = S::life_and_type::<'static>(S);
     S::life_and_type::<u8>(S);
     S::life_and_type::<'static, u8>(S);
diff --git a/src/test/ui/methods/method-call-lifetime-args-fail.stderr b/src/test/ui/methods/method-call-lifetime-args-fail.stderr
index 74dab5f4400..34a2e3dec2e 100644
--- a/src/test/ui/methods/method-call-lifetime-args-fail.stderr
+++ b/src/test/ui/methods/method-call-lifetime-args-fail.stderr
@@ -1,194 +1,234 @@
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
-  --> $DIR/method-call-lifetime-args-fail.rs:16:7
+error[E0107]: this associated function takes 2 lifetime arguments but only 1 lifetime argument was supplied
+  --> $DIR/method-call-lifetime-args-fail.rs:18:7
    |
 LL |     S.early::<'static>();
-   |       ^^^^^ expected 2 lifetime arguments
+   |       ^^^^^   ------- supplied 1 lifetime argument
+   |       |
+   |       expected 2 lifetime arguments
+   |
+note: associated function defined here, with 2 lifetime parameters: `'a`, `'b`
+  --> $DIR/method-call-lifetime-args-fail.rs:8:8
+   |
+LL |     fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
+   |        ^^^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     S.early::<'static, 'b>();
+   |                      ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 3
-  --> $DIR/method-call-lifetime-args-fail.rs:18:33
+error[E0107]: this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied
+  --> $DIR/method-call-lifetime-args-fail.rs:20:7
    |
 LL |     S.early::<'static, 'static, 'static>();
-   |                                 ^^^^^^^ unexpected lifetime argument
+   |       ^^^^^                   --------- help: remove this lifetime argument
+   |       |
+   |       expected 2 lifetime arguments
+   |
+note: associated function defined here, with 2 lifetime parameters: `'a`, `'b`
+  --> $DIR/method-call-lifetime-args-fail.rs:8:8
+   |
+LL |     fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
+   |        ^^^^^ --  --
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:27:15
+  --> $DIR/method-call-lifetime-args-fail.rs:29:15
    |
 LL |     S::late::<'static>(S, &0, &0);
    |               ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:4:13
+  --> $DIR/method-call-lifetime-args-fail.rs:6:13
    |
 LL |     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
    |             ^^
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:29:15
+  --> $DIR/method-call-lifetime-args-fail.rs:31:15
    |
 LL |     S::late::<'static, 'static>(S, &0, &0);
    |               ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:4:13
+  --> $DIR/method-call-lifetime-args-fail.rs:6:13
    |
 LL |     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
    |             ^^
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:31:15
+  --> $DIR/method-call-lifetime-args-fail.rs:33:15
    |
 LL |     S::late::<'static, 'static, 'static>(S, &0, &0);
    |               ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:4:13
+  --> $DIR/method-call-lifetime-args-fail.rs:6:13
    |
 LL |     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
    |             ^^
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:34:21
+  --> $DIR/method-call-lifetime-args-fail.rs:36:21
    |
 LL |     S::late_early::<'static, 'static>(S, &0);
    |                     ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:7:19
+  --> $DIR/method-call-lifetime-args-fail.rs:9:19
    |
 LL |     fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
    |                   ^^
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:36:21
+  --> $DIR/method-call-lifetime-args-fail.rs:38:21
    |
 LL |     S::late_early::<'static, 'static, 'static>(S, &0);
    |                     ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:7:19
+  --> $DIR/method-call-lifetime-args-fail.rs:9:19
    |
 LL |     fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
    |                   ^^
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:40:24
+  --> $DIR/method-call-lifetime-args-fail.rs:42:24
    |
 LL |     S::late_implicit::<'static>(S, &0, &0);
    |                        ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:5:31
+  --> $DIR/method-call-lifetime-args-fail.rs:7:31
    |
 LL |     fn late_implicit(self, _: &u8, _: &u8) {}
    |                               ^
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:42:24
+  --> $DIR/method-call-lifetime-args-fail.rs:44:24
    |
 LL |     S::late_implicit::<'static, 'static>(S, &0, &0);
    |                        ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:5:31
+  --> $DIR/method-call-lifetime-args-fail.rs:7:31
    |
 LL |     fn late_implicit(self, _: &u8, _: &u8) {}
    |                               ^
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:44:24
+  --> $DIR/method-call-lifetime-args-fail.rs:46:24
    |
 LL |     S::late_implicit::<'static, 'static, 'static>(S, &0, &0);
    |                        ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:5:31
+  --> $DIR/method-call-lifetime-args-fail.rs:7:31
    |
 LL |     fn late_implicit(self, _: &u8, _: &u8) {}
    |                               ^
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:47:30
+  --> $DIR/method-call-lifetime-args-fail.rs:49:30
    |
 LL |     S::late_implicit_early::<'static, 'static>(S, &0);
    |                              ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:8:41
+  --> $DIR/method-call-lifetime-args-fail.rs:10:41
    |
 LL |     fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
    |                                         ^
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:49:30
+  --> $DIR/method-call-lifetime-args-fail.rs:51:30
    |
 LL |     S::late_implicit_early::<'static, 'static, 'static>(S, &0);
    |                              ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:8:41
+  --> $DIR/method-call-lifetime-args-fail.rs:10:41
    |
 LL |     fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
    |                                         ^
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:52:35
+  --> $DIR/method-call-lifetime-args-fail.rs:54:35
    |
 LL |     S::late_implicit_self_early::<'static, 'static>(&S);
    |                                   ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:9:37
+  --> $DIR/method-call-lifetime-args-fail.rs:11:37
    |
 LL |     fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} }
    |                                     ^
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:54:35
+  --> $DIR/method-call-lifetime-args-fail.rs:56:35
    |
 LL |     S::late_implicit_self_early::<'static, 'static, 'static>(&S);
    |                                   ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:9:37
+  --> $DIR/method-call-lifetime-args-fail.rs:11:37
    |
 LL |     fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} }
    |                                     ^
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:57:28
+  --> $DIR/method-call-lifetime-args-fail.rs:59:28
    |
 LL |     S::late_unused_early::<'static, 'static>(S);
    |                            ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:10:26
+  --> $DIR/method-call-lifetime-args-fail.rs:12:26
    |
 LL |     fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} }
    |                          ^^
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:59:28
+  --> $DIR/method-call-lifetime-args-fail.rs:61:28
    |
 LL |     S::late_unused_early::<'static, 'static, 'static>(S);
    |                            ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:10:26
+  --> $DIR/method-call-lifetime-args-fail.rs:12:26
    |
 LL |     fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} }
    |                          ^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
-  --> $DIR/method-call-lifetime-args-fail.rs:63:5
+error[E0107]: this associated function takes 2 lifetime arguments but only 1 lifetime argument was supplied
+  --> $DIR/method-call-lifetime-args-fail.rs:65:8
    |
 LL |     S::early::<'static>(S);
-   |     ^^^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
+   |        ^^^^^   ------- supplied 1 lifetime argument
+   |        |
+   |        expected 2 lifetime arguments
+   |
+note: associated function defined here, with 2 lifetime parameters: `'a`, `'b`
+  --> $DIR/method-call-lifetime-args-fail.rs:8:8
+   |
+LL |     fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
+   |        ^^^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     S::early::<'static, 'b>(S);
+   |                       ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 3
-  --> $DIR/method-call-lifetime-args-fail.rs:65:34
+error[E0107]: this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied
+  --> $DIR/method-call-lifetime-args-fail.rs:67:8
    |
 LL |     S::early::<'static, 'static, 'static>(S);
-   |                                  ^^^^^^^ unexpected lifetime argument
+   |        ^^^^^                   --------- help: remove this lifetime argument
+   |        |
+   |        expected 2 lifetime arguments
+   |
+note: associated function defined here, with 2 lifetime parameters: `'a`, `'b`
+  --> $DIR/method-call-lifetime-args-fail.rs:8:8
+   |
+LL |     fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
+   |        ^^^^^ --  --
 
 error: aborting due to 18 previous errors
 
diff --git a/src/test/ui/mismatched_types/overloaded-calls-bad.stderr b/src/test/ui/mismatched_types/overloaded-calls-bad.stderr
index 706e25529bf..264d7cbb9b1 100644
--- a/src/test/ui/mismatched_types/overloaded-calls-bad.stderr
+++ b/src/test/ui/mismatched_types/overloaded-calls-bad.stderr
@@ -11,6 +11,12 @@ LL |     let ans = s();
    |               ^-- supplied 0 arguments
    |               |
    |               expected 1 argument
+   |
+note: associated function defined here
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL |     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
+   |                           ^^^^^^^^
 
 error[E0057]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/overloaded-calls-bad.rs:31:15
@@ -19,6 +25,12 @@ LL |     let ans = s("burma", "shave");
    |               ^ -------  ------- supplied 2 arguments
    |               |
    |               expected 1 argument
+   |
+note: associated function defined here
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL |     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
+   |                           ^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/resolve/resolve-primitive-fallback.stderr b/src/test/ui/resolve/resolve-primitive-fallback.stderr
index 8611306e82d..5af0aefe22b 100644
--- a/src/test/ui/resolve/resolve-primitive-fallback.stderr
+++ b/src/test/ui/resolve/resolve-primitive-fallback.stderr
@@ -22,6 +22,12 @@ LL |     std::mem::size_of(u16);
    |     ^^^^^^^^^^^^^^^^^ --- supplied 1 argument
    |     |
    |     expected 0 arguments
+   |
+note: function defined here
+  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+   |
+LL | pub const fn size_of<T>() -> usize {
+   |              ^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/seq-args.rs b/src/test/ui/seq-args.rs
index 9bb9f12f64c..9a3c495602a 100644
--- a/src/test/ui/seq-args.rs
+++ b/src/test/ui/seq-args.rs
@@ -1,11 +1,13 @@
 fn main() {
-trait Seq { }
+    trait Seq { }
 
-impl<T> Seq<T> for Vec<T> { //~ ERROR wrong number of type arguments
-    /* ... */
-}
-impl Seq<bool> for u32 { //~ ERROR wrong number of type arguments
-   /* Treat the integer as a sequence of bits */
-}
+    impl<T> Seq<T> for Vec<T> {
+        //~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
+        /* ... */
+    }
 
+    impl Seq<bool> for u32 {
+        //~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
+        /* Treat the integer as a sequence of bits */
+    }
 }
diff --git a/src/test/ui/seq-args.stderr b/src/test/ui/seq-args.stderr
index 2e7d901640e..0e89fefc69d 100644
--- a/src/test/ui/seq-args.stderr
+++ b/src/test/ui/seq-args.stderr
@@ -1,14 +1,30 @@
-error[E0107]: wrong number of type arguments: expected 0, found 1
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
   --> $DIR/seq-args.rs:4:13
    |
-LL | impl<T> Seq<T> for Vec<T> {
-   |             ^ unexpected type argument
+LL |     impl<T> Seq<T> for Vec<T> {
+   |             ^^^--- help: remove these generics
+   |             |
+   |             expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $DIR/seq-args.rs:2:11
+   |
+LL |     trait Seq { }
+   |           ^^^
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/seq-args.rs:7:10
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/seq-args.rs:9:10
+   |
+LL |     impl Seq<bool> for u32 {
+   |          ^^^------ help: remove these generics
+   |          |
+   |          expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $DIR/seq-args.rs:2:11
    |
-LL | impl Seq<bool> for u32 {
-   |          ^^^^ unexpected type argument
+LL |     trait Seq { }
+   |           ^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/structs/structure-constructor-type-mismatch.rs b/src/test/ui/structs/structure-constructor-type-mismatch.rs
index 01cc1764657..56c8ffb3e65 100644
--- a/src/test/ui/structs/structure-constructor-type-mismatch.rs
+++ b/src/test/ui/structs/structure-constructor-type-mismatch.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-linelength
+
 struct Point<T> {
     x: T,
     y: T,
@@ -45,13 +47,13 @@ fn main() {
         y: 8,
     };
 
-    let pt3 = PointF::<i32> { //~ ERROR wrong number of type arguments
+    let pt3 = PointF::<i32> { //~ ERROR this type alias takes 0 type arguments but 1 type argument was supplied
         x: 9,  //~ ERROR mismatched types
         y: 10, //~ ERROR mismatched types
     };
 
     match (Point { x: 1, y: 2 }) {
-        PointF::<u32> { .. } => {} //~ ERROR wrong number of type arguments
+        PointF::<u32> { .. } => {} //~ ERROR this type alias takes 0 type arguments but 1 type argument was supplied
         //~^ ERROR mismatched types
     }
 
diff --git a/src/test/ui/structs/structure-constructor-type-mismatch.stderr b/src/test/ui/structs/structure-constructor-type-mismatch.stderr
index 8cfa118a2da..46114149672 100644
--- a/src/test/ui/structs/structure-constructor-type-mismatch.stderr
+++ b/src/test/ui/structs/structure-constructor-type-mismatch.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/structure-constructor-type-mismatch.rs:17:12
+  --> $DIR/structure-constructor-type-mismatch.rs:19:12
    |
 LL |         x: 1,
    |            ^
@@ -8,7 +8,7 @@ LL |         x: 1,
    |            help: use a float literal: `1.0`
 
 error[E0308]: mismatched types
-  --> $DIR/structure-constructor-type-mismatch.rs:20:12
+  --> $DIR/structure-constructor-type-mismatch.rs:22:12
    |
 LL |         y: 2,
    |            ^
@@ -17,7 +17,7 @@ LL |         y: 2,
    |            help: use a float literal: `2.0`
 
 error[E0308]: mismatched types
-  --> $DIR/structure-constructor-type-mismatch.rs:26:12
+  --> $DIR/structure-constructor-type-mismatch.rs:28:12
    |
 LL |         x: 3,
    |            ^
@@ -26,7 +26,7 @@ LL |         x: 3,
    |            help: use a float literal: `3.0`
 
 error[E0308]: mismatched types
-  --> $DIR/structure-constructor-type-mismatch.rs:29:12
+  --> $DIR/structure-constructor-type-mismatch.rs:31:12
    |
 LL |         y: 4,
    |            ^
@@ -35,7 +35,7 @@ LL |         y: 4,
    |            help: use a float literal: `4.0`
 
 error[E0308]: mismatched types
-  --> $DIR/structure-constructor-type-mismatch.rs:35:12
+  --> $DIR/structure-constructor-type-mismatch.rs:37:12
    |
 LL |         x: 5,
    |            ^
@@ -44,7 +44,7 @@ LL |         x: 5,
    |            help: use a float literal: `5.0`
 
 error[E0308]: mismatched types
-  --> $DIR/structure-constructor-type-mismatch.rs:42:12
+  --> $DIR/structure-constructor-type-mismatch.rs:44:12
    |
 LL |         x: 7,
    |            ^
@@ -52,14 +52,22 @@ LL |         x: 7,
    |            expected `f32`, found integer
    |            help: use a float literal: `7.0`
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/structure-constructor-type-mismatch.rs:48:24
+error[E0107]: this type alias takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/structure-constructor-type-mismatch.rs:50:15
    |
 LL |     let pt3 = PointF::<i32> {
-   |                        ^^^ unexpected type argument
+   |               ^^^^^^------- help: remove these generics
+   |               |
+   |               expected 0 type arguments
+   |
+note: type alias defined here, with 0 type parameters
+  --> $DIR/structure-constructor-type-mismatch.rs:8:6
+   |
+LL | type PointF = Point<f32>;
+   |      ^^^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/structure-constructor-type-mismatch.rs:49:12
+  --> $DIR/structure-constructor-type-mismatch.rs:51:12
    |
 LL |         x: 9,
    |            ^
@@ -68,7 +76,7 @@ LL |         x: 9,
    |            help: use a float literal: `9.0`
 
 error[E0308]: mismatched types
-  --> $DIR/structure-constructor-type-mismatch.rs:50:12
+  --> $DIR/structure-constructor-type-mismatch.rs:52:12
    |
 LL |         y: 10,
    |            ^^
@@ -76,14 +84,22 @@ LL |         y: 10,
    |            expected `f32`, found integer
    |            help: use a float literal: `10.0`
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/structure-constructor-type-mismatch.rs:54:18
+error[E0107]: this type alias takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/structure-constructor-type-mismatch.rs:56:9
    |
 LL |         PointF::<u32> { .. } => {}
-   |                  ^^^ unexpected type argument
+   |         ^^^^^^------- help: remove these generics
+   |         |
+   |         expected 0 type arguments
+   |
+note: type alias defined here, with 0 type parameters
+  --> $DIR/structure-constructor-type-mismatch.rs:8:6
+   |
+LL | type PointF = Point<f32>;
+   |      ^^^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/structure-constructor-type-mismatch.rs:54:9
+  --> $DIR/structure-constructor-type-mismatch.rs:56:9
    |
 LL |     match (Point { x: 1, y: 2 }) {
    |           ---------------------- this expression has type `Point<{integer}>`
@@ -94,7 +110,7 @@ LL |         PointF::<u32> { .. } => {}
               found struct `Point<f32>`
 
 error[E0308]: mismatched types
-  --> $DIR/structure-constructor-type-mismatch.rs:59:9
+  --> $DIR/structure-constructor-type-mismatch.rs:61:9
    |
 LL |     match (Point { x: 1, y: 2 }) {
    |           ---------------------- this expression has type `Point<{integer}>`
@@ -105,7 +121,7 @@ LL |         PointF { .. } => {}
               found struct `Point<f32>`
 
 error[E0308]: mismatched types
-  --> $DIR/structure-constructor-type-mismatch.rs:67:9
+  --> $DIR/structure-constructor-type-mismatch.rs:69:9
    |
 LL |     match (Pair { x: 1, y: 2 }) {
    |           --------------------- this expression has type `Pair<{integer}, {integer}>`
diff --git a/src/test/ui/suggestions/missing-lifetime-specifier.rs b/src/test/ui/suggestions/missing-lifetime-specifier.rs
index fe88d105c78..761922beb17 100644
--- a/src/test/ui/suggestions/missing-lifetime-specifier.rs
+++ b/src/test/ui/suggestions/missing-lifetime-specifier.rs
@@ -41,17 +41,17 @@ thread_local! {
 
 thread_local! {
     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
-    //~^ ERROR wrong number of lifetime arguments: expected 2, found 1
-    //~| ERROR wrong number of lifetime arguments: expected 2, found 1
-    //~| ERROR wrong number of lifetime arguments: expected 2, found 1
-    //~| ERROR wrong number of lifetime arguments: expected 2, found 1
+    //~^ ERROR this union takes 2 lifetime arguments but only 1 lifetime argument was supplied
+    //~| ERROR this union takes 2 lifetime arguments but only 1 lifetime argument was supplied
+    //~| ERROR this union takes 2 lifetime arguments but only 1 lifetime argument was supplied
+    //~| ERROR this union takes 2 lifetime arguments but only 1 lifetime argument was supplied
 }
 thread_local! {
     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-    //~^ ERROR wrong number of lifetime arguments: expected 2, found 1
-    //~| ERROR wrong number of lifetime arguments: expected 2, found 1
-    //~| ERROR wrong number of lifetime arguments: expected 2, found 1
-    //~| ERROR wrong number of lifetime arguments: expected 2, found 1
+    //~^ ERROR this trait takes 2 lifetime arguments but only 1 lifetime argument was supplied
+    //~| ERROR this trait takes 2 lifetime arguments but only 1 lifetime argument was supplied
+    //~| ERROR this trait takes 2 lifetime arguments but only 1 lifetime argument was supplied
+    //~| ERROR this trait takes 2 lifetime arguments but only 1 lifetime argument was supplied
     //~| ERROR missing lifetime specifier
     //~| ERROR missing lifetime specifier
 }
diff --git a/src/test/ui/suggestions/missing-lifetime-specifier.stderr b/src/test/ui/suggestions/missing-lifetime-specifier.stderr
index 9838ac72ad7..e6cec5cbd45 100644
--- a/src/test/ui/suggestions/missing-lifetime-specifier.stderr
+++ b/src/test/ui/suggestions/missing-lifetime-specifier.stderr
@@ -166,53 +166,149 @@ help: consider using the `'static` lifetime
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                            ^^^^^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: this union takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:43:44
    |
 LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                            ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
+   |                                            ^^^ ------- supplied 1 lifetime argument
+   |                                            |
+   |                                            expected 2 lifetime arguments
+   |
+note: union defined here, with 2 lifetime parameters: `'t`, `'k`
+  --> $DIR/missing-lifetime-specifier.rs:11:11
+   |
+LL | pub union Qux<'t, 'k, I> {
+   |           ^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                       ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: this union takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:43:44
    |
 LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                            ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
+   |                                            ^^^ ------- supplied 1 lifetime argument
+   |                                            |
+   |                                            expected 2 lifetime arguments
+   |
+note: union defined here, with 2 lifetime parameters: `'t`, `'k`
+  --> $DIR/missing-lifetime-specifier.rs:11:11
+   |
+LL | pub union Qux<'t, 'k, I> {
+   |           ^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                       ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: this union takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:43:44
    |
 LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                            ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
+   |                                            ^^^ ------- supplied 1 lifetime argument
+   |                                            |
+   |                                            expected 2 lifetime arguments
+   |
+note: union defined here, with 2 lifetime parameters: `'t`, `'k`
+  --> $DIR/missing-lifetime-specifier.rs:11:11
+   |
+LL | pub union Qux<'t, 'k, I> {
+   |           ^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                       ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: this union takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:43:44
    |
 LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                            ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
+   |                                            ^^^ ------- supplied 1 lifetime argument
+   |                                            |
+   |                                            expected 2 lifetime arguments
+   |
+note: union defined here, with 2 lifetime parameters: `'t`, `'k`
+  --> $DIR/missing-lifetime-specifier.rs:11:11
+   |
+LL | pub union Qux<'t, 'k, I> {
+   |           ^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                       ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: this trait takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:50:45
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                             ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
+   |                                             ^^^ ------- supplied 1 lifetime argument
+   |                                             |
+   |                                             expected 2 lifetime arguments
+   |
+note: trait defined here, with 2 lifetime parameters: `'t`, `'k`
+  --> $DIR/missing-lifetime-specifier.rs:15:7
+   |
+LL | trait Tar<'t, 'k, I> {}
+   |       ^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                        ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: this trait takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:50:45
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                             ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
+   |                                             ^^^ ------- supplied 1 lifetime argument
+   |                                             |
+   |                                             expected 2 lifetime arguments
+   |
+note: trait defined here, with 2 lifetime parameters: `'t`, `'k`
+  --> $DIR/missing-lifetime-specifier.rs:15:7
+   |
+LL | trait Tar<'t, 'k, I> {}
+   |       ^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                        ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: this trait takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:50:45
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                             ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
+   |                                             ^^^ ------- supplied 1 lifetime argument
+   |                                             |
+   |                                             expected 2 lifetime arguments
+   |
+note: trait defined here, with 2 lifetime parameters: `'t`, `'k`
+  --> $DIR/missing-lifetime-specifier.rs:15:7
+   |
+LL | trait Tar<'t, 'k, I> {}
+   |       ^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                        ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: this trait takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:50:45
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                             ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
+   |                                             ^^^ ------- supplied 1 lifetime argument
+   |                                             |
+   |                                             expected 2 lifetime arguments
+   |
+note: trait defined here, with 2 lifetime parameters: `'t`, `'k`
+  --> $DIR/missing-lifetime-specifier.rs:15:7
+   |
+LL | trait Tar<'t, 'k, I> {}
+   |       ^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                        ^^^^
 
 error: aborting due to 22 previous errors
 
diff --git a/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.rs b/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.rs
index 78487bd7bb5..05e2d38c43b 100644
--- a/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.rs
+++ b/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.rs
@@ -6,7 +6,7 @@ pub trait T<X, Y> {
 pub struct Foo {
     i: Box<dyn T<usize, usize, usize, usize, B=usize>>,
     //~^ ERROR must be specified
-    //~| ERROR wrong number of type arguments
+    //~| ERROR this trait takes 2 type arguments but 4 type arguments were supplied
 }
 
 
diff --git a/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr b/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr
index 58a73187fb1..2d06591f4c7 100644
--- a/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr
+++ b/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr
@@ -1,10 +1,16 @@
-error[E0107]: wrong number of type arguments: expected 2, found 4
-  --> $DIR/use-type-argument-instead-of-assoc-type.rs:7:32
+error[E0107]: this trait takes 2 type arguments but 4 type arguments were supplied
+  --> $DIR/use-type-argument-instead-of-assoc-type.rs:7:16
    |
 LL |     i: Box<dyn T<usize, usize, usize, usize, B=usize>>,
-   |                                ^^^^^  ^^^^^ unexpected type argument
-   |                                |
-   |                                unexpected type argument
+   |                ^             -------------- help: remove these type arguments
+   |                |
+   |                expected 2 type arguments
+   |
+note: trait defined here, with 2 type parameters: `X`, `Y`
+  --> $DIR/use-type-argument-instead-of-assoc-type.rs:1:11
+   |
+LL | pub trait T<X, Y> {
+   |           ^ -  -
 
 error[E0191]: the value of the associated types `A` (from trait `T`), `C` (from trait `T`) must be specified
   --> $DIR/use-type-argument-instead-of-assoc-type.rs:7:16
diff --git a/src/test/ui/tag-type-args.rs b/src/test/ui/tag-type-args.rs
index 4f546fcc2ad..660d860ba77 100644
--- a/src/test/ui/tag-type-args.rs
+++ b/src/test/ui/tag-type-args.rs
@@ -1,5 +1,5 @@
 enum Quux<T> { Bar }
 
-fn foo(c: Quux) { assert!((false)); } //~ ERROR wrong number of type arguments
+fn foo(c: Quux) { assert!((false)); } //~ ERROR missing generics for enum `Quux`
 
 fn main() { panic!(); }
diff --git a/src/test/ui/tag-type-args.stderr b/src/test/ui/tag-type-args.stderr
index ac44dad4a88..c9888dc54dc 100644
--- a/src/test/ui/tag-type-args.stderr
+++ b/src/test/ui/tag-type-args.stderr
@@ -1,8 +1,18 @@
-error[E0107]: wrong number of type arguments: expected 1, found 0
+error[E0107]: missing generics for enum `Quux`
   --> $DIR/tag-type-args.rs:3:11
    |
 LL | fn foo(c: Quux) { assert!((false)); }
    |           ^^^^ expected 1 type argument
+   |
+note: enum defined here, with 1 type parameter: `T`
+  --> $DIR/tag-type-args.rs:1:6
+   |
+LL | enum Quux<T> { Bar }
+   |      ^^^^ -
+help: use angle brackets to add missing type argument
+   |
+LL | fn foo(c: Quux<T>) { assert!((false)); }
+   |               ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/trait-object-vs-lifetime.rs b/src/test/ui/traits/trait-object-vs-lifetime.rs
index e885cd2f68a..e49d276a55a 100644
--- a/src/test/ui/traits/trait-object-vs-lifetime.rs
+++ b/src/test/ui/traits/trait-object-vs-lifetime.rs
@@ -9,8 +9,8 @@ fn main() {
     let _: S<'static, dyn 'static +>;
     //~^ at least one trait is required for an object type
     let _: S<'static, 'static>;
-    //~^ ERROR wrong number of lifetime arguments: expected 1, found 2
-    //~| ERROR wrong number of type arguments: expected 1, found 0
+    //~^ ERROR this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
+    //~| ERROR this struct takes 1 type argument but 0 type arguments were supplied
     let _: S<dyn 'static +, 'static>;
     //~^ ERROR type provided when a lifetime was expected
     //~| ERROR at least one trait is required for an object type
diff --git a/src/test/ui/traits/trait-object-vs-lifetime.stderr b/src/test/ui/traits/trait-object-vs-lifetime.stderr
index 8958547e827..620c816d6d9 100644
--- a/src/test/ui/traits/trait-object-vs-lifetime.stderr
+++ b/src/test/ui/traits/trait-object-vs-lifetime.stderr
@@ -4,17 +4,35 @@ error[E0224]: at least one trait is required for an object type
 LL |     let _: S<'static, dyn 'static +>;
    |                       ^^^^^^^^^^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 1, found 2
-  --> $DIR/trait-object-vs-lifetime.rs:11:23
+error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
+  --> $DIR/trait-object-vs-lifetime.rs:11:12
    |
 LL |     let _: S<'static, 'static>;
-   |                       ^^^^^^^ unexpected lifetime argument
+   |            ^        --------- help: remove this lifetime argument
+   |            |
+   |            expected 1 lifetime argument
+   |
+note: struct defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/trait-object-vs-lifetime.rs:4:8
+   |
+LL | struct S<'a, T>(&'a u8, T);
+   |        ^ --
 
-error[E0107]: wrong number of type arguments: expected 1, found 0
+error[E0107]: this struct takes 1 type argument but 0 type arguments were supplied
   --> $DIR/trait-object-vs-lifetime.rs:11:12
    |
 LL |     let _: S<'static, 'static>;
-   |            ^^^^^^^^^^^^^^^^^^^ expected 1 type argument
+   |            ^ expected 1 type argument
+   |
+note: struct defined here, with 1 type parameter: `T`
+  --> $DIR/trait-object-vs-lifetime.rs:4:8
+   |
+LL | struct S<'a, T>(&'a u8, T);
+   |        ^     -
+help: add missing type argument
+   |
+LL |     let _: S<'static, 'static, T>;
+   |                              ^^^
 
 error[E0224]: at least one trait is required for an object type
   --> $DIR/trait-object-vs-lifetime.rs:14:14
diff --git a/src/test/ui/traits/trait-test-2.rs b/src/test/ui/traits/trait-test-2.rs
index 86570f1152e..a33773144c2 100644
--- a/src/test/ui/traits/trait-test-2.rs
+++ b/src/test/ui/traits/trait-test-2.rs
@@ -6,8 +6,10 @@ impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah<X>(&self) {} }
 impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah<X>(&self) {} }
 
 fn main() {
-    10.dup::<i32>(); //~ ERROR wrong number of type arguments: expected 0, found 1
-    10.blah::<i32, i32>(); //~ ERROR wrong number of type arguments: expected 1, found 2
+    10.dup::<i32>();
+    //~^ ERROR this associated function takes 0 type arguments but 1 type argument was supplied
+    10.blah::<i32, i32>();
+    //~^ ERROR this associated function takes 1 type argument but 2 type arguments were supplied
     (box 10 as Box<dyn bar>).dup();
     //~^ ERROR E0038
     //~| ERROR E0038
diff --git a/src/test/ui/traits/trait-test-2.stderr b/src/test/ui/traits/trait-test-2.stderr
index a06f6a49194..a38d3387c8d 100644
--- a/src/test/ui/traits/trait-test-2.stderr
+++ b/src/test/ui/traits/trait-test-2.stderr
@@ -1,17 +1,33 @@
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/trait-test-2.rs:9:14
+error[E0107]: this associated function takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/trait-test-2.rs:9:8
    |
 LL |     10.dup::<i32>();
-   |              ^^^ unexpected type argument
+   |        ^^^------- help: remove these generics
+   |        |
+   |        expected 0 type arguments
+   |
+note: associated function defined here, with 0 type parameters
+  --> $DIR/trait-test-2.rs:4:16
+   |
+LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
+   |                ^^^
 
-error[E0107]: wrong number of type arguments: expected 1, found 2
-  --> $DIR/trait-test-2.rs:10:20
+error[E0107]: this associated function takes 1 type argument but 2 type arguments were supplied
+  --> $DIR/trait-test-2.rs:11:8
    |
 LL |     10.blah::<i32, i32>();
-   |                    ^^^ unexpected type argument
+   |        ^^^^      ----- help: remove this type argument
+   |        |
+   |        expected 1 type argument
+   |
+note: associated function defined here, with 1 type parameter: `X`
+  --> $DIR/trait-test-2.rs:4:39
+   |
+LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
+   |                                       ^^^^ -
 
 error[E0038]: the trait `bar` cannot be made into an object
-  --> $DIR/trait-test-2.rs:11:16
+  --> $DIR/trait-test-2.rs:13:16
    |
 LL |     (box 10 as Box<dyn bar>).dup();
    |                ^^^^^^^^^^^^ `bar` cannot be made into an object
@@ -28,7 +44,7 @@ LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
    |       this trait cannot be made into an object...
 
 error[E0038]: the trait `bar` cannot be made into an object
-  --> $DIR/trait-test-2.rs:11:6
+  --> $DIR/trait-test-2.rs:13:6
    |
 LL |     (box 10 as Box<dyn bar>).dup();
    |      ^^^^^^ `bar` cannot be made into an object
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 f182c3ba8c7..f204035248a 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
@@ -16,10 +16,10 @@ impl<T> Enum<T> {
         //~^ ERROR type arguments are not allowed for this type [E0109]
         Self::<()>::TSVariant(());
         //~^ ERROR type arguments are not allowed for this type [E0109]
-        //~^^ ERROR mismatched types [E0308]
+        //~| 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 for this type [E0109]
     }
 
     fn s_variant() {
@@ -27,14 +27,14 @@ impl<T> Enum<T> {
         //~^ ERROR mismatched types [E0308]
         Self::SVariant::<()> { v: () };
         //~^ ERROR type arguments are not allowed for this type [E0109]
-        //~^^ ERROR mismatched types [E0308]
+        //~| ERROR mismatched types [E0308]
         Self::<()>::SVariant { v: () };
         //~^ ERROR type arguments are not allowed for this type [E0109]
-        //~^^ ERROR mismatched types [E0308]
+        //~| 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 mismatched types [E0308]
+        //~| ERROR type arguments are not allowed for this type [E0109]
+        //~| ERROR mismatched types [E0308]
     }
 
     fn u_variant() {
@@ -44,7 +44,7 @@ impl<T> Enum<T> {
         //~^ ERROR type arguments are not allowed for this 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 for this type [E0109]
     }
 }
 
@@ -62,10 +62,10 @@ fn main() {
     AliasFixed::TSVariant::<()>(());
     //~^ ERROR type arguments are not allowed for this type [E0109]
     AliasFixed::<()>::TSVariant(());
-    //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+    //~^ ERROR this type alias takes 0 type arguments but 1 type argument was supplied [E0107]
     AliasFixed::<()>::TSVariant::<()>(());
     //~^ ERROR type arguments are not allowed for this type [E0109]
-    //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+    //~| ERROR this type alias takes 0 type arguments but 1 type argument was supplied [E0107]
 
     // Struct variant
 
@@ -80,10 +80,10 @@ fn main() {
     AliasFixed::SVariant::<()> { v: () };
     //~^ ERROR type arguments are not allowed for this type [E0109]
     AliasFixed::<()>::SVariant { v: () };
-    //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+    //~^ ERROR this type alias takes 0 type arguments but 1 type argument was supplied [E0107]
     AliasFixed::<()>::SVariant::<()> { v: () };
     //~^ ERROR type arguments are not allowed for this type [E0109]
-    //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+    //~| ERROR this type alias takes 0 type arguments but 1 type argument was supplied [E0107]
 
     // Unit variant
 
@@ -98,8 +98,8 @@ fn main() {
     AliasFixed::UVariant::<()>;
     //~^ ERROR type arguments are not allowed for this type [E0109]
     AliasFixed::<()>::UVariant;
-    //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+    //~^ ERROR this type alias takes 0 type arguments but 1 type argument was supplied [E0107]
     AliasFixed::<()>::UVariant::<()>;
     //~^ ERROR type arguments are not allowed for this type [E0109]
-    //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+    //~| ERROR this type alias takes 0 type arguments but 1 type 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 caea791e653..e83db3b0d51 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
@@ -166,17 +166,33 @@ error[E0109]: type arguments are not allowed for this type
 LL |     AliasFixed::TSVariant::<()>(());
    |                             ^^ type argument not allowed
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/enum-variant-generic-args.rs:64:18
+error[E0107]: this type alias takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/enum-variant-generic-args.rs:64:5
    |
 LL |     AliasFixed::<()>::TSVariant(());
-   |                  ^^ unexpected type argument
+   |     ^^^^^^^^^^------ help: remove these generics
+   |     |
+   |     expected 0 type arguments
+   |
+note: type alias defined here, with 0 type parameters
+  --> $DIR/enum-variant-generic-args.rs:9:6
+   |
+LL | type AliasFixed = Enum<()>;
+   |      ^^^^^^^^^^
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/enum-variant-generic-args.rs:66:18
+error[E0107]: this type alias takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/enum-variant-generic-args.rs:66:5
    |
 LL |     AliasFixed::<()>::TSVariant::<()>(());
-   |                  ^^ unexpected type argument
+   |     ^^^^^^^^^^------ help: remove these generics
+   |     |
+   |     expected 0 type arguments
+   |
+note: type alias defined here, with 0 type parameters
+  --> $DIR/enum-variant-generic-args.rs:9:6
+   |
+LL | type AliasFixed = Enum<()>;
+   |      ^^^^^^^^^^
 
 error[E0109]: type arguments are not allowed for this type
   --> $DIR/enum-variant-generic-args.rs:66:35
@@ -208,17 +224,33 @@ error[E0109]: type arguments are not allowed for this type
 LL |     AliasFixed::SVariant::<()> { v: () };
    |                            ^^ type argument not allowed
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/enum-variant-generic-args.rs:82:18
+error[E0107]: this type alias takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/enum-variant-generic-args.rs:82:5
    |
 LL |     AliasFixed::<()>::SVariant { v: () };
-   |                  ^^ unexpected type argument
+   |     ^^^^^^^^^^------ help: remove these generics
+   |     |
+   |     expected 0 type arguments
+   |
+note: type alias defined here, with 0 type parameters
+  --> $DIR/enum-variant-generic-args.rs:9:6
+   |
+LL | type AliasFixed = Enum<()>;
+   |      ^^^^^^^^^^
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/enum-variant-generic-args.rs:84:18
+error[E0107]: this type alias takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/enum-variant-generic-args.rs:84:5
    |
 LL |     AliasFixed::<()>::SVariant::<()> { v: () };
-   |                  ^^ unexpected type argument
+   |     ^^^^^^^^^^------ help: remove these generics
+   |     |
+   |     expected 0 type arguments
+   |
+note: type alias defined here, with 0 type parameters
+  --> $DIR/enum-variant-generic-args.rs:9:6
+   |
+LL | type AliasFixed = Enum<()>;
+   |      ^^^^^^^^^^
 
 error[E0109]: type arguments are not allowed for this type
   --> $DIR/enum-variant-generic-args.rs:84:34
@@ -250,17 +282,33 @@ error[E0109]: type arguments are not allowed for this type
 LL |     AliasFixed::UVariant::<()>;
    |                            ^^ type argument not allowed
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/enum-variant-generic-args.rs:100:18
+error[E0107]: this type alias takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/enum-variant-generic-args.rs:100:5
    |
 LL |     AliasFixed::<()>::UVariant;
-   |                  ^^ unexpected type argument
+   |     ^^^^^^^^^^------ help: remove these generics
+   |     |
+   |     expected 0 type arguments
+   |
+note: type alias defined here, with 0 type parameters
+  --> $DIR/enum-variant-generic-args.rs:9:6
+   |
+LL | type AliasFixed = Enum<()>;
+   |      ^^^^^^^^^^
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/enum-variant-generic-args.rs:102:18
+error[E0107]: this type alias takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/enum-variant-generic-args.rs:102:5
    |
 LL |     AliasFixed::<()>::UVariant::<()>;
-   |                  ^^ unexpected type argument
+   |     ^^^^^^^^^^------ help: remove these generics
+   |     |
+   |     expected 0 type arguments
+   |
+note: type alias defined here, with 0 type parameters
+  --> $DIR/enum-variant-generic-args.rs:9:6
+   |
+LL | type AliasFixed = Enum<()>;
+   |      ^^^^^^^^^^
 
 error[E0109]: type arguments are not allowed for this type
   --> $DIR/enum-variant-generic-args.rs:102:34
diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr b/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
index 20e26058451..1d520613a28 100644
--- a/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
+++ b/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
@@ -5,12 +5,6 @@ LL |     <E>::V();
    |     ^^^^^^-- supplied 0 arguments
    |     |
    |     expected 1 argument
-   |
-note: tuple variant defined here
-  --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:5:5
-   |
-LL |     V(u8)
-   |     ^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:22:17
diff --git a/src/test/ui/type/ascription/issue-34255-1.rs b/src/test/ui/type/ascription/issue-34255-1.rs
index 3aad085f089..44b47cc4eb2 100644
--- a/src/test/ui/type/ascription/issue-34255-1.rs
+++ b/src/test/ui/type/ascription/issue-34255-1.rs
@@ -7,7 +7,7 @@ impl Reactor {
         input_cells: Vec::new()
         //~^ ERROR cannot find value `input_cells` in this scope
         //~| ERROR parenthesized type parameters may only be used with a `Fn` trait
-        //~| ERROR wrong number of type arguments: expected at least 1, found 0
+        //~| ERROR missing generics for struct `Vec`
     }
 }
 
diff --git a/src/test/ui/type/ascription/issue-34255-1.stderr b/src/test/ui/type/ascription/issue-34255-1.stderr
index 402e54d2a95..fc474e1ec3b 100644
--- a/src/test/ui/type/ascription/issue-34255-1.stderr
+++ b/src/test/ui/type/ascription/issue-34255-1.stderr
@@ -10,11 +10,21 @@ error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
 LL |         input_cells: Vec::new()
    |                           ^^^^^ only `Fn` traits may use parentheses
 
-error[E0107]: wrong number of type arguments: expected at least 1, found 0
+error[E0107]: missing generics for struct `Vec`
   --> $DIR/issue-34255-1.rs:7:22
    |
 LL |         input_cells: Vec::new()
-   |                      ^^^^^^^^^^ expected at least 1 type argument
+   |                      ^^^ expected at least 1 type argument
+   |
+note: struct defined here, with at least 1 type parameter: `T`
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+   |
+LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
+   |            ^^^ -
+help: use angle brackets to add missing type argument
+   |
+LL |         input_cells: Vec<T>::new()
+   |                         ^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/type/type-ascription-instead-of-initializer.stderr b/src/test/ui/type/type-ascription-instead-of-initializer.stderr
index 530f77e5ae9..e5666d4fe4f 100644
--- a/src/test/ui/type/type-ascription-instead-of-initializer.stderr
+++ b/src/test/ui/type/type-ascription-instead-of-initializer.stderr
@@ -14,6 +14,12 @@ LL |     let x: Vec::with_capacity(10, 20);
    |            ^^^^^^^^^^^^^^^^^^ --  -- supplied 2 arguments
    |            |
    |            expected 1 argument
+   |
+note: associated function defined here
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+   |
+LL |     pub fn with_capacity(capacity: usize) -> Self {
+   |            ^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/typeck/typeck-builtin-bound-type-parameters.rs b/src/test/ui/typeck/typeck-builtin-bound-type-parameters.rs
index f466c19e051..f1659d08670 100644
--- a/src/test/ui/typeck/typeck-builtin-bound-type-parameters.rs
+++ b/src/test/ui/typeck/typeck-builtin-bound-type-parameters.rs
@@ -1,19 +1,17 @@
 fn foo1<T:Copy<U>, U>(x: T) {}
-//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+//~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
 
 trait Trait: Copy<dyn Send> {}
-//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+//~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
 
 struct MyStruct1<T: Copy<T>>;
-//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+//~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
 
 struct MyStruct2<'a, T: Copy<'a>>;
-//~^ ERROR: wrong number of lifetime arguments: expected 0, found 1 [E0107]
-
+//~^ ERROR this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
 
 fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
-//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
-//~| ERROR: wrong number of lifetime arguments: expected 0, found 1
+//~^ ERROR this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
+//~| ERROR this trait takes 0 type arguments but 1 type argument was supplied
 
-fn main() {
-}
+fn main() { }
diff --git a/src/test/ui/typeck/typeck-builtin-bound-type-parameters.stderr b/src/test/ui/typeck/typeck-builtin-bound-type-parameters.stderr
index 0be1c8ef3bc..777bc1c95b0 100644
--- a/src/test/ui/typeck/typeck-builtin-bound-type-parameters.stderr
+++ b/src/test/ui/typeck/typeck-builtin-bound-type-parameters.stderr
@@ -1,38 +1,86 @@
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/typeck-builtin-bound-type-parameters.rs:1:16
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:1:11
    |
 LL | fn foo1<T:Copy<U>, U>(x: T) {}
-   |                ^ unexpected type argument
+   |           ^^^^--- help: remove these generics
+   |           |
+   |           expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $SRC_DIR/core/src/marker.rs:LL:COL
+   |
+LL | pub trait Copy: Clone {
+   |           ^^^^
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/typeck-builtin-bound-type-parameters.rs:4:19
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:4:14
    |
 LL | trait Trait: Copy<dyn Send> {}
-   |                   ^^^^^^^^ unexpected type argument
+   |              ^^^^---------- help: remove these generics
+   |              |
+   |              expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $SRC_DIR/core/src/marker.rs:LL:COL
+   |
+LL | pub trait Copy: Clone {
+   |           ^^^^
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/typeck-builtin-bound-type-parameters.rs:7:26
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:7:21
    |
 LL | struct MyStruct1<T: Copy<T>>;
-   |                          ^ unexpected type argument
+   |                     ^^^^--- help: remove these generics
+   |                     |
+   |                     expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $SRC_DIR/core/src/marker.rs:LL:COL
+   |
+LL | pub trait Copy: Clone {
+   |           ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 0, found 1
-  --> $DIR/typeck-builtin-bound-type-parameters.rs:10:30
+error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:10:25
    |
 LL | struct MyStruct2<'a, T: Copy<'a>>;
-   |                              ^^ unexpected lifetime argument
+   |                         ^^^^---- help: remove these generics
+   |                         |
+   |                         expected 0 lifetime arguments
+   |
+note: trait defined here, with 0 lifetime parameters
+  --> $SRC_DIR/core/src/marker.rs:LL:COL
+   |
+LL | pub trait Copy: Clone {
+   |           ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 0, found 1
-  --> $DIR/typeck-builtin-bound-type-parameters.rs:14:20
+error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:13:15
    |
 LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
-   |                    ^^ unexpected lifetime argument
+   |               ^^^^ ---- help: remove this lifetime argument
+   |               |
+   |               expected 0 lifetime arguments
+   |
+note: trait defined here, with 0 lifetime parameters
+  --> $SRC_DIR/core/src/marker.rs:LL:COL
+   |
+LL | pub trait Copy: Clone {
+   |           ^^^^
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/typeck-builtin-bound-type-parameters.rs:14:24
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:13:15
    |
 LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
-   |                        ^ unexpected type argument
+   |               ^^^^   --- help: remove this type argument
+   |               |
+   |               expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $SRC_DIR/core/src/marker.rs:LL:COL
+   |
+LL | pub trait Copy: Clone {
+   |           ^^^^
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/typeck/typeck_type_placeholder_lifetime_1.rs b/src/test/ui/typeck/typeck_type_placeholder_lifetime_1.rs
index 57ab7dee0e8..8f8917e16af 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_lifetime_1.rs
+++ b/src/test/ui/typeck/typeck_type_placeholder_lifetime_1.rs
@@ -7,5 +7,5 @@ struct Foo<'a, T:'a> {
 
 pub fn main() {
     let c: Foo<_, _> = Foo { r: &5 };
-    //~^ ERROR wrong number of type arguments: expected 1, found 2 [E0107]
+    //~^ ERROR this struct takes 1 type argument but 2 type arguments were supplied
 }
diff --git a/src/test/ui/typeck/typeck_type_placeholder_lifetime_1.stderr b/src/test/ui/typeck/typeck_type_placeholder_lifetime_1.stderr
index 8186d75f920..01ab8e78d7c 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_lifetime_1.stderr
+++ b/src/test/ui/typeck/typeck_type_placeholder_lifetime_1.stderr
@@ -1,8 +1,16 @@
-error[E0107]: wrong number of type arguments: expected 1, found 2
-  --> $DIR/typeck_type_placeholder_lifetime_1.rs:9:19
+error[E0107]: this struct takes 1 type argument but 2 type arguments were supplied
+  --> $DIR/typeck_type_placeholder_lifetime_1.rs:9:12
    |
 LL |     let c: Foo<_, _> = Foo { r: &5 };
-   |                   ^ unexpected type argument
+   |            ^^^  --- help: remove this type argument
+   |            |
+   |            expected 1 type argument
+   |
+note: struct defined here, with 1 type parameter: `T`
+  --> $DIR/typeck_type_placeholder_lifetime_1.rs:4:8
+   |
+LL | struct Foo<'a, T:'a> {
+   |        ^^^     -
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/typeck/typeck_type_placeholder_lifetime_2.rs b/src/test/ui/typeck/typeck_type_placeholder_lifetime_2.rs
index b68d2832b4f..b491a7e1a9c 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_lifetime_2.rs
+++ b/src/test/ui/typeck/typeck_type_placeholder_lifetime_2.rs
@@ -7,5 +7,5 @@ struct Foo<'a, T:'a> {
 
 pub fn main() {
     let c: Foo<_, usize> = Foo { r: &5 };
-    //~^ ERROR wrong number of type arguments: expected 1, found 2 [E0107]
+    //~^ ERROR this struct takes 1 type argument but 2 type arguments were supplied
 }
diff --git a/src/test/ui/typeck/typeck_type_placeholder_lifetime_2.stderr b/src/test/ui/typeck/typeck_type_placeholder_lifetime_2.stderr
index 9b0f9695ef7..6d03b833c0f 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_lifetime_2.stderr
+++ b/src/test/ui/typeck/typeck_type_placeholder_lifetime_2.stderr
@@ -1,8 +1,16 @@
-error[E0107]: wrong number of type arguments: expected 1, found 2
-  --> $DIR/typeck_type_placeholder_lifetime_2.rs:9:19
+error[E0107]: this struct takes 1 type argument but 2 type arguments were supplied
+  --> $DIR/typeck_type_placeholder_lifetime_2.rs:9:12
    |
 LL |     let c: Foo<_, usize> = Foo { r: &5 };
-   |                   ^^^^^ unexpected type argument
+   |            ^^^  ------- help: remove this type argument
+   |            |
+   |            expected 1 type argument
+   |
+note: struct defined here, with 1 type parameter: `T`
+  --> $DIR/typeck_type_placeholder_lifetime_2.rs:4:8
+   |
+LL | struct Foo<'a, T:'a> {
+   |        ^^^     -
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/ufcs/ufcs-qpath-missing-params.rs b/src/test/ui/ufcs/ufcs-qpath-missing-params.rs
index 8b66a8fa90a..7d2fbdae6a2 100644
--- a/src/test/ui/ufcs/ufcs-qpath-missing-params.rs
+++ b/src/test/ui/ufcs/ufcs-qpath-missing-params.rs
@@ -12,5 +12,9 @@ impl<'a> IntoCow<'a, str> for String {
 
 fn main() {
     <String as IntoCow>::into_cow("foo".to_string());
-    //~^ ERROR wrong number of type arguments: expected 1, found 0
+    //~^ ERROR missing generics for trait `IntoCow`
+
+    <String as IntoCow>::into_cow::<str>("foo".to_string());
+    //~^ ERROR missing generics for trait `IntoCow`
+    //~| ERROR this associated function takes 0 type arguments but 1 type argument was supplied
 }
diff --git a/src/test/ui/ufcs/ufcs-qpath-missing-params.stderr b/src/test/ui/ufcs/ufcs-qpath-missing-params.stderr
index 1145f1e6409..e3fcef3dc1b 100644
--- a/src/test/ui/ufcs/ufcs-qpath-missing-params.stderr
+++ b/src/test/ui/ufcs/ufcs-qpath-missing-params.stderr
@@ -1,9 +1,49 @@
-error[E0107]: wrong number of type arguments: expected 1, found 0
-  --> $DIR/ufcs-qpath-missing-params.rs:14:5
+error[E0107]: missing generics for trait `IntoCow`
+  --> $DIR/ufcs-qpath-missing-params.rs:14:16
    |
 LL |     <String as IntoCow>::into_cow("foo".to_string());
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 type argument
+   |                ^^^^^^^ expected 1 type argument
+   |
+note: trait defined here, with 1 type parameter: `B`
+  --> $DIR/ufcs-qpath-missing-params.rs:3:11
+   |
+LL | pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
+   |           ^^^^^^^     -
+help: use angle brackets to add missing type argument
+   |
+LL |     <String as IntoCow<B>>::into_cow("foo".to_string());
+   |                       ^^^
+
+error[E0107]: missing generics for trait `IntoCow`
+  --> $DIR/ufcs-qpath-missing-params.rs:17:16
+   |
+LL |     <String as IntoCow>::into_cow::<str>("foo".to_string());
+   |                ^^^^^^^ expected 1 type argument
+   |
+note: trait defined here, with 1 type parameter: `B`
+  --> $DIR/ufcs-qpath-missing-params.rs:3:11
+   |
+LL | pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
+   |           ^^^^^^^     -
+help: use angle brackets to add missing type argument
+   |
+LL |     <String as IntoCow<B>>::into_cow::<str>("foo".to_string());
+   |                       ^^^
+
+error[E0107]: this associated function takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/ufcs-qpath-missing-params.rs:17:26
+   |
+LL |     <String as IntoCow>::into_cow::<str>("foo".to_string());
+   |                          ^^^^^^^^------- help: remove these generics
+   |                          |
+   |                          expected 0 type arguments
+   |
+note: associated function defined here, with 0 type parameters
+  --> $DIR/ufcs-qpath-missing-params.rs:4:8
+   |
+LL |     fn into_cow(self) -> Cow<'a, B>;
+   |        ^^^^^^^^
 
-error: aborting due to previous error
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.rs
index 76c928d7b6a..65f40075bd8 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.rs
@@ -28,7 +28,7 @@ fn test<'a,'b>() {
 }
 
 fn test2(x: &dyn Foo<(isize,),Output=()>, y: &dyn Foo(isize)) {
-//~^ ERROR wrong number of lifetime arguments: expected 1, found 0
+    //~^ ERROR this trait takes 1 lifetime argument but 0 lifetime arguments were supplied
     // Here, the omitted lifetimes are expanded to distinct things.
     same_type(x, y)
 }
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.stderr
index e9d51983a7a..016fc4dfb24 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.stderr
@@ -1,8 +1,14 @@
-error[E0107]: wrong number of lifetime arguments: expected 1, found 0
+error[E0107]: this trait takes 1 lifetime argument but 0 lifetime arguments were supplied
   --> $DIR/unboxed-closure-sugar-region.rs:30:51
    |
 LL | fn test2(x: &dyn Foo<(isize,),Output=()>, y: &dyn Foo(isize)) {
-   |                                                   ^^^^^^^^^^ expected 1 lifetime argument
+   |                                                   ^^^ expected 1 lifetime argument
+   |
+note: trait defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/unboxed-closure-sugar-region.rs:10:7
+   |
+LL | trait Foo<'a,T> {
+   |       ^^^ --
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs
index c96a6fa8b6c..a82856add59 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs
@@ -7,7 +7,7 @@ struct Bar<A> {
 fn bar() {
     let x: Box<Bar()> = panic!();
     //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
-    //~| ERROR wrong number of type arguments: expected 1, found 0
+    //~| ERROR missing generics for struct `Bar`
 }
 
 fn main() { }
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr
index 32619420f6d..d81975abbe9 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr
@@ -4,11 +4,21 @@ error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
 LL |     let x: Box<Bar()> = panic!();
    |                ^^^^^ only `Fn` traits may use parentheses
 
-error[E0107]: wrong number of type arguments: expected 1, found 0
+error[E0107]: missing generics for struct `Bar`
   --> $DIR/unboxed-closure-sugar-used-on-struct-1.rs:8:16
    |
 LL |     let x: Box<Bar()> = panic!();
-   |                ^^^^^ expected 1 type argument
+   |                ^^^ expected 1 type argument
+   |
+note: struct defined here, with 1 type parameter: `A`
+  --> $DIR/unboxed-closure-sugar-used-on-struct-1.rs:3:8
+   |
+LL | struct Bar<A> {
+   |        ^^^ -
+help: use angle brackets to add missing type argument
+   |
+LL |     let x: Box<Bar<A>()> = panic!();
+   |                   ^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs
index 1af7f55674c..b44505f8a41 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs
@@ -6,7 +6,7 @@ struct Bar<A> {
 
 fn foo(b: Box<Bar()>) {
     //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
-    //~| ERROR wrong number of type arguments: expected 1, found 0
+    //~| ERROR missing generics for struct `Bar`
 }
 
 fn main() { }
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr
index ba93b60dad8..80d7c2402b6 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr
@@ -4,11 +4,21 @@ error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
 LL | fn foo(b: Box<Bar()>) {
    |               ^^^^^ only `Fn` traits may use parentheses
 
-error[E0107]: wrong number of type arguments: expected 1, found 0
+error[E0107]: missing generics for struct `Bar`
   --> $DIR/unboxed-closure-sugar-used-on-struct.rs:7:15
    |
 LL | fn foo(b: Box<Bar()>) {
-   |               ^^^^^ expected 1 type argument
+   |               ^^^ expected 1 type argument
+   |
+note: struct defined here, with 1 type parameter: `A`
+  --> $DIR/unboxed-closure-sugar-used-on-struct.rs:3:8
+   |
+LL | struct Bar<A> {
+   |        ^^^ -
+help: use angle brackets to add missing type argument
+   |
+LL | fn foo(b: Box<Bar<A>()>) {
+   |                  ^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs
index 01c76d64c6b..a496b7da2f1 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs
@@ -3,7 +3,7 @@
 trait Three<A,B,C> { fn dummy(&self) -> (A,B,C); }
 
 fn foo(_: &dyn Three())
-//~^ ERROR wrong number of type arguments
+//~^ ERROR this trait takes 3 type arguments but only 1 type argument was supplied
 //~| ERROR associated type `Output` not found
 {}
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr
index f42ac38d370..ef5e7d222b4 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr
@@ -1,8 +1,16 @@
-error[E0107]: wrong number of type arguments: expected 3, found 1
+error[E0107]: this trait takes 3 type arguments but only 1 type argument was supplied
   --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs:5:16
    |
 LL | fn foo(_: &dyn Three())
-   |                ^^^^^^^ expected 3 type arguments
+   |                ^^^^^-- supplied 1 type argument
+   |                |
+   |                expected 3 type arguments
+   |
+note: trait defined here, with 3 type parameters: `A`, `B`, `C`
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs:3:7
+   |
+LL | trait Three<A,B,C> { fn dummy(&self) -> (A,B,C); }
+   |       ^^^^^ - - -
 
 error[E0220]: associated type `Output` not found for `Three<(), [type error], [type error]>`
   --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs:5:16
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.rs
index bc9901c795b..d0c85150efe 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.rs
@@ -2,9 +2,27 @@
 
 trait Zero { fn dummy(&self); }
 
-fn foo(_: dyn Zero())
-    //~^ ERROR wrong number of type arguments
+fn foo1(_: dyn Zero()) {
+    //~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
     //~| ERROR associated type `Output` not found for `Zero`
-{}
+}
+
+fn foo2(_: dyn Zero<usize>) {
+    //~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
+}
+
+fn foo3(_: dyn Zero <   usize   >) {
+    //~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
+}
+
+fn foo4(_: dyn Zero(usize)) {
+    //~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
+    //~| ERROR associated type `Output` not found for `Zero`
+}
+
+fn foo5(_: dyn Zero (   usize   )) {
+    //~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
+    //~| ERROR associated type `Output` not found for `Zero`
+}
 
 fn main() { }
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr
index 8185a798e7b..2e620a5563f 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr
@@ -1,16 +1,92 @@
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:5:15
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:5:16
    |
-LL | fn foo(_: dyn Zero())
-   |               ^^^^^^ unexpected type argument
+LL | fn foo1(_: dyn Zero()) {
+   |                ^^^^-- help: remove these parenthetical generics
+   |                |
+   |                expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:3:7
+   |
+LL | trait Zero { fn dummy(&self); }
+   |       ^^^^
+
+error[E0220]: associated type `Output` not found for `Zero`
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:5:16
+   |
+LL | fn foo1(_: dyn Zero()) {
+   |                ^^^^^^ associated type `Output` not found
+
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:10:16
+   |
+LL | fn foo2(_: dyn Zero<usize>) {
+   |                ^^^^------- help: remove these generics
+   |                |
+   |                expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:3:7
+   |
+LL | trait Zero { fn dummy(&self); }
+   |       ^^^^
+
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:14:16
+   |
+LL | fn foo3(_: dyn Zero <   usize   >) {
+   |                ^^^^-------------- help: remove these generics
+   |                |
+   |                expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:3:7
+   |
+LL | trait Zero { fn dummy(&self); }
+   |       ^^^^
+
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:18:16
+   |
+LL | fn foo4(_: dyn Zero(usize)) {
+   |                ^^^^------- help: remove these parenthetical generics
+   |                |
+   |                expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:3:7
+   |
+LL | trait Zero { fn dummy(&self); }
+   |       ^^^^
+
+error[E0220]: associated type `Output` not found for `Zero`
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:18:16
+   |
+LL | fn foo4(_: dyn Zero(usize)) {
+   |                ^^^^^^^^^^^ associated type `Output` not found
+
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:23:16
+   |
+LL | fn foo5(_: dyn Zero (   usize   )) {
+   |                ^^^^-------------- help: remove these parenthetical generics
+   |                |
+   |                expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:3:7
+   |
+LL | trait Zero { fn dummy(&self); }
+   |       ^^^^
 
 error[E0220]: associated type `Output` not found for `Zero`
-  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:5:15
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:23:16
    |
-LL | fn foo(_: dyn Zero())
-   |               ^^^^^^ associated type `Output` not found
+LL | fn foo5(_: dyn Zero (   usize   )) {
+   |                ^^^^^^^^^^^^^^^^^^ associated type `Output` not found
 
-error: aborting due to 2 previous errors
+error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0107, E0220.
 For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.rs
index 3e5342ca7df..5a47942e5af 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.rs
@@ -3,7 +3,7 @@
 trait Trait {}
 
 fn f<F:Trait(isize) -> isize>(x: F) {}
-//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
-//~| ERROR E0220
+//~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
+//~| ERROR associated type `Output` not found for `Trait`
 
 fn main() {}
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr
index c81402a3dcc..b88a316c0c9 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr
@@ -1,8 +1,16 @@
-error[E0107]: wrong number of type arguments: expected 0, found 1
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
   --> $DIR/unboxed-closure-sugar-wrong-trait.rs:5:8
    |
 LL | fn f<F:Trait(isize) -> isize>(x: F) {}
-   |        ^^^^^^^^^^^^ unexpected type argument
+   |        ^^^^^------- help: remove these parenthetical generics
+   |        |
+   |        expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $DIR/unboxed-closure-sugar-wrong-trait.rs:3:7
+   |
+LL | trait Trait {}
+   |       ^^^^^
 
 error[E0220]: associated type `Output` not found for `Trait`
   --> $DIR/unboxed-closure-sugar-wrong-trait.rs:5:24
diff --git a/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs b/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs
index a8fbb2ffaf0..1ec92500ce8 100644
--- a/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs
@@ -744,7 +744,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                     }
                     for segment in path.segments {
                         segment.ident.name.hash(&mut self.s);
-                        self.hash_generic_args(segment.generic_args().args);
+                        self.hash_generic_args(segment.args().args);
                     }
                 },
                 QPath::TypeRelative(ref ty, ref segment) => {