about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/hir/mod.rs29
-rw-r--r--src/librustc/middle/reachable.rs23
-rw-r--r--src/librustc/ty/mod.rs10
-rw-r--r--src/librustc/ty/subst.rs1
-rw-r--r--src/librustc/util/ppaux.rs5
-rw-r--r--src/librustc_lint/types.rs8
-rw-r--r--src/librustc_metadata/encoder.rs25
-rw-r--r--src/librustc_passes/ast_validation.rs7
-rw-r--r--src/librustc_privacy/lib.rs13
-rw-r--r--src/librustc_resolve/lib.rs51
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs42
-rw-r--r--src/librustc_typeck/astconv.rs663
-rw-r--r--src/librustc_typeck/check/method/confirm.rs82
-rw-r--r--src/librustc_typeck/check/mod.rs452
-rw-r--r--src/librustc_typeck/diagnostics.rs30
-rw-r--r--src/librustdoc/clean/mod.rs5
-rw-r--r--src/test/ui/bad/bad-mid-path-type-params.rs8
-rw-r--r--src/test/ui/bad/bad-mid-path-type-params.stderr18
-rw-r--r--src/test/ui/constructor-lifetime-args.rs8
-rw-r--r--src/test/ui/constructor-lifetime-args.stderr16
-rw-r--r--src/test/ui/error-codes/E0087.rs4
-rw-r--r--src/test/ui/error-codes/E0087.stderr12
-rw-r--r--src/test/ui/error-codes/E0088.stderr8
-rw-r--r--src/test/ui/error-codes/E0089.rs2
-rw-r--r--src/test/ui/error-codes/E0089.stderr6
-rw-r--r--src/test/ui/error-codes/E0090.rs2
-rw-r--r--src/test/ui/error-codes/E0090.stderr6
-rw-r--r--src/test/ui/error-codes/E0107.rs9
-rw-r--r--src/test/ui/error-codes/E0107.stderr14
-rw-r--r--src/test/ui/error-codes/E0244.stderr2
-rw-r--r--src/test/ui/generic/generic-arg-mismatch-recover.rs21
-rw-r--r--src/test/ui/generic/generic-arg-mismatch-recover.stderr31
-rw-r--r--src/test/ui/generic/generic-impl-more-params-with-defaults.stderr2
-rw-r--r--src/test/ui/generic/generic-type-more-params-with-defaults.stderr2
-rw-r--r--src/test/ui/issue-53251.rs4
-rw-r--r--src/test/ui/issue-53251.stderr13
-rw-r--r--src/test/ui/issues/issue-18423.rs4
-rw-r--r--src/test/ui/issues/issue-18423.stderr8
-rw-r--r--src/test/ui/issues/issue-3214.stderr4
-rw-r--r--src/test/ui/methods/method-call-lifetime-args-fail.rs8
-rw-r--r--src/test/ui/methods/method-call-lifetime-args-fail.stderr16
-rw-r--r--src/test/ui/seq-args.stderr8
-rw-r--r--src/test/ui/structs/structure-constructor-type-mismatch.stderr8
-rw-r--r--src/test/ui/traits/trait-object-vs-lifetime.rs2
-rw-r--r--src/test/ui/traits/trait-object-vs-lifetime.stderr6
-rw-r--r--src/test/ui/traits/trait-test-2.rs4
-rw-r--r--src/test/ui/traits/trait-test-2.stderr12
-rw-r--r--src/test/ui/typeck/typeck-builtin-bound-type-parameters.rs4
-rw-r--r--src/test/ui/typeck/typeck-builtin-bound-type-parameters.stderr28
-rw-r--r--src/test/ui/typeck/typeck_type_placeholder_lifetime_1.stderr4
-rw-r--r--src/test/ui/typeck/typeck_type_placeholder_lifetime_2.stderr4
-rw-r--r--src/test/ui/ufcs/ufcs-qpath-missing-params.rs2
-rw-r--r--src/test/ui/ufcs/ufcs-qpath-missing-params.stderr4
-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.stderr4
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr4
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr4
57 files changed, 973 insertions, 801 deletions
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 795dba93abd..43cc33f422f 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -401,6 +401,13 @@ impl GenericArg {
             GenericArg::Type(t) => t.span,
         }
     }
+
+    pub fn id(&self) -> NodeId {
+        match self {
+            GenericArg::Lifetime(l) => l.id,
+            GenericArg::Type(t) => t.id,
+        }
+    }
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
@@ -445,6 +452,22 @@ impl GenericArgs {
         }
         bug!("GenericArgs::inputs: not a `Fn(T) -> U`");
     }
+
+    pub fn own_counts(&self) -> GenericParamCount {
+        // 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();
+
+        for arg in &self.args {
+            match arg {
+                GenericArg::Lifetime(_) => own_counts.lifetimes += 1,
+                GenericArg::Type(_) => own_counts.types += 1,
+            };
+        }
+
+        own_counts
+    }
 }
 
 /// A modifier on a bound, currently this is only used for `?Sized`, where the
@@ -503,6 +526,7 @@ pub struct GenericParam {
     pub kind: GenericParamKind,
 }
 
+#[derive(Default)]
 pub struct GenericParamCount {
     pub lifetimes: usize,
     pub types: usize,
@@ -533,10 +557,7 @@ impl 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 {
-            lifetimes: 0,
-            types: 0,
-        };
+        let mut own_counts: GenericParamCount = Default::default();
 
         for param in &self.params {
             match param.kind {
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index a09942258e2..3d8bb6b825b 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -20,7 +20,7 @@ use hir::map as hir_map;
 use hir::def::Def;
 use hir::def_id::{DefId, CrateNum};
 use rustc_data_structures::sync::Lrc;
-use ty::{self, TyCtxt, GenericParamDefKind};
+use ty::{self, TyCtxt};
 use ty::query::Providers;
 use middle::privacy;
 use session::config;
@@ -34,18 +34,6 @@ use hir::intravisit::{Visitor, NestedVisitorMap};
 use hir::itemlikevisit::ItemLikeVisitor;
 use hir::intravisit;
 
-// Returns true if the given set of generics implies that the item it's
-// associated with must be inlined.
-fn generics_require_inlining(generics: &ty::Generics) -> bool {
-    for param in &generics.params {
-        match param.kind {
-            GenericParamDefKind::Lifetime { .. } => {}
-            GenericParamDefKind::Type { .. } => return true,
-        }
-    }
-    false
-}
-
 // Returns true if the given item must be inlined because it may be
 // monomorphized or it was marked with `#[inline]`. This will only return
 // true for functions.
@@ -60,7 +48,7 @@ fn item_might_be_inlined(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         hir::ItemKind::Impl(..) |
         hir::ItemKind::Fn(..) => {
             let generics = tcx.generics_of(tcx.hir.local_def_id(item.id));
-            generics_require_inlining(generics)
+            generics.requires_monomorphization(tcx)
         }
         _ => false,
     }
@@ -71,7 +59,7 @@ fn method_might_be_inlined<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                      impl_src: DefId) -> bool {
     let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id.owner_def_id());
     let generics = tcx.generics_of(tcx.hir.local_def_id(impl_item.id));
-    if codegen_fn_attrs.requests_inline() || generics_require_inlining(generics) {
+    if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) {
         return true
     }
     if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_src) {
@@ -189,8 +177,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
                     hir::ImplItemKind::Method(..) => {
                         let attrs = self.tcx.codegen_fn_attrs(def_id);
                         let generics = self.tcx.generics_of(def_id);
-                        if generics_require_inlining(&generics) ||
-                                attrs.requests_inline() {
+                        if generics.requires_monomorphization(self.tcx) || attrs.requests_inline() {
                             true
                         } else {
                             let impl_did = self.tcx
@@ -203,7 +190,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
                             match self.tcx.hir.expect_item(impl_node_id).node {
                                 hir::ItemKind::Impl(..) => {
                                     let generics = self.tcx.generics_of(impl_did);
-                                    generics_require_inlining(&generics)
+                                    generics.requires_monomorphization(self.tcx)
                                 }
                                 _ => false
                             }
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 6c27d527ae8..f6d21ca5861 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -881,6 +881,7 @@ impl GenericParamDef {
     }
 }
 
+#[derive(Default)]
 pub struct GenericParamCount {
     pub lifetimes: usize,
     pub types: usize,
@@ -913,15 +914,12 @@ impl<'a, 'gcx, '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 {
-            lifetimes: 0,
-            types: 0,
-        };
+        let mut own_counts: GenericParamCount = Default::default();
 
         for param in &self.params {
             match param.kind {
                 GenericParamDefKind::Lifetime => own_counts.lifetimes += 1,
-                GenericParamDefKind::Type {..} => own_counts.types += 1,
+                GenericParamDefKind::Type { .. } => own_counts.types += 1,
             };
         }
 
@@ -931,7 +929,7 @@ impl<'a, 'gcx, 'tcx> Generics {
     pub fn requires_monomorphization(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
         for param in &self.params {
             match param.kind {
-                GenericParamDefKind::Type {..} => return true,
+                GenericParamDefKind::Type { .. } => return true,
                 GenericParamDefKind::Lifetime => {}
             }
         }
diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs
index 2e3c6df9754..a6ff979f472 100644
--- a/src/librustc/ty/subst.rs
+++ b/src/librustc/ty/subst.rs
@@ -231,7 +231,6 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
                     mk_kind: &mut F)
     where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Kind<'tcx>
     {
-
         if let Some(def_id) = defs.parent {
             let parent_defs = tcx.generics_of(def_id);
             Substs::fill_item(substs, tcx, parent_defs, mk_kind);
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index bb54e183604..9513086667b 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -262,10 +262,7 @@ impl PrintContext {
         let verbose = self.is_verbose;
         let mut num_supplied_defaults = 0;
         let mut has_self = false;
-        let mut own_counts = GenericParamCount {
-            lifetimes: 0,
-            types: 0,
-        };
+        let mut own_counts: GenericParamCount = Default::default();
         let mut is_value_path = false;
         let fn_trait_kind = ty::tls::with(|tcx| {
             // Unfortunately, some kinds of items (e.g., closures) don't have
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 46b33255b45..32a68738fb2 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -819,14 +819,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
     fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
         if let hir::ItemKind::Enum(ref enum_definition, _) = it.node {
             let item_def_id = cx.tcx.hir.local_def_id(it.id);
-            let generics = cx.tcx.generics_of(item_def_id);
-            for param in &generics.params {
-                match param.kind {
-                    ty::GenericParamDefKind::Lifetime { .. } => {},
-                    ty::GenericParamDefKind::Type { .. } => return,
-                }
-            }
-            // Sizes only make sense for non-generic types.
             let t = cx.tcx.type_of(item_def_id);
             let ty = cx.tcx.erase_regions(&t);
             match cx.layout_of(ty) {
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 4b5c9d68fd7..1b13c240a87 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -1262,12 +1262,9 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                 hir::ItemKind::Const(..) => self.encode_optimized_mir(def_id),
                 hir::ItemKind::Fn(_, header, ..) => {
                     let generics = tcx.generics_of(def_id);
-                    let has_types = generics.params.iter().any(|param| match param.kind {
-                        ty::GenericParamDefKind::Type { .. } => true,
-                        _ => false,
-                    });
                     let needs_inline =
-                        (has_types || tcx.codegen_fn_attrs(def_id).requests_inline()) &&
+                        (generics.requires_monomorphization(tcx) ||
+                         tcx.codegen_fn_attrs(def_id).requests_inline()) &&
                             !self.metadata_output_only();
                     let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
                     if needs_inline
@@ -1683,15 +1680,17 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
     }
 
     fn encode_info_for_generics(&mut self, generics: &hir::Generics) {
-        generics.params.iter().for_each(|param| match param.kind {
-            hir::GenericParamKind::Lifetime { .. } => {}
-            hir::GenericParamKind::Type { ref default, .. } => {
-                let def_id = self.tcx.hir.local_def_id(param.id);
-                let has_default = Untracked(default.is_some());
-                let encode_info = IsolatedEncoder::encode_info_for_ty_param;
-                self.record(def_id, encode_info, (def_id, has_default));
+        for param in &generics.params {
+            match param.kind {
+                hir::GenericParamKind::Lifetime { .. } => {}
+                hir::GenericParamKind::Type { ref default, .. } => {
+                    let def_id = self.tcx.hir.local_def_id(param.id);
+                    let has_default = Untracked(default.is_some());
+                    let encode_info = IsolatedEncoder::encode_info_for_ty_param;
+                    self.record(def_id, encode_info, (def_id, has_default));
+                }
             }
-        });
+        }
     }
 
     fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 99ea62e8029..11d1d85c97d 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -539,10 +539,9 @@ impl<'a> Visitor<'a> for NestedImplTraitVisitor<'a> {
     fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) {
         match *generic_args {
             GenericArgs::AngleBracketed(ref data) => {
-                data.args.iter().for_each(|arg| match arg {
-                    GenericArg::Type(ty) => self.visit_ty(ty),
-                    _ => {}
-                });
+                for arg in &data.args {
+                    self.visit_generic_arg(arg)
+                }
                 for type_binding in &data.bindings {
                     // Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
                     // are allowed to contain nested `impl Trait`.
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index fcb1b65014b..d9c3fc221dc 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -23,7 +23,7 @@ extern crate rustc_typeck;
 extern crate syntax_pos;
 extern crate rustc_data_structures;
 
-use rustc::hir::{self, GenericParamKind, PatKind};
+use rustc::hir::{self, PatKind};
 use rustc::hir::def::Def;
 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
@@ -1270,14 +1270,11 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
     }
 
     fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
-        generics.params.iter().for_each(|param| match param.kind {
-            GenericParamKind::Lifetime { .. } => {}
-            GenericParamKind::Type { .. } => {
-                for bound in &param.bounds {
-                    self.check_generic_bound(bound);
-                }
+        for param in &generics.params {
+            for bound in &param.bounds {
+                self.check_generic_bound(bound);
             }
-        });
+        }
         for predicate in &generics.where_clause.predicates {
             match predicate {
                 &hir::WherePredicate::BoundPredicate(ref bound_pred) => {
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 282589c4e68..71a7fde2029 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -822,11 +822,12 @@ impl<'a, 'tcx, 'cl> Visitor<'tcx> for Resolver<'a, 'cl> {
             .filter_map(|param| match param.kind {
                 GenericParamKind::Lifetime { .. } => None,
                 GenericParamKind::Type { ref default, .. } => {
-                    if found_default || default.is_some() {
-                        found_default = true;
-                        return Some((Ident::with_empty_ctxt(param.ident.name), Def::Err));
+                    found_default |= default.is_some();
+                    if found_default {
+                        Some((Ident::with_empty_ctxt(param.ident.name), Def::Err))
+                    } else {
+                        None
                     }
-                    None
                 }
             }));
 
@@ -2339,28 +2340,30 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
             HasTypeParameters(generics, rib_kind) => {
                 let mut function_type_rib = Rib::new(rib_kind);
                 let mut seen_bindings = FxHashMap();
-                generics.params.iter().for_each(|param| match param.kind {
-                    GenericParamKind::Lifetime { .. } => {}
-                    GenericParamKind::Type { .. } => {
-                        let ident = param.ident.modern();
-                        debug!("with_type_parameter_rib: {}", param.id);
-
-                        if seen_bindings.contains_key(&ident) {
-                            let span = seen_bindings.get(&ident).unwrap();
-                            let err = ResolutionError::NameAlreadyUsedInTypeParameterList(
-                                ident.name,
-                                span,
-                            );
-                            resolve_error(self, param.ident.span, err);
-                        }
-                        seen_bindings.entry(ident).or_insert(param.ident.span);
+                for param in &generics.params {
+                    match param.kind {
+                        GenericParamKind::Lifetime { .. } => {}
+                        GenericParamKind::Type { .. } => {
+                            let ident = param.ident.modern();
+                            debug!("with_type_parameter_rib: {}", param.id);
+
+                            if seen_bindings.contains_key(&ident) {
+                                let span = seen_bindings.get(&ident).unwrap();
+                                let err = ResolutionError::NameAlreadyUsedInTypeParameterList(
+                                    ident.name,
+                                    span,
+                                );
+                                resolve_error(self, param.ident.span, err);
+                            }
+                            seen_bindings.entry(ident).or_insert(param.ident.span);
 
-                    // Plain insert (no renaming).
-                    let def = Def::TyParam(self.definitions.local_def_id(param.id));
-                        function_type_rib.bindings.insert(ident, def);
-                        self.record_def(param.id, PathResolution::new(def));
+                        // Plain insert (no renaming).
+                        let def = Def::TyParam(self.definitions.local_def_id(param.id));
+                            function_type_rib.bindings.insert(ident, def);
+                            self.record_def(param.id, PathResolution::new(def));
+                        }
                     }
-                });
+                }
                 self.ribs[TypeNS].push(function_type_rib);
             }
 
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index c6cec2ecca6..dc9310cdcda 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -824,10 +824,12 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
             if let Some(ref generic_args) = seg.args {
                 match **generic_args {
                     ast::GenericArgs::AngleBracketed(ref data) => {
-                        data.args.iter().for_each(|arg| match arg {
-                            ast::GenericArg::Type(ty) => self.visit_ty(ty),
-                            _ => {}
-                        });
+                        for arg in &data.args {
+                            match arg {
+                                ast::GenericArg::Type(ty) => self.visit_ty(ty),
+                                _ => {}
+                            }
+                        }
                     }
                     ast::GenericArgs::Parenthesized(ref data) => {
                         for t in &data.inputs {
@@ -911,10 +913,12 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
         // Explicit types in the turbo-fish.
         if let Some(ref generic_args) = seg.args {
             if let ast::GenericArgs::AngleBracketed(ref data) = **generic_args {
-                data.args.iter().for_each(|arg| match arg {
-                    ast::GenericArg::Type(ty) => self.visit_ty(ty),
-                    _ => {}
-                });
+                for arg in &data.args {
+                    match arg {
+                        ast::GenericArg::Type(ty) => self.visit_ty(ty),
+                        _ => {}
+                    }
+                }
             }
         }
 
@@ -1522,19 +1526,21 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
     }
 
     fn visit_generics(&mut self, generics: &'l ast::Generics) {
-        generics.params.iter().for_each(|param| match param.kind {
-            ast::GenericParamKind::Lifetime { .. } => {}
-            ast::GenericParamKind::Type { ref default, .. } => {
-                for bound in &param.bounds {
-                    if let ast::GenericBound::Trait(ref trait_ref, _) = *bound {
-                        self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path)
+        for param in &generics.params {
+            match param.kind {
+                ast::GenericParamKind::Lifetime { .. } => {}
+                ast::GenericParamKind::Type { ref default, .. } => {
+                    for bound in &param.bounds {
+                        if let ast::GenericBound::Trait(ref trait_ref, _) = *bound {
+                            self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path)
+                        }
+                    }
+                    if let Some(ref ty) = default {
+                        self.visit_ty(&ty);
                     }
-                }
-                if let Some(ref ty) = default {
-                    self.visit_ty(&ty);
                 }
             }
-        });
+        }
     }
 
     fn visit_ty(&mut self, t: &'l ast::Ty) {
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 0bc7ae04185..ccdb751bc4e 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -13,27 +13,31 @@
 //! is parameterized by an instance of `AstConv`.
 
 use rustc_data_structures::accumulate_vec::AccumulateVec;
-use hir::{self, GenericArg};
+use rustc_data_structures::array_vec::ArrayVec;
+use hir::{self, GenericArg, GenericArgs};
 use hir::def::Def;
 use hir::def_id::DefId;
+use hir::HirVec;
 use middle::resolve_lifetime as rl;
 use namespace::Namespace;
-use rustc::ty::subst::{Subst, Substs};
+use rustc::ty::subst::{Kind, Subst, Substs};
 use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
-use rustc::ty::GenericParamDefKind;
+use rustc::ty::{GenericParamDef, GenericParamDefKind};
 use rustc::ty::wf::object_region_bounds;
 use rustc_target::spec::abi;
 use std::slice;
 use require_c_abi_if_variadic;
 use util::common::ErrorReported;
 use util::nodemap::{FxHashSet, FxHashMap};
-use errors::FatalError;
+use errors::{FatalError, DiagnosticId};
+use lint;
 
 use std::iter;
 use syntax::ast;
+use syntax::ptr::P;
 use syntax::feature_gate::{GateIssue, emit_feature_err};
-use syntax_pos::Span;
+use syntax_pos::{Span, MultiSpan};
 
 pub trait AstConv<'gcx, 'tcx> {
     fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>;
@@ -88,9 +92,17 @@ struct ConvertedBinding<'tcx> {
     span: Span,
 }
 
-struct ParamRange {
-    required: usize,
-    accepted: usize
+#[derive(PartialEq)]
+enum GenericArgPosition {
+    Type,
+    Value, // e.g. functions
+    MethodCall,
+}
+
+// FIXME(#53525): these error codes should all be unified.
+struct GenericArgMismatchErrorCode {
+    lifetimes: (&'static str, &'static str),
+    types: (&'static str, &'static str),
 }
 
 /// Dummy type used for the `Self` of a `TraitRef` created for converting
@@ -176,21 +188,370 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
         -> &'tcx Substs<'tcx>
     {
 
-        let (substs, assoc_bindings) =
-            item_segment.with_generic_args(|generic_args| {
-                self.create_substs_for_ast_path(
-                    span,
-                    def_id,
-                    generic_args,
-                    item_segment.infer_types,
-                    None)
-            });
+        let (substs, assoc_bindings) = item_segment.with_generic_args(|generic_args| {
+            self.create_substs_for_ast_path(
+                span,
+                def_id,
+                generic_args,
+                item_segment.infer_types,
+                None,
+            )
+        });
 
-        assoc_bindings.first().map(|b| self.prohibit_projection(b.span));
+        assoc_bindings.first().map(|b| Self::prohibit_assoc_ty_binding(self.tcx(), b.span));
 
         substs
     }
 
+    /// Report error if there is an explicit type parameter when using `impl Trait`.
+    fn check_impl_trait(
+        tcx: TyCtxt,
+        span: Span,
+        seg: &hir::PathSegment,
+        generics: &ty::Generics,
+    ) -> bool {
+        let explicit = !seg.infer_types;
+        let impl_trait = generics.params.iter().any(|param| match param.kind {
+            ty::GenericParamDefKind::Type {
+                synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), ..
+            } => true,
+            _ => false,
+        });
+
+        if explicit && impl_trait {
+            let mut err = struct_span_err! {
+                tcx.sess,
+                span,
+                E0632,
+                "cannot provide explicit type parameters when `impl Trait` is \
+                used in argument position."
+            };
+
+            err.emit();
+        }
+
+        impl_trait
+    }
+
+    /// Check that the correct number of generic arguments have been provided.
+    /// Used specifically for function calls.
+    pub fn check_generic_arg_count_for_call(
+        tcx: TyCtxt,
+        span: Span,
+        def: &ty::Generics,
+        seg: &hir::PathSegment,
+        is_method_call: bool,
+    ) -> bool {
+        let empty_args = P(hir::GenericArgs {
+            args: HirVec::new(), bindings: HirVec::new(), parenthesized: false,
+        });
+        let suppress_mismatch = Self::check_impl_trait(tcx, span, seg, &def);
+        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_types || suppress_mismatch, // `infer_types`
+            GenericArgMismatchErrorCode {
+                lifetimes: ("E0090", "E0088"),
+                types: ("E0089", "E0087"),
+            },
+        )
+    }
+
+    /// Check that the correct number of generic arguments have been provided.
+    /// This is used both for datatypes and function calls.
+    fn check_generic_arg_count(
+        tcx: TyCtxt,
+        span: Span,
+        def: &ty::Generics,
+        args: &hir::GenericArgs,
+        position: GenericArgPosition,
+        has_self: bool,
+        infer_types: bool,
+        error_codes: GenericArgMismatchErrorCode,
+    ) -> bool {
+        // 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 arg_counts = args.own_counts();
+        let infer_lifetimes = position != 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
+                }
+            };
+        }
+
+        if position != GenericArgPosition::Type && !args.bindings.is_empty() {
+            AstConv::prohibit_assoc_ty_binding(tcx, args.bindings[0].span);
+        }
+
+        // Prohibit explicit lifetime arguments if late-bound lifetime parameters are present.
+        if !infer_lifetimes {
+            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 {
+                    let mut err = tcx.sess.struct_span_err(span, msg);
+                    err.span_note(span_late, note);
+                    err.emit();
+                    return true;
+                } else {
+                    let mut multispan = MultiSpan::from_span(span);
+                    multispan.push_span_label(span_late, note.to_string());
+                    tcx.lint_node(lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS,
+                                  args.args[0].id(), multispan, msg);
+                    return false;
+                }
+            }
+        }
+
+        let check_kind_count = |error_code: (&str, &str),
+                                kind,
+                                required,
+                                permitted,
+                                provided,
+                                offset| {
+            // We enforce the following: `required` <= `provided` <= `permitted`.
+            // For kinds without defaults (i.e. lifetimes), `required == permitted`.
+            // For other kinds (i.e. types), `permitted` may be greater than `required`.
+            if required <= provided && provided <= permitted {
+                return false;
+            }
+
+            // 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 ")
+                }
+            } else {
+                (required, "")
+            };
+
+            let mut span = span;
+            let label = if required == permitted && provided > permitted {
+                let diff = provided - permitted;
+                if diff == 1 {
+                    // In the case when the user has provided too many arguments,
+                    // we want to point to the first unexpected argument.
+                    let first_superfluous_arg: &GenericArg = &args.args[offset + permitted];
+                    span = first_superfluous_arg.span();
+                }
+                format!(
+                    "{}unexpected {} argument{}",
+                    if diff != 1 { format!("{} ", diff) } else { String::new() },
+                    kind,
+                    if diff != 1 { "s" } else { "" },
+                )
+            } else {
+                format!(
+                    "expected {}{} {} argument{}",
+                    quantifier,
+                    bound,
+                    kind,
+                    if required != 1 { "s" } else { "" },
+                )
+            };
+
+            tcx.sess.struct_span_err_with_code(
+                span,
+                &format!(
+                    "wrong number of {} arguments: expected {}{}, found {}",
+                    kind,
+                    quantifier,
+                    bound,
+                    provided,
+                ),
+                DiagnosticId::Error({
+                    if provided <= permitted {
+                        error_code.0
+                    } else {
+                        error_code.1
+                    }
+                }.into())
+            ).span_label(span, label).emit();
+
+            provided > required // `suppress_error`
+        };
+
+        if !infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes {
+            check_kind_count(
+                error_codes.lifetimes,
+                "lifetime",
+                param_counts.lifetimes,
+                param_counts.lifetimes,
+                arg_counts.lifetimes,
+                0,
+            );
+        }
+        if !infer_types
+            || arg_counts.types > param_counts.types - defaults.types - has_self as usize {
+            check_kind_count(
+                error_codes.types,
+                "type",
+                param_counts.types - defaults.types - has_self as usize,
+                param_counts.types - has_self as usize,
+                arg_counts.types,
+                arg_counts.lifetimes,
+            )
+        } else {
+            false
+        }
+    }
+
+    /// Creates the relevant generic argument substitutions
+    /// corresponding to a set of generic parameters.
+    pub fn create_substs_for_generic_args<'a, 'b, A, P, I>(
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+        def_id: DefId,
+        parent_substs: &[Kind<'tcx>],
+        has_self: bool,
+        self_ty: Option<Ty<'tcx>>,
+        args_for_def_id: A,
+        provided_kind: P,
+        inferred_kind: I,
+    ) -> &'tcx Substs<'tcx> where
+        A: Fn(DefId) -> (Option<&'b GenericArgs>, bool),
+        P: Fn(&GenericParamDef, &GenericArg) -> Kind<'tcx>,
+        I: Fn(Option<&[Kind<'tcx>]>, &GenericParamDef, bool) -> Kind<'tcx>
+    {
+        // Collect the segments of the path: we need to substitute arguments
+        // for parameters throughout the entire path (wherever there are
+        // generic parameters).
+        let mut parent_defs = tcx.generics_of(def_id);
+        let count = parent_defs.count();
+        let mut stack = vec![(def_id, parent_defs)];
+        while let Some(def_id) = parent_defs.parent {
+            parent_defs = tcx.generics_of(def_id);
+            stack.push((def_id, parent_defs));
+        }
+
+        // We manually build up the substitution, rather than using convenience
+        // methods in subst.rs so that we can iterate over the arguments and
+        // parameters in lock-step linearly, rather than trying to match each pair.
+        let mut substs: AccumulateVec<[Kind<'tcx>; 8]> = if count <= 8 {
+            AccumulateVec::Array(ArrayVec::new())
+        } else {
+            AccumulateVec::Heap(Vec::with_capacity(count))
+        };
+
+        fn push_kind<'tcx>(substs: &mut AccumulateVec<[Kind<'tcx>; 8]>, kind: Kind<'tcx>) {
+            match substs {
+                AccumulateVec::Array(ref mut arr) => arr.push(kind),
+                AccumulateVec::Heap(ref mut vec) => vec.push(kind),
+            }
+        }
+
+        // Iterate over each segment of the path.
+        while let Some((def_id, defs)) = stack.pop() {
+            let mut params = defs.params.iter().peekable();
+
+            // If we have already computed substitutions for parents, we can use those directly.
+            while let Some(&param) = params.peek() {
+                if let Some(&kind) = parent_substs.get(param.index as usize) {
+                    push_kind(&mut substs, kind);
+                    params.next();
+                } else {
+                    break;
+                }
+            }
+
+            // (Unless it's been handled in `parent_substs`) `Self` is handled first.
+            if has_self {
+                if let Some(&param) = params.peek() {
+                    if param.index == 0 {
+                        if let GenericParamDefKind::Type { .. } = param.kind {
+                            push_kind(&mut substs, self_ty.map(|ty| ty.into())
+                                .unwrap_or_else(|| inferred_kind(None, param, true)));
+                            params.next();
+                        }
+                    }
+                }
+            }
+
+            // Check whether this segment takes generic arguments and the user has provided any.
+            let (generic_args, infer_types) = args_for_def_id(def_id);
+
+            let mut args = generic_args.iter().flat_map(|generic_args| generic_args.args.iter())
+                .peekable();
+
+            loop {
+                // We're going to iterate through the generic arguments that the user
+                // provided, matching them with the generic parameters we expect.
+                // Mismatches can occur as a result of elided lifetimes, or for malformed
+                // input. We try to handle both sensibly.
+                match (args.peek(), params.peek()) {
+                    (Some(&arg), Some(&param)) => {
+                        match (arg, &param.kind) {
+                            (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime)
+                            | (GenericArg::Type(_), GenericParamDefKind::Type { .. }) => {
+                                push_kind(&mut substs, provided_kind(param, arg));
+                                args.next();
+                                params.next();
+                            }
+                            (GenericArg::Lifetime(_), GenericParamDefKind::Type { .. }) => {
+                                // We expected a type argument, but got a lifetime
+                                // argument. This is an error, but we need to handle it
+                                // gracefully so we can report sensible errors. In this
+                                // case, we're simply going to infer this argument.
+                                args.next();
+                            }
+                            (GenericArg::Type(_), GenericParamDefKind::Lifetime) => {
+                                // We expected a lifetime argument, but got a type
+                                // argument. That means we're inferring the lifetimes.
+                                push_kind(&mut substs, inferred_kind(None, param, infer_types));
+                                params.next();
+                            }
+                        }
+                    }
+                    (Some(_), None) => {
+                        // We should never be able to reach this point with well-formed input.
+                        // Getting to this point means the user supplied more arguments than
+                        // there are parameters.
+                        args.next();
+                    }
+                    (None, Some(&param)) => {
+                        // If there are fewer arguments than parameters, it means
+                        // we're inferring the remaining arguments.
+                        match param.kind {
+                            GenericParamDefKind::Lifetime | GenericParamDefKind::Type { .. } => {
+                                let kind = inferred_kind(Some(&substs), param, infer_types);
+                                push_kind(&mut substs, kind);
+                            }
+                        }
+                        args.next();
+                        params.next();
+                    }
+                    (None, None) => break,
+                }
+            }
+        }
+
+        tcx.intern_substs(&substs)
+    }
+
     /// Given the type/region arguments provided to some path (along with
     /// an implicit Self, if this is a trait reference) returns the complete
     /// set of substitutions. This may involve applying defaulted type parameters.
@@ -204,60 +565,33 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
         self_ty: Option<Ty<'tcx>>)
         -> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>)
     {
-        let tcx = self.tcx();
-
-        debug!("create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \
-               generic_args={:?})",
-               def_id, self_ty, generic_args);
-
         // If the type is parameterized by this region, then replace this
         // region with the current anon region binding (in other words,
         // whatever & would get replaced with).
+        debug!("create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \
+               generic_args={:?})",
+               def_id, self_ty, generic_args);
 
-        // FIXME(varkor): Separating out the parameters is messy.
-        let lifetimes: Vec<_> = generic_args.args.iter().filter_map(|arg| match arg {
-            GenericArg::Lifetime(lt) => Some(lt),
-            _ => None,
-        }).collect();
-        let types: Vec<_> = generic_args.args.iter().filter_map(|arg| match arg {
-            GenericArg::Type(ty) => Some(ty),
-            _ => None,
-        }).collect();
-        let lt_provided = lifetimes.len();
-        let ty_provided = types.len();
-
-        let decl_generics = tcx.generics_of(def_id);
-        let mut lt_accepted = 0;
-        let mut ty_params = ParamRange { required: 0, accepted: 0 };
-        for param in &decl_generics.params {
-            match param.kind {
-                GenericParamDefKind::Lifetime => {
-                    lt_accepted += 1;
-                }
-                GenericParamDefKind::Type { has_default, .. } => {
-                    ty_params.accepted += 1;
-                    if !has_default {
-                        ty_params.required += 1;
-                    }
-                }
-            };
-        }
-        if self_ty.is_some() {
-            ty_params.required -= 1;
-            ty_params.accepted -= 1;
-        }
-
-        if lt_accepted != lt_provided {
-            report_lifetime_number_error(tcx, span, lt_provided, lt_accepted);
-        }
+        let tcx = self.tcx();
+        let generic_params = tcx.generics_of(def_id);
 
         // If a self-type was declared, one should be provided.
-        assert_eq!(decl_generics.has_self, self_ty.is_some());
+        assert_eq!(generic_params.has_self, self_ty.is_some());
 
-        // Check the number of type parameters supplied by the user.
-        if !infer_types || ty_provided > ty_params.required {
-            check_type_argument_count(tcx, span, ty_provided, ty_params);
-        }
+        let has_self = generic_params.has_self;
+        Self::check_generic_arg_count(
+            self.tcx(),
+            span,
+            &generic_params,
+            &generic_args,
+            GenericArgPosition::Type,
+            has_self,
+            infer_types,
+            GenericArgMismatchErrorCode {
+                lifetimes: ("E0107", "E0107"),
+                types: ("E0243", "E0244"),
+            },
+        );
 
         let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF);
         let default_needs_object_self = |param: &ty::GenericParamDef| {
@@ -274,71 +608,74 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
             false
         };
 
-        let own_self = self_ty.is_some() as usize;
-        let substs = Substs::for_item(tcx, def_id, |param, substs| {
-            match param.kind {
-                GenericParamDefKind::Lifetime => {
-                    let i = param.index as usize - own_self;
-                    if let Some(lt) = lifetimes.get(i) {
-                        self.ast_region_to_region(lt, Some(param)).into()
-                    } else {
-                        tcx.types.re_static.into()
+        let substs = Self::create_substs_for_generic_args(
+            self.tcx(),
+            def_id,
+            &[][..],
+            self_ty.is_some(),
+            self_ty,
+            // Provide the generic args, and whether types should be inferred.
+            |_| (Some(generic_args), infer_types),
+            // Provide substitutions for parameters for which (valid) arguments have been provided.
+            |param, arg| {
+                match (&param.kind, arg) {
+                    (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
+                        self.ast_region_to_region(&lt, Some(param)).into()
                     }
-                }
-                GenericParamDefKind::Type { has_default, .. } => {
-                    let i = param.index as usize;
-
-                    // Handle Self first, so we can adjust the index to match the AST.
-                    if let (0, Some(ty)) = (i, self_ty) {
-                        return ty.into();
+                    (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
+                        self.ast_ty_to_ty(&ty).into()
                     }
-
-                    let i = i - (lt_accepted + own_self);
-                    if i < ty_provided {
-                        // A provided type parameter.
-                        self.ast_ty_to_ty(&types[i]).into()
-                    } else if infer_types {
-                        // No type parameters were provided, we can infer all.
-                        if !default_needs_object_self(param) {
-                            self.ty_infer_for_def(param, span).into()
+                    _ => unreachable!(),
+                }
+            },
+            // Provide substitutions for parameters for which arguments are inferred.
+            |substs, param, infer_types| {
+                match param.kind {
+                    GenericParamDefKind::Lifetime => tcx.types.re_static.into(),
+                    GenericParamDefKind::Type { has_default, .. } => {
+                        if !infer_types && has_default {
+                            // No type parameter provided, but a default exists.
+
+                            // If we are converting an object type, then the
+                            // `Self` parameter is unknown. However, some of the
+                            // other type parameters may reference `Self` in their
+                            // defaults. This will lead to an ICE if we are not
+                            // careful!
+                            if default_needs_object_self(param) {
+                                struct_span_err!(tcx.sess, span, E0393,
+                                                    "the type parameter `{}` must be explicitly \
+                                                    specified",
+                                                    param.name)
+                                    .span_label(span,
+                                                format!("missing reference to `{}`", param.name))
+                                    .note(&format!("because of the default `Self` reference, \
+                                                    type parameters must be specified on object \
+                                                    types"))
+                                    .emit();
+                                tcx.types.err.into()
+                            } else {
+                                // This is a default type parameter.
+                                self.normalize_ty(
+                                    span,
+                                    tcx.at(span).type_of(param.def_id)
+                                        .subst_spanned(tcx, substs.unwrap(), Some(span))
+                                ).into()
+                            }
+                        } else if infer_types {
+                            // No type parameters were provided, we can infer all.
+                            if !default_needs_object_self(param) {
+                                self.ty_infer_for_def(param, span).into()
+                            } else {
+                                self.ty_infer(span).into()
+                            }
                         } else {
-                            self.ty_infer(span).into()
-                        }
-                    } else if has_default {
-                        // No type parameter provided, but a default exists.
-
-                        // If we are converting an object type, then the
-                        // `Self` parameter is unknown. However, some of the
-                        // other type parameters may reference `Self` in their
-                        // defaults. This will lead to an ICE if we are not
-                        // careful!
-                        if default_needs_object_self(param) {
-                            struct_span_err!(tcx.sess, span, E0393,
-                                             "the type parameter `{}` must be explicitly \
-                                             specified",
-                                             param.name)
-                                .span_label(span,
-                                            format!("missing reference to `{}`", param.name))
-                                .note(&format!("because of the default `Self` reference, \
-                                                type parameters must be specified on object \
-                                                types"))
-                                .emit();
+                            // We've already errored above about the mismatch.
                             tcx.types.err.into()
-                        } else {
-                            // This is a default type parameter.
-                            self.normalize_ty(
-                                span,
-                                tcx.at(span).type_of(param.def_id)
-                                    .subst_spanned(tcx, substs, Some(span))
-                            ).into()
                         }
-                    } else {
-                        // We've already errored above about the mismatch.
-                        tcx.types.err.into()
                     }
                 }
-            }
-        });
+            },
+        );
 
         let assoc_bindings = generic_args.bindings.iter().map(|binding| {
             ConvertedBinding {
@@ -348,8 +685,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
             }
         }).collect();
 
-        debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}",
-               decl_generics, self_ty, substs);
+        debug!("create_substs_for_ast_path(generic_params={:?}, self_ty={:?}) -> {:?}",
+               generic_params, self_ty, substs);
 
         (substs, assoc_bindings)
     }
@@ -444,7 +781,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
                                                  trait_def_id,
                                                  self_ty,
                                                  trait_segment);
-        assoc_bindings.first().map(|b| self.prohibit_projection(b.span));
+        assoc_bindings.first().map(|b| AstConv::prohibit_assoc_ty_binding(self.tcx(), b.span));
         ty::TraitRef::new(trait_def_id, substs)
     }
 
@@ -978,7 +1315,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
         self.normalize_ty(span, tcx.mk_projection(item_def_id, trait_ref.substs))
     }
 
-    pub fn prohibit_generics(&self, segments: &[hir::PathSegment]) {
+    pub fn prohibit_generics<'a, T: IntoIterator<Item = &'a hir::PathSegment>>(&self, segments: T) {
         for segment in segments {
             segment.with_generic_args(|generic_args| {
                 let (mut err_for_lt, mut err_for_ty) = (false, false);
@@ -1009,15 +1346,15 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
                     }
                 }
                 for binding in &generic_args.bindings {
-                    self.prohibit_projection(binding.span);
+                    Self::prohibit_assoc_ty_binding(self.tcx(), binding.span);
                     break;
                 }
             })
         }
     }
 
-    pub fn prohibit_projection(&self, span: Span) {
-        let mut err = struct_span_err!(self.tcx().sess, span, E0229,
+    pub fn prohibit_assoc_ty_binding(tcx: TyCtxt, span: Span) {
+        let mut err = struct_span_err!(tcx.sess, span, E0229,
                                        "associated type bindings are not allowed here");
         err.span_label(span, "associated type not allowed here").emit();
     }
@@ -1393,72 +1730,6 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
     (auto_traits, trait_bounds)
 }
 
-fn check_type_argument_count(tcx: TyCtxt,
-                             span: Span,
-                             supplied: usize,
-                             ty_params: ParamRange)
-{
-    let (required, accepted) = (ty_params.required, ty_params.accepted);
-    if supplied < required {
-        let expected = if required < accepted {
-            "expected at least"
-        } else {
-            "expected"
-        };
-        let arguments_plural = if required == 1 { "" } else { "s" };
-
-        struct_span_err!(tcx.sess, span, E0243,
-                "wrong number of type arguments: {} {}, found {}",
-                expected, required, supplied)
-            .span_label(span,
-                format!("{} {} type argument{}",
-                    expected,
-                    required,
-                    arguments_plural))
-            .emit();
-    } else if supplied > accepted {
-        let expected = if required < accepted {
-            format!("expected at most {}", accepted)
-        } else {
-            format!("expected {}", accepted)
-        };
-        let arguments_plural = if accepted == 1 { "" } else { "s" };
-
-        struct_span_err!(tcx.sess, span, E0244,
-                "wrong number of type arguments: {}, found {}",
-                expected, supplied)
-            .span_label(
-                span,
-                format!("{} type argument{}",
-                    if accepted == 0 { "expected no" } else { &expected },
-                    arguments_plural)
-            )
-            .emit();
-    }
-}
-
-fn report_lifetime_number_error(tcx: TyCtxt, span: Span, number: usize, expected: usize) {
-    let label = if number < expected {
-        if expected == 1 {
-            format!("expected {} lifetime parameter", expected)
-        } else {
-            format!("expected {} lifetime parameters", expected)
-        }
-    } else {
-        let additional = number - expected;
-        if additional == 1 {
-            "unexpected lifetime parameter".to_string()
-        } else {
-            format!("{} unexpected lifetime parameters", additional)
-        }
-    };
-    struct_span_err!(tcx.sess, span, E0107,
-                     "wrong number of lifetime parameters: expected {}, found {}",
-                     expected, number)
-        .span_label(span, label)
-        .emit();
-}
-
 // A helper struct for conveniently grouping a set of bounds which we pass to
 // and return from functions in multiple places.
 #[derive(PartialEq, Eq, Clone, Debug)]
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 6c3e265619f..fbb49c95edf 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -22,8 +22,8 @@ use rustc::ty::adjustment::{Adjustment, Adjust, OverloadedDeref};
 use rustc::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc::ty::fold::TypeFoldable;
 use rustc::infer::{self, InferOk};
-use syntax_pos::Span;
 use rustc::hir;
+use syntax_pos::Span;
 
 use std::ops::Deref;
 
@@ -308,55 +308,55 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
     fn instantiate_method_substs(
         &mut self,
         pick: &probe::Pick<'tcx>,
-        segment: &hir::PathSegment,
+        seg: &hir::PathSegment,
         parent_substs: &Substs<'tcx>,
     ) -> &'tcx Substs<'tcx> {
         // Determine the values for the generic parameters of the method.
         // If they were not explicitly supplied, just construct fresh
         // variables.
-        let method_generics = self.tcx.generics_of(pick.item.def_id);
-        let mut fn_segment = Some((segment, method_generics));
-        let supress_mismatch = self.fcx.check_impl_trait(self.span, fn_segment);
-        self.fcx.check_generic_arg_count(self.span, &mut fn_segment, true, supress_mismatch);
+        let generics = self.tcx.generics_of(pick.item.def_id);
+        AstConv::check_generic_arg_count_for_call(
+            self.tcx,
+            self.span,
+            &generics,
+            &seg,
+            true, // `is_method_call`
+        );
 
         // Create subst for early-bound lifetime parameters, combining
         // parameters from the type and those from the method.
-        assert_eq!(method_generics.parent_count, parent_substs.len());
-        let provided = &segment.args;
-        let own_counts = method_generics.own_counts();
-        Substs::for_item(self.tcx, pick.item.def_id, |param, _| {
-            let mut i = param.index as usize;
-            if i < parent_substs.len() {
-                parent_substs[i]
-            } else {
-                let (is_lt, is_ty) = match param.kind {
-                    GenericParamDefKind::Lifetime => (true, false),
-                    GenericParamDefKind::Type { .. } => (false, true),
-                };
-                provided.as_ref().and_then(|data| {
-                    for arg in &data.args {
-                        match arg {
-                            GenericArg::Lifetime(lt) if is_lt => {
-                                if i == parent_substs.len() {
-                                    return Some(AstConv::ast_region_to_region(
-                                        self.fcx, lt, Some(param)).into());
-                                }
-                                i -= 1;
-                            }
-                            GenericArg::Lifetime(_) => {}
-                            GenericArg::Type(ty) if is_ty => {
-                                if i == parent_substs.len() + own_counts.lifetimes {
-                                    return Some(self.to_ty(ty).into());
-                                }
-                                i -= 1;
-                            }
-                            GenericArg::Type(_) => {}
-                        }
+        assert_eq!(generics.parent_count, parent_substs.len());
+
+        AstConv::create_substs_for_generic_args(
+            self.tcx,
+            pick.item.def_id,
+            parent_substs,
+            false,
+            None,
+            // Provide the generic args, and whether types should be inferred.
+            |_| {
+                // The last argument of the returned tuple here is unimportant.
+                if let Some(ref data) = seg.args {
+                    (Some(data), false)
+                } else {
+                    (None, false)
+                }
+            },
+            // Provide substitutions for parameters for which (valid) arguments have been provided.
+            |param, arg| {
+                match (&param.kind, arg) {
+                    (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
+                        AstConv::ast_region_to_region(self.fcx, lt, Some(param)).into()
                     }
-                    None
-                }).unwrap_or_else(|| self.var_for_def(self.span, param))
-            }
-        })
+                    (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
+                        self.to_ty(ty).into()
+                    }
+                    _ => unreachable!(),
+                }
+            },
+            // Provide substitutions for parameters for which arguments are inferred.
+            |_, param, _| self.var_for_def(self.span, param),
+        )
     }
 
     fn unify_receivers(&mut self, self_ty: Ty<'tcx>, method_self_ty: Ty<'tcx>) {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index b57967a7aab..c89f7e0586b 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -109,7 +109,7 @@ use session::{CompileIncomplete, config, Session};
 use TypeAndSubsts;
 use lint;
 use util::common::{ErrorReported, indenter};
-use util::nodemap::{DefIdMap, DefIdSet, FxHashMap, NodeMap};
+use util::nodemap::{DefIdMap, DefIdSet, FxHashMap, FxHashSet, NodeMap};
 
 use std::cell::{Cell, RefCell, Ref, RefMut};
 use rustc_data_structures::sync::Lrc;
@@ -505,6 +505,9 @@ impl<'gcx, 'tcx> EnclosingBreakables<'gcx, 'tcx> {
     }
 }
 
+#[derive(Debug)]
+struct PathSeg(DefId, usize);
+
 pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     body_id: ast::NodeId,
 
@@ -4277,8 +4280,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     {
         match *qpath {
             hir::QPath::Resolved(ref maybe_qself, ref path) => {
-                let opt_self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself));
-                let ty = AstConv::def_to_ty(self, opt_self_ty, path, true);
+                let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself));
+                let ty = AstConv::def_to_ty(self, self_ty, path, true);
                 (path.def, ty)
             }
             hir::QPath::TypeRelative(ref qself, ref segment) => {
@@ -4770,20 +4773,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         err.span_suggestion(span_semi, "consider removing this semicolon", "".to_string());
     }
 
-    // Instantiates the given path, which must refer to an item with the given
-    // number of type parameters and type.
-    pub fn instantiate_value_path(&self,
-                                  segments: &[hir::PathSegment],
-                                  opt_self_ty: Option<Ty<'tcx>>,
-                                  def: Def,
-                                  span: Span,
-                                  node_id: ast::NodeId)
-                                  -> Ty<'tcx> {
-        debug!("instantiate_value_path(path={:?}, def={:?}, node_id={})",
-               segments,
-               def,
-               node_id);
-
+    fn def_ids_for_path_segments(&self,
+                                 segments: &[hir::PathSegment],
+                                 def: Def)
+                                 -> Vec<PathSeg> {
         // We need to extract the type parameters supplied by the user in
         // the path `path`. Due to the current setup, this is a bit of a
         // tricky-process; the problem is that resolve only tells us the
@@ -4829,35 +4822,71 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // The first step then is to categorize the segments appropriately.
 
         assert!(!segments.is_empty());
+        let last = segments.len() - 1;
+
+        let mut path_segs = vec![];
 
-        let mut ufcs_associated = None;
-        let mut type_segment = None;
-        let mut fn_segment = None;
         match def {
             // Case 1. Reference to a struct/variant constructor.
             Def::StructCtor(def_id, ..) |
             Def::VariantCtor(def_id, ..) => {
                 // Everything but the final segment should have no
                 // parameters at all.
-                let mut generics = self.tcx.generics_of(def_id);
-                if let Some(def_id) = generics.parent {
-                    // Variant and struct constructors use the
-                    // generics of their parent type definition.
-                    generics = self.tcx.generics_of(def_id);
-                }
-                type_segment = Some((segments.last().unwrap(), generics));
+                let generics = self.tcx.generics_of(def_id);
+                // Variant and struct constructors use the
+                // generics of their parent type definition.
+                let generics_def_id = generics.parent.unwrap_or(def_id);
+                path_segs.push(PathSeg(generics_def_id, last));
             }
 
             // Case 2. Reference to a top-level value.
             Def::Fn(def_id) |
             Def::Const(def_id) |
             Def::Static(def_id, _) => {
-                fn_segment = Some((segments.last().unwrap(), self.tcx.generics_of(def_id)));
+                path_segs.push(PathSeg(def_id, last));
             }
 
             // Case 3. Reference to a method or associated const.
             Def::Method(def_id) |
             Def::AssociatedConst(def_id) => {
+                if segments.len() >= 2 {
+                    let generics = self.tcx.generics_of(def_id);
+                    path_segs.push(PathSeg(generics.parent.unwrap(), last - 1));
+                }
+                path_segs.push(PathSeg(def_id, last));
+            }
+
+            // Case 4. Local variable, no generics.
+            Def::Local(..) | Def::Upvar(..) => {}
+
+            _ => bug!("unexpected definition: {:?}", def),
+        }
+
+        debug!("path_segs = {:?}", path_segs);
+
+        path_segs
+    }
+
+    // Instantiates the given path, which must refer to an item with the given
+    // number of type parameters and type.
+    pub fn instantiate_value_path(&self,
+                                  segments: &[hir::PathSegment],
+                                  self_ty: Option<Ty<'tcx>>,
+                                  def: Def,
+                                  span: Span,
+                                  node_id: ast::NodeId)
+                                  -> Ty<'tcx> {
+        debug!("instantiate_value_path(path={:?}, def={:?}, node_id={})",
+               segments,
+               def,
+               node_id);
+
+        let path_segs = self.def_ids_for_path_segments(segments, def);
+
+        let mut ufcs_associated = None;
+        match def {
+            Def::Method(def_id) |
+            Def::AssociatedConst(def_id) => {
                 let container = self.tcx.associated_item(def_id).container;
                 match container {
                     ty::TraitContainer(trait_did) => {
@@ -4865,34 +4894,31 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     }
                     ty::ImplContainer(_) => {}
                 }
-
-                let generics = self.tcx.generics_of(def_id);
-                if segments.len() >= 2 {
-                    let parent_generics = self.tcx.generics_of(generics.parent.unwrap());
-                    type_segment = Some((&segments[segments.len() - 2], parent_generics));
-                } else {
+                if segments.len() == 1 {
                     // `<T>::assoc` will end up here, and so can `T::assoc`.
-                    let self_ty = opt_self_ty.expect("UFCS sugared assoc missing Self");
+                    let self_ty = self_ty.expect("UFCS sugared assoc missing Self");
                     ufcs_associated = Some((container, self_ty));
                 }
-                fn_segment = Some((segments.last().unwrap(), generics));
             }
-
-            // Case 4. Local variable, no generics.
-            Def::Local(..) | Def::Upvar(..) => {}
-
-            _ => bug!("unexpected definition: {:?}", def),
+            _ => {}
         }
 
-        debug!("type_segment={:?} fn_segment={:?}", type_segment, fn_segment);
-
         // Now that we have categorized what space the parameters for each
         // segment belong to, let's sort out the parameters that the user
         // provided (if any) into their appropriate spaces. We'll also report
         // errors if type parameters are provided in an inappropriate place.
-        let poly_segments = type_segment.is_some() as usize +
-                            fn_segment.is_some() as usize;
-        AstConv::prohibit_generics(self, &segments[..segments.len() - poly_segments]);
+
+        let mut generic_segs = FxHashSet::default();
+        for PathSeg(_, index) in &path_segs {
+            generic_segs.insert(index);
+        }
+        AstConv::prohibit_generics(self, segments.iter().enumerate().filter_map(|(index, seg)| {
+            if !generic_segs.contains(&index) {
+                Some(seg)
+            } else {
+                None
+            }
+        }));
 
         match def {
             Def::Local(nid) | Def::Upvar(nid, ..) => {
@@ -4910,120 +4936,109 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // variables. If the user provided some types, we may still need
         // to add defaults. If the user provided *too many* types, that's
         // a problem.
-        let supress_mismatch = self.check_impl_trait(span, fn_segment);
-        self.check_generic_arg_count(span, &mut type_segment, false, supress_mismatch);
-        self.check_generic_arg_count(span, &mut fn_segment, false, supress_mismatch);
 
-        let (fn_start, has_self) = match (type_segment, fn_segment) {
-            (_, Some((_, generics))) => {
-                (generics.parent_count, generics.has_self)
-            }
-            (Some((_, generics)), None) => {
-                (generics.params.len(), generics.has_self)
-            }
-            (None, None) => (0, false)
-        };
-        // FIXME(varkor): Separating out the parameters is messy.
-        let mut lifetimes_type_seg = vec![];
-        let mut types_type_seg = vec![];
-        let mut infer_types_type_seg = true;
-        if let Some((seg, _)) = type_segment {
-            if let Some(ref data) = seg.args {
-                for arg in &data.args {
-                    match arg {
-                        GenericArg::Lifetime(lt) => lifetimes_type_seg.push(lt),
-                        GenericArg::Type(ty) => types_type_seg.push(ty),
-                    }
-                }
+        let mut infer_args_for_err = FxHashSet::default();
+        for &PathSeg(def_id, index) in &path_segs {
+            let seg = &segments[index];
+            let generics = self.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.
+            let suppress_errors = AstConv::check_generic_arg_count_for_call(
+                self.tcx,
+                span,
+                &generics,
+                &seg,
+                false, // `is_method_call`
+            );
+            if suppress_errors {
+                infer_args_for_err.insert(index);
+                self.set_tainted_by_errors(); // See issue #53251.
             }
-            infer_types_type_seg = seg.infer_types;
         }
 
-        let mut lifetimes_fn_seg = vec![];
-        let mut types_fn_seg = vec![];
-        let mut infer_types_fn_seg = true;
-        if let Some((seg, _)) = fn_segment {
-            if let Some(ref data) = seg.args {
-                for arg in &data.args {
-                    match arg {
-                        GenericArg::Lifetime(lt) => lifetimes_fn_seg.push(lt),
-                        GenericArg::Type(ty) => types_fn_seg.push(ty),
-                    }
-                }
-            }
-            infer_types_fn_seg = seg.infer_types;
-        }
+        let has_self = path_segs.last().map(|PathSeg(def_id, _)| {
+            self.tcx.generics_of(*def_id).has_self
+        }).unwrap_or(false);
 
-        let substs = Substs::for_item(self.tcx, def.def_id(), |param, substs| {
-            let mut i = param.index as usize;
+        let def_id = def.def_id();
 
-            let (segment, lifetimes, types, infer_types) = if i < fn_start {
-                if let GenericParamDefKind::Type { .. } = param.kind {
-                    // Handle Self first, so we can adjust the index to match the AST.
-                    if has_self && i == 0 {
-                        return opt_self_ty.map(|ty| ty.into()).unwrap_or_else(|| {
-                            self.var_for_def(span, param)
-                        });
+        let substs = AstConv::create_substs_for_generic_args(
+            self.tcx,
+            def_id,
+            &[][..],
+            has_self,
+            self_ty,
+            // Provide the generic args, and whether types should be inferred.
+            |def_id| {
+                if let Some(&PathSeg(_, index)) = path_segs.iter().find(|&PathSeg(did, _)| {
+                    *did == def_id
+                }) {
+                    // If we've encountered an `impl Trait`-related error, we're just
+                    // going to infer the arguments for better error messages.
+                    if !infer_args_for_err.contains(&index) {
+                        // Check whether the user has provided generic arguments.
+                        if let Some(ref data) = segments[index].args {
+                            return (Some(data), segments[index].infer_types);
+                        }
                     }
+                    return (None, segments[index].infer_types);
                 }
-                i -= has_self as usize;
-                (type_segment, &lifetimes_type_seg, &types_type_seg, infer_types_type_seg)
-            } else {
-                i -= fn_start;
-                (fn_segment, &lifetimes_fn_seg, &types_fn_seg, infer_types_fn_seg)
-            };
 
-            match param.kind {
-                GenericParamDefKind::Lifetime => {
-                    if let Some(lifetime) = lifetimes.get(i) {
-                        AstConv::ast_region_to_region(self, lifetime, Some(param)).into()
-                    } else {
-                        self.re_infer(span, Some(param)).unwrap().into()
+                (None, true)
+            },
+            // Provide substitutions for parameters for which (valid) arguments have been provided.
+            |param, arg| {
+                match (&param.kind, arg) {
+                    (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
+                        AstConv::ast_region_to_region(self, lt, Some(param)).into()
                     }
+                    (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
+                        self.to_ty(ty).into()
+                    }
+                    _ => unreachable!(),
                 }
-                GenericParamDefKind::Type { .. } => {
-                    // Skip over the lifetimes in the same segment.
-                    if let Some((_, generics)) = segment {
-                        i -= generics.own_counts().lifetimes;
+            },
+            // Provide substitutions for parameters for which arguments are inferred.
+            |substs, param, infer_types| {
+                match param.kind {
+                    GenericParamDefKind::Lifetime => {
+                        self.re_infer(span, Some(param)).unwrap().into()
                     }
-
-                    let has_default = match param.kind {
-                        GenericParamDefKind::Type { has_default, .. } => has_default,
-                        _ => unreachable!()
-                    };
-
-                    if let Some(ast_ty) = types.get(i) {
-                        // A provided type parameter.
-                        self.to_ty(ast_ty).into()
-                    } else if !infer_types && has_default {
-                        // No type parameter provided, but a default exists.
-                        let default = self.tcx.type_of(param.def_id);
-                        self.normalize_ty(
-                            span,
-                            default.subst_spanned(self.tcx, substs, Some(span))
-                        ).into()
-                    } else {
-                        // No type parameters were provided, we can infer all.
-                        // This can also be reached in some error cases:
-                        // We prefer to use inference variables instead of
-                        // TyError to let type inference recover somewhat.
-                        self.var_for_def(span, param)
+                    GenericParamDefKind::Type { has_default, .. } => {
+                        if !infer_types && has_default {
+                            // If we have a default, then we it doesn't matter that we're not
+                            // inferring the type arguments: we provide the default where any
+                            // is missing.
+                            let default = self.tcx.type_of(param.def_id);
+                            self.normalize_ty(
+                                span,
+                                default.subst_spanned(self.tcx, substs.unwrap(), Some(span))
+                            ).into()
+                        } else {
+                            // If no type arguments were provided, we have to infer them.
+                            // This case also occurs as a result of some malformed input, e.g.
+                            // a lifetime argument being given instead of a type paramter.
+                            // Using inference instead of `TyError` gives better error messages.
+                            self.var_for_def(span, param)
+                        }
                     }
                 }
-            }
-        });
+            },
+        );
 
         // The things we are substituting into the type should not contain
         // escaping late-bound regions, and nor should the base type scheme.
-        let ty = self.tcx.type_of(def.def_id());
+        let ty = self.tcx.type_of(def_id);
         assert!(!substs.has_escaping_regions());
         assert!(!ty.has_escaping_regions());
 
         // Add all the obligations that are required, substituting and
         // normalized appropriately.
-        let bounds = self.instantiate_bounds(span, def.def_id(), &substs);
+        let bounds = self.instantiate_bounds(span, def_id, &substs);
         self.add_obligations_for_parameters(
-            traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def.def_id())),
+            traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def_id)),
             &bounds);
 
         // Substitute the values for the type parameters into the type of
@@ -5049,7 +5064,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             }
         }
 
-        self.check_rustc_args_require_const(def.def_id(), node_id, span);
+        self.check_rustc_args_require_const(def_id, node_id, span);
 
         debug!("instantiate_value_path: type of {:?} is {:?}",
                node_id,
@@ -5088,167 +5103,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                       directly, not through a function pointer");
     }
 
-    /// Report errors if the provided parameters are too few or too many.
-    fn check_generic_arg_count(&self,
-                               span: Span,
-                               segment: &mut Option<(&hir::PathSegment, &ty::Generics)>,
-                               is_method_call: bool,
-                               supress_mismatch_error: bool) {
-        let (lifetimes, types, infer_types, bindings) = segment.map_or(
-            (vec![], vec![], true, &[][..]),
-            |(s, _)| {
-                s.args.as_ref().map_or(
-                    (vec![], vec![], s.infer_types, &[][..]),
-                    |data| {
-                        let (mut lifetimes, mut types) = (vec![], vec![]);
-                        data.args.iter().for_each(|arg| match arg {
-                            GenericArg::Lifetime(lt) => lifetimes.push(lt),
-                            GenericArg::Type(ty) => types.push(ty),
-                        });
-                        (lifetimes, types, s.infer_types, &data.bindings[..])
-                    }
-                )
-            });
-
-        // Check provided parameters.
-        let ((ty_required, ty_accepted), lt_accepted) =
-            segment.map_or(((0, 0), 0), |(_, generics)| {
-                struct ParamRange {
-                    required: usize,
-                    accepted: usize
-                };
-
-                let mut lt_accepted = 0;
-                let mut ty_params = ParamRange { required: 0, accepted: 0 };
-                for param in &generics.params {
-                    match param.kind {
-                        GenericParamDefKind::Lifetime => lt_accepted += 1,
-                        GenericParamDefKind::Type { has_default, .. } => {
-                            ty_params.accepted += 1;
-                            if !has_default {
-                                ty_params.required += 1;
-                            }
-                        }
-                    };
-                }
-                if generics.parent.is_none() && generics.has_self {
-                    ty_params.required -= 1;
-                    ty_params.accepted -= 1;
-                }
-
-                ((ty_params.required, ty_params.accepted), lt_accepted)
-            });
-
-        let count_type_params = |n| {
-            format!("{} type parameter{}", n, if n == 1 { "" } else { "s" })
-        };
-        let expected_text = count_type_params(ty_accepted);
-        let actual_text = count_type_params(types.len());
-        if let Some((mut err, span)) = if types.len() > ty_accepted {
-            // To prevent derived errors to accumulate due to extra
-            // type parameters, we force instantiate_value_path to
-            // use inference variables instead of the provided types.
-            *segment = None;
-            let span = types[ty_accepted].span;
-            Some((struct_span_err!(self.tcx.sess, span, E0087,
-                                  "too many type parameters provided: \
-                                  expected at most {}, found {}",
-                                  expected_text, actual_text), span))
-        } else if types.len() < ty_required && !infer_types && !supress_mismatch_error {
-            Some((struct_span_err!(self.tcx.sess, span, E0089,
-                                  "too few type parameters provided: \
-                                  expected {}, found {}",
-                                  expected_text, actual_text), span))
-        } else {
-            None
-        } {
-            self.set_tainted_by_errors(); // #53251
-            err.span_label(span, format!("expected {}", expected_text)).emit();
-        }
-
-        if !bindings.is_empty() {
-            AstConv::prohibit_projection(self, bindings[0].span);
-        }
-
-        let infer_lifetimes = lifetimes.len() == 0;
-        // Prohibit explicit lifetime arguments if late bound lifetime parameters are present.
-        let has_late_bound_lifetime_defs =
-            segment.map_or(None, |(_, generics)| generics.has_late_bound_regions);
-        if let (Some(span_late), false) = (has_late_bound_lifetime_defs, lifetimes.is_empty()) {
-            // Report this as a lint only if no error was reported previously.
-            let primary_msg = "cannot specify lifetime arguments explicitly \
-                               if late bound lifetime parameters are present";
-            let note_msg = "the late bound lifetime parameter is introduced here";
-            if !is_method_call && (lifetimes.len() > lt_accepted ||
-                                   lifetimes.len() < lt_accepted && !infer_lifetimes) {
-                let mut err = self.tcx.sess.struct_span_err(lifetimes[0].span, primary_msg);
-                err.span_note(span_late, note_msg);
-                err.emit();
-                *segment = None;
-            } else {
-                let mut multispan = MultiSpan::from_span(lifetimes[0].span);
-                multispan.push_span_label(span_late, note_msg.to_string());
-                self.tcx.lint_node(lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS,
-                                   lifetimes[0].id, multispan, primary_msg);
-            }
-            return;
-        }
-
-        let count_lifetime_params = |n| {
-            format!("{} lifetime parameter{}", n, if n == 1 { "" } else { "s" })
-        };
-        let expected_text = count_lifetime_params(lt_accepted);
-        let actual_text = count_lifetime_params(lifetimes.len());
-        if let Some((mut err, span)) = if lifetimes.len() > lt_accepted {
-            let span = lifetimes[lt_accepted].span;
-            Some((struct_span_err!(self.tcx.sess, span, E0088,
-                                  "too many lifetime parameters provided: \
-                                  expected at most {}, found {}",
-                                  expected_text, actual_text), span))
-        } else if lifetimes.len() < lt_accepted && !infer_lifetimes {
-            Some((struct_span_err!(self.tcx.sess, span, E0090,
-                                  "too few lifetime parameters provided: \
-                                  expected {}, found {}",
-                                  expected_text, actual_text), span))
-        } else {
-            None
-        } {
-            err.span_label(span, format!("expected {}", expected_text)).emit();
-        }
-    }
-
-    /// Report error if there is an explicit type parameter when using `impl Trait`.
-    fn check_impl_trait(&self,
-                        span: Span,
-                        segment: Option<(&hir::PathSegment, &ty::Generics)>)
-                        -> bool {
-        let segment = segment.map(|(path_segment, generics)| {
-            let explicit = !path_segment.infer_types;
-            let impl_trait = generics.params.iter().any(|param| match param.kind {
-                ty::GenericParamDefKind::Type {
-                    synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), ..
-                } => true,
-                _ => false,
-            });
-
-            if explicit && impl_trait {
-                let mut err = struct_span_err! {
-                    self.tcx.sess,
-                    span,
-                    E0632,
-                    "cannot provide explicit type parameters when `impl Trait` is \
-                    used in argument position."
-                };
-
-                err.emit();
-            }
-
-            impl_trait
-        });
-
-        segment.unwrap_or(false)
-    }
-
     // Resolves `typ` by a single level if `typ` is a type variable.
     // If no resolution is possible, then an error is reported.
     // Numeric inference variables may be left unresolved.
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index 4d957c9aa45..c01102272ae 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -1041,32 +1041,34 @@ enum NightsWatch {}
 "##,
 
 E0087: r##"
-Too many type parameters were supplied for a function. For example:
+Too many type arguments were supplied for a function. For example:
 
 ```compile_fail,E0087
 fn foo<T>() {}
 
 fn main() {
-    foo::<f64, bool>(); // error, expected 1 parameter, found 2 parameters
+    foo::<f64, bool>(); // error: wrong number of type arguments:
+                        //        expected 1, found 2
 }
 ```
 
-The number of supplied parameters must exactly match the number of defined type
+The number of supplied arguments must exactly match the number of defined type
 parameters.
 "##,
 
 E0088: r##"
-You gave too many lifetime parameters. Erroneous code example:
+You gave too many lifetime arguments. Erroneous code example:
 
 ```compile_fail,E0088
 fn f() {}
 
 fn main() {
-    f::<'static>() // error: too many lifetime parameters provided
+    f::<'static>() // error: wrong number of lifetime arguments:
+                   //        expected 0, found 1
 }
 ```
 
-Please check you give the right number of lifetime parameters. Example:
+Please check you give the right number of lifetime arguments. Example:
 
 ```
 fn f() {}
@@ -1101,17 +1103,17 @@ fn main() {
 "##,
 
 E0089: r##"
-Not enough type parameters were supplied for a function. For example:
+Too few type arguments were supplied for a function. For example:
 
 ```compile_fail,E0089
 fn foo<T, U>() {}
 
 fn main() {
-    foo::<f64>(); // error, expected 2 parameters, found 1 parameter
+    foo::<f64>(); // error: wrong number of type arguments: expected 2, found 1
 }
 ```
 
-Note that if a function takes multiple type parameters but you want the compiler
+Note that if a function takes multiple type arguments but you want the compiler
 to infer some of them, you can use type placeholders:
 
 ```compile_fail,E0089
@@ -1119,24 +1121,26 @@ fn foo<T, U>(x: T) {}
 
 fn main() {
     let x: bool = true;
-    foo::<f64>(x);    // error, expected 2 parameters, found 1 parameter
+    foo::<f64>(x);    // error: wrong number of type arguments:
+                      //        expected 2, found 1
     foo::<_, f64>(x); // same as `foo::<bool, f64>(x)`
 }
 ```
 "##,
 
 E0090: r##"
-You gave too few lifetime parameters. Example:
+You gave too few lifetime arguments. Example:
 
 ```compile_fail,E0090
 fn foo<'a: 'b, 'b: 'a>() {}
 
 fn main() {
-    foo::<'static>(); // error, expected 2 lifetime parameters
+    foo::<'static>(); // error: wrong number of lifetime arguments:
+                      //        expected 2, found 1
 }
 ```
 
-Please check you give the right number of lifetime parameters. Example:
+Please check you give the right number of lifetime arguments. Example:
 
 ```
 fn foo<'a: 'b, 'b: 'a>() {}
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 9b77ff82f90..6cb37c0e6de 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2432,10 +2432,7 @@ impl Clean<Type> for hir::Ty {
                     let mut ty_substs = FxHashMap();
                     let mut lt_substs = FxHashMap();
                     provided_params.with_generic_args(|generic_args| {
-                        let mut indices = ty::GenericParamCount {
-                            lifetimes: 0,
-                            types: 0
-                        };
+                        let mut indices: GenericParamCount = Default::default();
                         for param in generics.params.iter() {
                             match param.kind {
                                 hir::GenericParamKind::Lifetime { .. } => {
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 20ac757354f..1ee70d9bdde 100644
--- a/src/test/ui/bad/bad-mid-path-type-params.rs
+++ b/src/test/ui/bad/bad-mid-path-type-params.rs
@@ -38,16 +38,16 @@ impl Trait<isize> for S2 {
 
 fn foo<'a>() {
     let _ = S::new::<isize,f64>(1, 1.0);
-    //~^ ERROR too many type parameters provided
+    //~^ ERROR wrong number of type arguments
 
     let _ = S::<'a,isize>::new::<f64>(1, 1.0);
-    //~^ ERROR wrong number of lifetime parameters
+    //~^ ERROR wrong number of lifetime arguments
 
     let _: S2 = Trait::new::<isize,f64>(1, 1.0);
-    //~^ ERROR too many type parameters provided
+    //~^ ERROR wrong number of type arguments
 
     let _: S2 = Trait::<'a,isize>::new::<f64>(1, 1.0);
-    //~^ ERROR too many lifetime parameters provided
+    //~^ ERROR wrong number of lifetime arguments
 }
 
 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 d2b002ebee9..7901f1f0fba 100644
--- a/src/test/ui/bad/bad-mid-path-type-params.stderr
+++ b/src/test/ui/bad/bad-mid-path-type-params.stderr
@@ -1,26 +1,26 @@
-error[E0087]: too many type parameters provided: expected at most 1 type parameter, found 2 type parameters
+error[E0087]: wrong number of type arguments: expected 1, found 2
   --> $DIR/bad-mid-path-type-params.rs:40:28
    |
 LL |     let _ = S::new::<isize,f64>(1, 1.0);
-   |                            ^^^ expected 1 type parameter
+   |                            ^^^ unexpected type argument
 
-error[E0107]: wrong number of lifetime parameters: expected 0, found 1
-  --> $DIR/bad-mid-path-type-params.rs:43:13
+error[E0107]: wrong number of lifetime arguments: expected 0, found 1
+  --> $DIR/bad-mid-path-type-params.rs:43:17
    |
 LL |     let _ = S::<'a,isize>::new::<f64>(1, 1.0);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^ unexpected lifetime parameter
+   |                 ^^ unexpected lifetime argument
 
-error[E0087]: too many type parameters provided: expected at most 1 type parameter, found 2 type parameters
+error[E0087]: wrong number of type arguments: expected 1, found 2
   --> $DIR/bad-mid-path-type-params.rs:46:36
    |
 LL |     let _: S2 = Trait::new::<isize,f64>(1, 1.0);
-   |                                    ^^^ expected 1 type parameter
+   |                                    ^^^ unexpected type argument
 
-error[E0088]: too many lifetime parameters provided: expected at most 0 lifetime parameters, found 1 lifetime parameter
+error[E0088]: wrong number of lifetime arguments: expected 0, found 1
   --> $DIR/bad-mid-path-type-params.rs:49:25
    |
 LL |     let _: S2 = Trait::<'a,isize>::new::<f64>(1, 1.0);
-   |                         ^^ expected 0 lifetime parameters
+   |                         ^^ unexpected lifetime argument
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/constructor-lifetime-args.rs b/src/test/ui/constructor-lifetime-args.rs
index 50db9707355..1fe50cfebba 100644
--- a/src/test/ui/constructor-lifetime-args.rs
+++ b/src/test/ui/constructor-lifetime-args.rs
@@ -25,12 +25,12 @@ enum E<'a, 'b> {
 fn main() {
     S(&0, &0); // OK
     S::<'static>(&0, &0);
-    //~^ ERROR expected 2 lifetime parameters, found 1 lifetime parameter
+    //~^ ERROR wrong number of lifetime arguments: expected 2, found 1
     S::<'static, 'static, 'static>(&0, &0);
-    //~^ ERROR expected at most 2 lifetime parameters, found 3 lifetime parameters
+    //~^ ERROR wrong number of lifetime arguments: expected 2, found 3
     E::V(&0); // OK
     E::V::<'static>(&0);
-    //~^ ERROR expected 2 lifetime parameters, found 1 lifetime parameter
+    //~^ ERROR wrong number of lifetime arguments: expected 2, found 1
     E::V::<'static, 'static, 'static>(&0);
-    //~^ ERROR expected at most 2 lifetime parameters, found 3 lifetime parameters
+    //~^ ERROR wrong number of lifetime arguments: expected 2, found 3
 }
diff --git a/src/test/ui/constructor-lifetime-args.stderr b/src/test/ui/constructor-lifetime-args.stderr
index 1710594d255..cf3ad9ae8ec 100644
--- a/src/test/ui/constructor-lifetime-args.stderr
+++ b/src/test/ui/constructor-lifetime-args.stderr
@@ -1,26 +1,26 @@
-error[E0090]: too few lifetime parameters provided: expected 2 lifetime parameters, found 1 lifetime parameter
+error[E0090]: wrong number of lifetime arguments: expected 2, found 1
   --> $DIR/constructor-lifetime-args.rs:27:5
    |
 LL |     S::<'static>(&0, &0);
-   |     ^^^^^^^^^^^^ expected 2 lifetime parameters
+   |     ^^^^^^^^^^^^ expected 2 lifetime arguments
 
-error[E0088]: too many lifetime parameters provided: expected at most 2 lifetime parameters, found 3 lifetime parameters
+error[E0088]: wrong number of lifetime arguments: expected 2, found 3
   --> $DIR/constructor-lifetime-args.rs:29:27
    |
 LL |     S::<'static, 'static, 'static>(&0, &0);
-   |                           ^^^^^^^ expected 2 lifetime parameters
+   |                           ^^^^^^^ unexpected lifetime argument
 
-error[E0090]: too few lifetime parameters provided: expected 2 lifetime parameters, found 1 lifetime parameter
+error[E0090]: wrong number of lifetime arguments: expected 2, found 1
   --> $DIR/constructor-lifetime-args.rs:32:5
    |
 LL |     E::V::<'static>(&0);
-   |     ^^^^^^^^^^^^^^^ expected 2 lifetime parameters
+   |     ^^^^^^^^^^^^^^^ expected 2 lifetime arguments
 
-error[E0088]: too many lifetime parameters provided: expected at most 2 lifetime parameters, found 3 lifetime parameters
+error[E0088]: wrong number of lifetime arguments: expected 2, found 3
   --> $DIR/constructor-lifetime-args.rs:34:30
    |
 LL |     E::V::<'static, 'static, 'static>(&0);
-   |                              ^^^^^^^ expected 2 lifetime parameters
+   |                              ^^^^^^^ unexpected lifetime argument
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/error-codes/E0087.rs b/src/test/ui/error-codes/E0087.rs
index 6dc08860614..bea76f34220 100644
--- a/src/test/ui/error-codes/E0087.rs
+++ b/src/test/ui/error-codes/E0087.rs
@@ -12,7 +12,7 @@ fn foo() {}
 fn bar<T>() {}
 
 fn main() {
-    foo::<f64>(); //~ ERROR expected at most 0 type parameters, found 1 type parameter [E0087]
+    foo::<f64>(); //~ ERROR wrong number of type arguments: expected 0, found 1 [E0087]
 
-    bar::<f64, u64>(); //~ ERROR expected at most 1 type parameter, found 2 type parameters [E0087]
+    bar::<f64, u64>(); //~ ERROR wrong number of type arguments: expected 1, found 2 [E0087]
 }
diff --git a/src/test/ui/error-codes/E0087.stderr b/src/test/ui/error-codes/E0087.stderr
index cd1e99e7b41..a07f1bbf39a 100644
--- a/src/test/ui/error-codes/E0087.stderr
+++ b/src/test/ui/error-codes/E0087.stderr
@@ -1,14 +1,14 @@
-error[E0087]: too many type parameters provided: expected at most 0 type parameters, found 1 type parameter
+error[E0087]: wrong number of type arguments: expected 0, found 1
   --> $DIR/E0087.rs:15:11
    |
-LL |     foo::<f64>(); //~ ERROR expected at most 0 type parameters, found 1 type parameter [E0087]
-   |           ^^^ expected 0 type parameters
+LL |     foo::<f64>(); //~ ERROR wrong number of type arguments: expected 0, found 1 [E0087]
+   |           ^^^ unexpected type argument
 
-error[E0087]: too many type parameters provided: expected at most 1 type parameter, found 2 type parameters
+error[E0087]: wrong number of type arguments: expected 1, found 2
   --> $DIR/E0087.rs:17:16
    |
-LL |     bar::<f64, u64>(); //~ ERROR expected at most 1 type parameter, found 2 type parameters [E0087]
-   |                ^^^ expected 1 type parameter
+LL |     bar::<f64, u64>(); //~ ERROR wrong number of type arguments: expected 1, found 2 [E0087]
+   |                ^^^ unexpected type argument
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/error-codes/E0088.stderr b/src/test/ui/error-codes/E0088.stderr
index 4bf2760994e..6b956023e05 100644
--- a/src/test/ui/error-codes/E0088.stderr
+++ b/src/test/ui/error-codes/E0088.stderr
@@ -1,14 +1,14 @@
-error[E0088]: too many lifetime parameters provided: expected at most 0 lifetime parameters, found 1 lifetime parameter
+error[E0088]: wrong number of lifetime arguments: expected 0, found 1
   --> $DIR/E0088.rs:15:9
    |
 LL |     f::<'static>(); //~ ERROR E0088
-   |         ^^^^^^^ expected 0 lifetime parameters
+   |         ^^^^^^^ unexpected lifetime argument
 
-error[E0088]: too many lifetime parameters provided: expected at most 1 lifetime parameter, found 2 lifetime parameters
+error[E0088]: wrong number of lifetime arguments: expected 1, found 2
   --> $DIR/E0088.rs:16:18
    |
 LL |     g::<'static, 'static>(); //~ ERROR E0088
-   |                  ^^^^^^^ expected 1 lifetime parameter
+   |                  ^^^^^^^ unexpected lifetime argument
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/error-codes/E0089.rs b/src/test/ui/error-codes/E0089.rs
index 21df9abd093..4e6196a7b89 100644
--- a/src/test/ui/error-codes/E0089.rs
+++ b/src/test/ui/error-codes/E0089.rs
@@ -11,5 +11,5 @@
 fn foo<T, U>() {}
 
 fn main() {
-    foo::<f64>(); //~ ERROR expected 2 type parameters, found 1 type parameter [E0089]
+    foo::<f64>(); //~ ERROR wrong number of type arguments: expected 2, found 1 [E0089]
 }
diff --git a/src/test/ui/error-codes/E0089.stderr b/src/test/ui/error-codes/E0089.stderr
index 0b95033fb36..f79c478b733 100644
--- a/src/test/ui/error-codes/E0089.stderr
+++ b/src/test/ui/error-codes/E0089.stderr
@@ -1,8 +1,8 @@
-error[E0089]: too few type parameters provided: expected 2 type parameters, found 1 type parameter
+error[E0089]: wrong number of type arguments: expected 2, found 1
   --> $DIR/E0089.rs:14:5
    |
-LL |     foo::<f64>(); //~ ERROR expected 2 type parameters, found 1 type parameter [E0089]
-   |     ^^^^^^^^^^ expected 2 type parameters
+LL |     foo::<f64>(); //~ ERROR wrong number of type arguments: expected 2, found 1 [E0089]
+   |     ^^^^^^^^^^ expected 2 type arguments
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0090.rs b/src/test/ui/error-codes/E0090.rs
index 13b2131cc8b..26be4c12f07 100644
--- a/src/test/ui/error-codes/E0090.rs
+++ b/src/test/ui/error-codes/E0090.rs
@@ -11,5 +11,5 @@
 fn foo<'a: 'b, 'b: 'a>() {}
 
 fn main() {
-    foo::<'static>(); //~ ERROR expected 2 lifetime parameters, found 1 lifetime parameter [E0090]
+    foo::<'static>(); //~ ERROR wrong number of lifetime arguments: expected 2, found 1 [E0090]
 }
diff --git a/src/test/ui/error-codes/E0090.stderr b/src/test/ui/error-codes/E0090.stderr
index f119d5fa467..9029b6c2708 100644
--- a/src/test/ui/error-codes/E0090.stderr
+++ b/src/test/ui/error-codes/E0090.stderr
@@ -1,8 +1,8 @@
-error[E0090]: too few lifetime parameters provided: expected 2 lifetime parameters, found 1 lifetime parameter
+error[E0090]: wrong number of lifetime arguments: expected 2, found 1
   --> $DIR/E0090.rs:14:5
    |
-LL |     foo::<'static>(); //~ ERROR expected 2 lifetime parameters, found 1 lifetime parameter [E0090]
-   |     ^^^^^^^^^^^^^^ expected 2 lifetime parameters
+LL |     foo::<'static>(); //~ ERROR wrong number of lifetime arguments: expected 2, found 1 [E0090]
+   |     ^^^^^^^^^^^^^^ expected 2 lifetime arguments
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0107.rs b/src/test/ui/error-codes/E0107.rs
index 16ebd3e9ca5..815c7fefd2a 100644
--- a/src/test/ui/error-codes/E0107.rs
+++ b/src/test/ui/error-codes/E0107.rs
@@ -20,14 +20,13 @@ enum Bar {
 struct Baz<'a, 'b, 'c> {
     buzz: Buzz<'a>,
     //~^ ERROR E0107
-    //~| expected 2 lifetime parameters
+    //~| expected 2 lifetime arguments
     bar: Bar<'a>,
     //~^ ERROR E0107
-    //~| unexpected lifetime parameter
+    //~| unexpected lifetime argument
     foo2: Foo<'a, 'b, 'c>,
     //~^ ERROR E0107
-    //~| 2 unexpected lifetime parameters
+    //~| 2 unexpected lifetime arguments
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/src/test/ui/error-codes/E0107.stderr b/src/test/ui/error-codes/E0107.stderr
index 76bb2667643..497fa91bd4f 100644
--- a/src/test/ui/error-codes/E0107.stderr
+++ b/src/test/ui/error-codes/E0107.stderr
@@ -1,20 +1,20 @@
-error[E0107]: wrong number of lifetime parameters: expected 2, found 1
+error[E0107]: wrong number of lifetime arguments: expected 2, found 1
   --> $DIR/E0107.rs:21:11
    |
 LL |     buzz: Buzz<'a>,
-   |           ^^^^^^^^ expected 2 lifetime parameters
+   |           ^^^^^^^^ expected 2 lifetime arguments
 
-error[E0107]: wrong number of lifetime parameters: expected 0, found 1
-  --> $DIR/E0107.rs:24:10
+error[E0107]: wrong number of lifetime arguments: expected 0, found 1
+  --> $DIR/E0107.rs:24:14
    |
 LL |     bar: Bar<'a>,
-   |          ^^^^^^^ unexpected lifetime parameter
+   |              ^^ unexpected lifetime argument
 
-error[E0107]: wrong number of lifetime parameters: expected 1, found 3
+error[E0107]: wrong number of lifetime arguments: expected 1, found 3
   --> $DIR/E0107.rs:27:11
    |
 LL |     foo2: Foo<'a, 'b, 'c>,
-   |           ^^^^^^^^^^^^^^^ 2 unexpected lifetime parameters
+   |           ^^^^^^^^^^^^^^^ 2 unexpected lifetime arguments
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/error-codes/E0244.stderr b/src/test/ui/error-codes/E0244.stderr
index e3239703962..87f063c604f 100644
--- a/src/test/ui/error-codes/E0244.stderr
+++ b/src/test/ui/error-codes/E0244.stderr
@@ -2,7 +2,7 @@ error[E0244]: wrong number of type arguments: expected 0, found 2
   --> $DIR/E0244.rs:12:23
    |
 LL | struct Bar<S, T> { x: Foo<S, T> }
-   |                       ^^^^^^^^^ expected no type arguments
+   |                       ^^^^^^^^^ 2 unexpected type arguments
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generic/generic-arg-mismatch-recover.rs b/src/test/ui/generic/generic-arg-mismatch-recover.rs
new file mode 100644
index 00000000000..b8883ff9c83
--- /dev/null
+++ b/src/test/ui/generic/generic-arg-mismatch-recover.rs
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo<'a, T: 'a>(&'a T);
+
+struct Bar<'a>(&'a ());
+
+fn main() {
+    Foo::<'static, 'static, ()>(&0); //~ ERROR wrong number of lifetime arguments
+    //~^ ERROR mismatched types
+
+    Bar::<'static, 'static, ()>(&()); //~ ERROR wrong number of lifetime arguments
+    //~^ ERROR wrong number of type arguments
+}
diff --git a/src/test/ui/generic/generic-arg-mismatch-recover.stderr b/src/test/ui/generic/generic-arg-mismatch-recover.stderr
new file mode 100644
index 00000000000..81869ad0d08
--- /dev/null
+++ b/src/test/ui/generic/generic-arg-mismatch-recover.stderr
@@ -0,0 +1,31 @@
+error[E0088]: wrong number of lifetime arguments: expected 1, found 2
+  --> $DIR/generic-arg-mismatch-recover.rs:16:20
+   |
+LL |     Foo::<'static, 'static, ()>(&0); //~ ERROR wrong number of lifetime arguments
+   |                    ^^^^^^^ unexpected lifetime argument
+
+error[E0308]: mismatched types
+  --> $DIR/generic-arg-mismatch-recover.rs:16:33
+   |
+LL |     Foo::<'static, 'static, ()>(&0); //~ ERROR wrong number of lifetime arguments
+   |                                 ^^ expected (), found integral variable
+   |
+   = note: expected type `&'static ()`
+              found type `&{integer}`
+
+error[E0088]: wrong number of lifetime arguments: expected 1, found 2
+  --> $DIR/generic-arg-mismatch-recover.rs:19:20
+   |
+LL |     Bar::<'static, 'static, ()>(&()); //~ ERROR wrong number of lifetime arguments
+   |                    ^^^^^^^ unexpected lifetime argument
+
+error[E0087]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/generic-arg-mismatch-recover.rs:19:29
+   |
+LL |     Bar::<'static, 'static, ()>(&()); //~ ERROR wrong number of lifetime arguments
+   |                             ^^ unexpected type argument
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0087, E0088, E0308.
+For more information about an error, try `rustc --explain E0087`.
diff --git a/src/test/ui/generic/generic-impl-more-params-with-defaults.stderr b/src/test/ui/generic/generic-impl-more-params-with-defaults.stderr
index 6b54baefb1d..b614da88ba1 100644
--- a/src/test/ui/generic/generic-impl-more-params-with-defaults.stderr
+++ b/src/test/ui/generic/generic-impl-more-params-with-defaults.stderr
@@ -2,7 +2,7 @@ error[E0244]: wrong number of type arguments: expected at most 2, found 3
   --> $DIR/generic-impl-more-params-with-defaults.rs:23:5
    |
 LL |     Vec::<isize, Heap, bool>::new();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected at most 2 type arguments
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected at most 2 type argument
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generic/generic-type-more-params-with-defaults.stderr b/src/test/ui/generic/generic-type-more-params-with-defaults.stderr
index 684a22ce45c..f226921816d 100644
--- a/src/test/ui/generic/generic-type-more-params-with-defaults.stderr
+++ b/src/test/ui/generic/generic-type-more-params-with-defaults.stderr
@@ -2,7 +2,7 @@ error[E0244]: wrong number of type arguments: expected at most 2, found 3
   --> $DIR/generic-type-more-params-with-defaults.rs:19:12
    |
 LL |     let _: Vec<isize, Heap, bool>;
-   |            ^^^^^^^^^^^^^^^^^^^^^^ expected at most 2 type arguments
+   |            ^^^^^^^^^^^^^^^^^^^^^^ expected at most 2 type argument
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issue-53251.rs b/src/test/ui/issue-53251.rs
index aa9da744566..8c75ea45a61 100644
--- a/src/test/ui/issue-53251.rs
+++ b/src/test/ui/issue-53251.rs
@@ -19,10 +19,12 @@ macro_rules! impl_add {
         $(
             fn $n() {
                 S::f::<i64>();
-                //~^ ERROR too many type parameters provided
+                //~^ ERROR wrong number of type arguments
             }
         )*
     }
 }
 
 impl_add!(a b);
+
+fn main() {}
diff --git a/src/test/ui/issue-53251.stderr b/src/test/ui/issue-53251.stderr
index bf99e73f0d9..f12afa4a792 100644
--- a/src/test/ui/issue-53251.stderr
+++ b/src/test/ui/issue-53251.stderr
@@ -1,17 +1,12 @@
-error[E0601]: `main` function not found in crate `issue_53251`
-   |
-   = note: consider adding a `main` function to `$DIR/issue-53251.rs`
-
-error[E0087]: too many type parameters provided: expected at most 0 type parameters, found 1 type parameter
+error[E0087]: wrong number of type arguments: expected 0, found 1
   --> $DIR/issue-53251.rs:21:24
    |
 LL |                 S::f::<i64>();
-   |                        ^^^ expected 0 type parameters
+   |                        ^^^ unexpected type argument
 ...
 LL | impl_add!(a b);
    | --------------- in this macro invocation
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors occurred: E0087, E0601.
-For more information about an error, try `rustc --explain E0087`.
+For more information about this error, try `rustc --explain E0087`.
diff --git a/src/test/ui/issues/issue-18423.rs b/src/test/ui/issues/issue-18423.rs
index 5945a7a1c9a..f550dc6f310 100644
--- a/src/test/ui/issues/issue-18423.rs
+++ b/src/test/ui/issues/issue-18423.rs
@@ -8,10 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Test that `Box` cannot be used with a lifetime parameter.
+// Test that `Box` cannot be used with a lifetime argument.
 
 struct Foo<'a> {
-    x: Box<'a, isize> //~ ERROR wrong number of lifetime parameters
+    x: Box<'a, isize> //~ ERROR wrong number of lifetime arguments
 }
 
 pub fn main() {
diff --git a/src/test/ui/issues/issue-18423.stderr b/src/test/ui/issues/issue-18423.stderr
index 25406198193..49afd513092 100644
--- a/src/test/ui/issues/issue-18423.stderr
+++ b/src/test/ui/issues/issue-18423.stderr
@@ -1,8 +1,8 @@
-error[E0107]: wrong number of lifetime parameters: expected 0, found 1
-  --> $DIR/issue-18423.rs:14:8
+error[E0107]: wrong number of lifetime arguments: expected 0, found 1
+  --> $DIR/issue-18423.rs:14:12
    |
-LL |     x: Box<'a, isize> //~ ERROR wrong number of lifetime parameters
-   |        ^^^^^^^^^^^^^^ unexpected lifetime parameter
+LL |     x: Box<'a, isize> //~ ERROR wrong number of lifetime arguments
+   |            ^^ unexpected lifetime argument
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-3214.stderr b/src/test/ui/issues/issue-3214.stderr
index 1298e4a007d..2c4b9f84105 100644
--- a/src/test/ui/issues/issue-3214.stderr
+++ b/src/test/ui/issues/issue-3214.stderr
@@ -10,10 +10,10 @@ LL |         x: T, //~ ERROR can't use type parameters from outer function
    |            ^ use of type variable from outer function
 
 error[E0244]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/issue-3214.rs:16:22
+  --> $DIR/issue-3214.rs:16:26
    |
 LL |     impl<T> Drop for foo<T> {
-   |                      ^^^^^^ expected no type arguments
+   |                          ^ unexpected type argument
 
 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 f0a87c74703..980ada9020c 100644
--- a/src/test/ui/methods/method-call-lifetime-args-fail.rs
+++ b/src/test/ui/methods/method-call-lifetime-args-fail.rs
@@ -24,9 +24,9 @@ impl S {
 fn method_call() {
     S.early(); // OK
     S.early::<'static>();
-    //~^ ERROR expected 2 lifetime parameters, found 1 lifetime parameter
+    //~^ ERROR wrong number of lifetime arguments: expected 2, found 1
     S.early::<'static, 'static, 'static>();
-    //~^ ERROR expected at most 2 lifetime parameters, found 3 lifetime parameters
+    //~^ ERROR wrong number of lifetime arguments: expected 2, found 3
     let _: &u8 = S.life_and_type::<'static>();
     S.life_and_type::<u8>();
     S.life_and_type::<'static, u8>();
@@ -71,9 +71,9 @@ fn ufcs() {
 
     S::early(S); // OK
     S::early::<'static>(S);
-    //~^ ERROR expected 2 lifetime parameters, found 1 lifetime parameter
+    //~^ ERROR wrong number of lifetime arguments: expected 2, found 1
     S::early::<'static, 'static, 'static>(S);
-    //~^ ERROR expected at most 2 lifetime parameters, found 3 lifetime parameters
+    //~^ ERROR wrong number of lifetime arguments: expected 2, found 3
     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 3814f4b5065..d86a9f48e00 100644
--- a/src/test/ui/methods/method-call-lifetime-args-fail.stderr
+++ b/src/test/ui/methods/method-call-lifetime-args-fail.stderr
@@ -1,14 +1,14 @@
-error[E0090]: too few lifetime parameters provided: expected 2 lifetime parameters, found 1 lifetime parameter
+error[E0090]: wrong number of lifetime arguments: expected 2, found 1
   --> $DIR/method-call-lifetime-args-fail.rs:26:7
    |
 LL |     S.early::<'static>();
-   |       ^^^^^ expected 2 lifetime parameters
+   |       ^^^^^ expected 2 lifetime arguments
 
-error[E0088]: too many lifetime parameters provided: expected at most 2 lifetime parameters, found 3 lifetime parameters
+error[E0088]: wrong number of lifetime arguments: expected 2, found 3
   --> $DIR/method-call-lifetime-args-fail.rs:28:33
    |
 LL |     S.early::<'static, 'static, 'static>();
-   |                                 ^^^^^^^ expected 2 lifetime parameters
+   |                                 ^^^^^^^ unexpected lifetime argument
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/method-call-lifetime-args-fail.rs:37:15
@@ -178,17 +178,17 @@ note: the late bound lifetime parameter is introduced here
 LL |     fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} }
    |                          ^^
 
-error[E0090]: too few lifetime parameters provided: expected 2 lifetime parameters, found 1 lifetime parameter
+error[E0090]: wrong number of lifetime arguments: expected 2, found 1
   --> $DIR/method-call-lifetime-args-fail.rs:73:5
    |
 LL |     S::early::<'static>(S);
-   |     ^^^^^^^^^^^^^^^^^^^ expected 2 lifetime parameters
+   |     ^^^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
 
-error[E0088]: too many lifetime parameters provided: expected at most 2 lifetime parameters, found 3 lifetime parameters
+error[E0088]: wrong number of lifetime arguments: expected 2, found 3
   --> $DIR/method-call-lifetime-args-fail.rs:75:34
    |
 LL |     S::early::<'static, 'static, 'static>(S);
-   |                                  ^^^^^^^ expected 2 lifetime parameters
+   |                                  ^^^^^^^ unexpected lifetime argument
 
 error: aborting due to 18 previous errors
 
diff --git a/src/test/ui/seq-args.stderr b/src/test/ui/seq-args.stderr
index dc9d0a7fc0b..068f08eebe7 100644
--- a/src/test/ui/seq-args.stderr
+++ b/src/test/ui/seq-args.stderr
@@ -1,14 +1,14 @@
 error[E0244]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/seq-args.rs:14:9
+  --> $DIR/seq-args.rs:14:13
    |
 LL | impl<T> seq<T> for Vec<T> { //~ ERROR wrong number of type arguments
-   |         ^^^^^^ expected no type arguments
+   |             ^ unexpected type argument
 
 error[E0244]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/seq-args.rs:17:6
+  --> $DIR/seq-args.rs:17:10
    |
 LL | impl seq<bool> for u32 { //~ ERROR wrong number of type arguments
-   |      ^^^^^^^^^ expected no type arguments
+   |          ^^^^ unexpected type argument
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/structs/structure-constructor-type-mismatch.stderr b/src/test/ui/structs/structure-constructor-type-mismatch.stderr
index 1a88bc09dd6..dfa219e0872 100644
--- a/src/test/ui/structs/structure-constructor-type-mismatch.stderr
+++ b/src/test/ui/structs/structure-constructor-type-mismatch.stderr
@@ -71,10 +71,10 @@ LL |         x: 7,
               found type `{integer}`
 
 error[E0244]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/structure-constructor-type-mismatch.rs:58:15
+  --> $DIR/structure-constructor-type-mismatch.rs:58:24
    |
 LL |     let pt3 = PointF::<i32> { //~ ERROR wrong number of type arguments
-   |               ^^^^^^^^^^^^^ expected no type arguments
+   |                        ^^^ unexpected type argument
 
 error[E0308]: mismatched types
   --> $DIR/structure-constructor-type-mismatch.rs:59:12
@@ -101,10 +101,10 @@ LL |         y: 10, //~ ERROR mismatched types
               found type `{integer}`
 
 error[E0244]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/structure-constructor-type-mismatch.rs:64:9
+  --> $DIR/structure-constructor-type-mismatch.rs:64:18
    |
 LL |         PointF::<u32> { .. } => {} //~ ERROR wrong number of type arguments
-   |         ^^^^^^^^^^^^^ expected no type arguments
+   |                  ^^^ unexpected type argument
 
 error[E0308]: mismatched types
   --> $DIR/structure-constructor-type-mismatch.rs:64:9
diff --git a/src/test/ui/traits/trait-object-vs-lifetime.rs b/src/test/ui/traits/trait-object-vs-lifetime.rs
index a70141edc29..954e20e3345 100644
--- a/src/test/ui/traits/trait-object-vs-lifetime.rs
+++ b/src/test/ui/traits/trait-object-vs-lifetime.rs
@@ -21,7 +21,7 @@ fn main() {
     let _: S<'static, 'static +>;
     //~^ at least one non-builtin trait is required for an object type
     let _: S<'static, 'static>;
-    //~^ ERROR wrong number of lifetime parameters: expected 1, found 2
+    //~^ ERROR wrong number of lifetime arguments: expected 1, found 2
     //~| ERROR wrong number of type arguments: expected 1, found 0
     let _: S<'static +, 'static>;
     //~^ ERROR lifetime parameters must be declared prior to type parameters
diff --git a/src/test/ui/traits/trait-object-vs-lifetime.stderr b/src/test/ui/traits/trait-object-vs-lifetime.stderr
index d875e7d4845..c0b65a7aa5c 100644
--- a/src/test/ui/traits/trait-object-vs-lifetime.stderr
+++ b/src/test/ui/traits/trait-object-vs-lifetime.stderr
@@ -10,11 +10,11 @@ error[E0224]: at least one non-builtin trait is required for an object type
 LL |     let _: S<'static, 'static +>;
    |                       ^^^^^^^^^
 
-error[E0107]: wrong number of lifetime parameters: expected 1, found 2
-  --> $DIR/trait-object-vs-lifetime.rs:23:12
+error[E0107]: wrong number of lifetime arguments: expected 1, found 2
+  --> $DIR/trait-object-vs-lifetime.rs:23:23
    |
 LL |     let _: S<'static, 'static>;
-   |            ^^^^^^^^^^^^^^^^^^^ unexpected lifetime parameter
+   |                       ^^^^^^^ unexpected lifetime argument
 
 error[E0243]: wrong number of type arguments: expected 1, found 0
   --> $DIR/trait-object-vs-lifetime.rs:23:12
diff --git a/src/test/ui/traits/trait-test-2.rs b/src/test/ui/traits/trait-test-2.rs
index b08aab6da85..dac76fb57fd 100644
--- a/src/test/ui/traits/trait-test-2.rs
+++ b/src/test/ui/traits/trait-test-2.rs
@@ -15,8 +15,8 @@ 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 expected at most 0 type parameters, found 1 type parameter
-    10.blah::<i32, i32>(); //~ ERROR expected at most 1 type parameter, found 2 type parameters
+    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
     (box 10 as Box<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 58e91447963..fb9cd701922 100644
--- a/src/test/ui/traits/trait-test-2.stderr
+++ b/src/test/ui/traits/trait-test-2.stderr
@@ -1,14 +1,14 @@
-error[E0087]: too many type parameters provided: expected at most 0 type parameters, found 1 type parameter
+error[E0087]: wrong number of type arguments: expected 0, found 1
   --> $DIR/trait-test-2.rs:18:14
    |
-LL |     10.dup::<i32>(); //~ ERROR expected at most 0 type parameters, found 1 type parameter
-   |              ^^^ expected 0 type parameters
+LL |     10.dup::<i32>(); //~ ERROR wrong number of type arguments: expected 0, found 1
+   |              ^^^ unexpected type argument
 
-error[E0087]: too many type parameters provided: expected at most 1 type parameter, found 2 type parameters
+error[E0087]: wrong number of type arguments: expected 1, found 2
   --> $DIR/trait-test-2.rs:19:20
    |
-LL |     10.blah::<i32, i32>(); //~ ERROR expected at most 1 type parameter, found 2 type parameters
-   |                    ^^^ expected 1 type parameter
+LL |     10.blah::<i32, i32>(); //~ ERROR wrong number of type arguments: expected 1, found 2
+   |                    ^^^ unexpected type argument
 
 error[E0277]: the trait bound `dyn bar: bar` is not satisfied
   --> $DIR/trait-test-2.rs:20:26
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 15fc3ecab97..9285b8ca6bc 100644
--- a/src/test/ui/typeck/typeck-builtin-bound-type-parameters.rs
+++ b/src/test/ui/typeck/typeck-builtin-bound-type-parameters.rs
@@ -18,12 +18,12 @@ struct MyStruct1<T: Copy<T>>;
 //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0244]
 
 struct MyStruct2<'a, T: Copy<'a>>;
-//~^ ERROR: wrong number of lifetime parameters: expected 0, found 1
+//~^ ERROR: wrong number of lifetime arguments: expected 0, found 1
 
 
 fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
 //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0244]
-//~| ERROR: wrong number of lifetime parameters: expected 0, found 1
+//~| ERROR: wrong number of lifetime arguments: expected 0, found 1
 
 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 221f05b9150..b6444181dd8 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,38 @@
 error[E0244]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/typeck-builtin-bound-type-parameters.rs:11:11
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:11:16
    |
 LL | fn foo1<T:Copy<U>, U>(x: T) {}
-   |           ^^^^^^^ expected no type arguments
+   |                ^ unexpected type argument
 
 error[E0244]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/typeck-builtin-bound-type-parameters.rs:14:14
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:14:19
    |
 LL | trait Trait: Copy<Send> {}
-   |              ^^^^^^^^^^ expected no type arguments
+   |                   ^^^^ unexpected type argument
 
 error[E0244]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/typeck-builtin-bound-type-parameters.rs:17:21
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:17:26
    |
 LL | struct MyStruct1<T: Copy<T>>;
-   |                     ^^^^^^^ expected no type arguments
+   |                          ^ unexpected type argument
 
-error[E0107]: wrong number of lifetime parameters: expected 0, found 1
-  --> $DIR/typeck-builtin-bound-type-parameters.rs:20:25
+error[E0107]: wrong number of lifetime arguments: expected 0, found 1
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:20:30
    |
 LL | struct MyStruct2<'a, T: Copy<'a>>;
-   |                         ^^^^^^^^ unexpected lifetime parameter
+   |                              ^^ unexpected lifetime argument
 
-error[E0107]: wrong number of lifetime parameters: expected 0, found 1
-  --> $DIR/typeck-builtin-bound-type-parameters.rs:24:15
+error[E0107]: wrong number of lifetime arguments: expected 0, found 1
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:24:20
    |
 LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
-   |               ^^^^^^^^^^^ unexpected lifetime parameter
+   |                    ^^ unexpected lifetime argument
 
 error[E0244]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/typeck-builtin-bound-type-parameters.rs:24:15
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:24:24
    |
 LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
-   |               ^^^^^^^^^^^ expected no type arguments
+   |                        ^ unexpected type argument
 
 error: aborting due to 6 previous errors
 
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 fe9566b3181..a49839b7310 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,8 @@
 error[E0244]: wrong number of type arguments: expected 1, found 2
-  --> $DIR/typeck_type_placeholder_lifetime_1.rs:19:12
+  --> $DIR/typeck_type_placeholder_lifetime_1.rs:19:19
    |
 LL |     let c: Foo<_, _> = Foo { r: &5 };
-   |            ^^^^^^^^^ expected 1 type argument
+   |                   ^ unexpected type argument
 
 error: aborting due to previous error
 
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 64ec4245466..cafb6f507a0 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,8 @@
 error[E0244]: wrong number of type arguments: expected 1, found 2
-  --> $DIR/typeck_type_placeholder_lifetime_2.rs:19:12
+  --> $DIR/typeck_type_placeholder_lifetime_2.rs:19:19
    |
 LL |     let c: Foo<_, usize> = Foo { r: &5 };
-   |            ^^^^^^^^^^^^^ expected 1 type argument
+   |                   ^^^^^ unexpected type argument
 
 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 5c108e05216..294a0fa0340 100644
--- a/src/test/ui/ufcs/ufcs-qpath-missing-params.rs
+++ b/src/test/ui/ufcs/ufcs-qpath-missing-params.rs
@@ -22,5 +22,5 @@ impl<'a> IntoCow<'a, str> for String {
 
 fn main() {
     <String as IntoCow>::into_cow("foo".to_string());
-    //~^ ERROR too few type parameters provided: expected 1 type parameter
+    //~^ ERROR wrong number of type arguments: expected 1, found 0
 }
diff --git a/src/test/ui/ufcs/ufcs-qpath-missing-params.stderr b/src/test/ui/ufcs/ufcs-qpath-missing-params.stderr
index 6c752dba6b4..2653b7bf4ac 100644
--- a/src/test/ui/ufcs/ufcs-qpath-missing-params.stderr
+++ b/src/test/ui/ufcs/ufcs-qpath-missing-params.stderr
@@ -1,8 +1,8 @@
-error[E0089]: too few type parameters provided: expected 1 type parameter, found 0 type parameters
+error[E0089]: wrong number of type arguments: expected 1, found 0
   --> $DIR/ufcs-qpath-missing-params.rs:24:5
    |
 LL |     <String as IntoCow>::into_cow("foo".to_string());
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 type parameter
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 type argument
 
 error: aborting due to previous error
 
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 18a1185d695..331ad620c27 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.rs
@@ -38,7 +38,7 @@ fn test<'a,'b>() {
 }
 
 fn test2(x: &Foo<(isize,),Output=()>, y: &Foo(isize)) {
-//~^ ERROR wrong number of lifetime parameters: expected 1, found 0
+//~^ ERROR wrong number of lifetime arguments: expected 1, found 0
     // 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 663034ba143..2245c5e6648 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,8 @@
-error[E0107]: wrong number of lifetime parameters: expected 1, found 0
+error[E0107]: wrong number of lifetime arguments: expected 1, found 0
   --> $DIR/unboxed-closure-sugar-region.rs:40:43
    |
 LL | fn test2(x: &Foo<(isize,),Output=()>, y: &Foo(isize)) {
-   |                                           ^^^^^^^^^^ expected 1 lifetime parameter
+   |                                           ^^^^^^^^^^ expected 1 lifetime argument
 
 error: aborting due to previous error
 
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 457bea046c7..89587c47cf6 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,8 +1,8 @@
 error[E0244]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:15:11
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:15:15
    |
 LL | fn foo(_: Zero())
-   |           ^^^^^^ expected no type arguments
+   |               ^^ unexpected type argument
 
 error[E0220]: associated type `Output` not found for `Zero`
   --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:15:15
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 82ba4e66393..5d8c86f5a58 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,8 @@
 error[E0244]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/unboxed-closure-sugar-wrong-trait.rs:15:8
+  --> $DIR/unboxed-closure-sugar-wrong-trait.rs:15:13
    |
 LL | fn f<F:Trait(isize) -> isize>(x: F) {}
-   |        ^^^^^^^^^^^^^^^^^^^^^ expected no type arguments
+   |             ^^^^^^^^^^^^^^^^ unexpected type argument
 
 error[E0220]: associated type `Output` not found for `Trait`
   --> $DIR/unboxed-closure-sugar-wrong-trait.rs:15:24