about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_typeck/astconv.rs23
-rw-r--r--src/librustc_typeck/check/method/confirm.rs8
-rw-r--r--src/librustc_typeck/check/mod.rs149
-rw-r--r--src/test/ui/error-codes/E0087.rs4
-rw-r--r--src/test/ui/error-codes/E0087.stderr16
-rw-r--r--src/test/ui/error-codes/E0088.stderr12
-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
10 files changed, 65 insertions, 163 deletions
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 2e59c5959fb..3cd435e756e 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -90,6 +90,11 @@ struct ConvertedBinding<'tcx> {
     span: Span,
 }
 
+pub struct GenericArgMismatchErrorCode {
+    pub lifetimes: (&'static str, &'static str),
+    pub types: (&'static str, &'static str),
+}
+
 /// Dummy type used for the `Self` of a `TraitRef` created for converting
 /// a trait object, and which gets removed in `ExistentialTraitRef`.
 /// This type must not appear anywhere in other converted types.
@@ -199,6 +204,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
         is_method_call: bool,
         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
@@ -243,8 +249,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
             }
         }
 
-        let check_kind_count = |error_code_less: &str,
-                                error_code_more: &str,
+        let check_kind_count = |error_code: (&str, &str),
                                 kind,
                                 required,
                                 permitted,
@@ -296,9 +301,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
                 ),
                 DiagnosticId::Error({
                     if provided <= permitted {
-                        error_code_less
+                        error_code.0
                     } else {
-                        error_code_more
+                        error_code.1
                     }
                 }.into())
             ).span_label(span, label).emit();
@@ -308,8 +313,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
 
         if !infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes {
             check_kind_count(
-                "E0107",
-                "E0107",
+                error_codes.lifetimes,
                 "lifetime",
                 param_counts.lifetimes,
                 param_counts.lifetimes,
@@ -319,8 +323,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
         if !infer_types
             || arg_counts.types > param_counts.types - defaults.types - has_self as usize {
             check_kind_count(
-                "E0243",
-                "E0244", // FIXME: E0243 and E0244 should be unified.
+                error_codes.types,
                 "type",
                 param_counts.types - defaults.types - has_self as usize,
                 param_counts.types - has_self as usize,
@@ -508,6 +511,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
             false, // `is_method_call` (irrelevant here)
             has_self,
             infer_types,
+            GenericArgMismatchErrorCode {
+                lifetimes: ("E0107", "E0107"),
+                types: ("E0243", "E0244"), // FIXME: E0243 and E0244 should be unified.
+            },
         );
 
         let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF);
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 49225680432..88c540915af 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -10,7 +10,7 @@
 
 use super::{probe, MethodCallee};
 
-use astconv::AstConv;
+use astconv::{AstConv, GenericArgMismatchErrorCode};
 use check::{FnCtxt, PlaceOp, callee, Needs};
 use hir::GenericArg;
 use hir::def_id::DefId;
@@ -329,9 +329,11 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
             true, // `is_method_call`
             method_generics.parent.is_none() && method_generics.has_self,
             segment.infer_types || suppress_mismatch,
+            GenericArgMismatchErrorCode {
+                lifetimes: ("E0090", "E0088"),
+                types: ("E0089", "E0087"),
+            },
         );
-        // self.fcx.check_generic_arg_count(self.span, &segment, &method_generics, true,
-                                        //  supress_mismatch);
 
         // Create subst for early-bound lifetime parameters, combining
         // parameters from the type and those from the method.
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index ae5c0fc6fb1..17adfda0bac 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -84,9 +84,10 @@ pub use self::compare_method::{compare_impl_method, compare_const_impl};
 use self::method::MethodCallee;
 use self::TupleArgumentsFlag::*;
 
-use astconv::AstConv;
+use astconv::{AstConv, GenericArgMismatchErrorCode};
 use hir::GenericArg;
 use hir::def::Def;
+use hir::HirVec;
 use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use std::slice;
 use namespace::Namespace;
@@ -4937,16 +4938,30 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // to add defaults. If the user provided *too many* types, that's
         // a problem.
 
-        let mut supress_errors = FxHashMap();
+        let mut suppress_errors = FxHashMap();
         for &PathSeg(def_id, index) in &path_segs {
             let seg = &segments[index];
             let generics = self.tcx.generics_of(def_id);
             // `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 supress_mismatch = self.check_impl_trait(span, seg, &generics);
-            supress_errors.insert(index,
-                self.check_generic_arg_count(span, seg, &generics, false, supress_mismatch));
+            let suppress_mismatch = self.check_impl_trait(span, seg, &generics);
+            suppress_errors.insert(index, AstConv::check_generic_arg_count(
+                self.tcx,
+                span,
+                &generics,
+                &seg.args.clone().unwrap_or_else(|| P(hir::GenericArgs {
+                    args: HirVec::new(), bindings: HirVec::new(), parenthesized: false,
+                })),
+                false, // `is_declaration`
+                false, // `is_method_call`
+                generics.parent.is_none() && generics.has_self,
+                seg.infer_types || suppress_mismatch,
+                GenericArgMismatchErrorCode {
+                    lifetimes: ("E0090", "E0088"), // FIXME: E0090 and E0088 should be unified.
+                    types: ("E0089", "E0087"), // FIXME: E0089 and E0087 should be unified.
+                },
+            ));
         }
 
         let has_self = path_segs.last().map(|PathSeg(def_id, _)| {
@@ -4968,7 +4983,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 }) {
                     // If we've encountered an `impl Trait`-related error, we're just
                     // going to infer the arguments for better error messages.
-                    if !supress_errors[&index] {
+                    if !suppress_errors[&index] {
                         // Check whether the user has provided generic arguments.
                         if let Some(ref data) = segments[index].args {
                             return (Some(data), segments[index].infer_types);
@@ -5097,128 +5112,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: &hir::PathSegment,
-                               generics: &ty::Generics,
-                               is_method_call: bool,
-                               supress_mismatch_error: bool)
-                               -> bool {
-        let mut supress_errors = false;
-        let (mut lifetimes, mut types) = (vec![], vec![]);
-        let infer_types = segment.infer_types;
-        let mut bindings = vec![];
-        if let Some(ref data) = segment.args {
-            data.args.iter().for_each(|arg| match arg {
-                GenericArg::Lifetime(lt) => lifetimes.push(lt.clone()),
-                GenericArg::Type(ty) => types.push(ty.clone()),
-            });
-            bindings = data.bindings.clone().to_vec();
-        }
-
-        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;
-        }
-        let ty_accepted = ty_params.accepted;
-        let ty_required = ty_params.required;
-
-        let count_ty_params = |n| format!("{} type parameter{}", n, if n == 1 { "" } else { "s" });
-        let expected_text = count_ty_params(ty_accepted);
-        let actual_text = count_ty_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.
-            supress_errors = true;
-            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_assoc_ty_binding(self.tcx, 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 = 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) {
-                supress_errors = true;
-                let mut err = self.tcx.sess.struct_span_err(lifetimes[0].span, primary_msg);
-                err.span_note(span_late, note_msg);
-                err.emit();
-            } 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 supress_errors;
-        }
-
-        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();
-        }
-
-        supress_errors
-    }
-
     /// Report error if there is an explicit type parameter when using `impl Trait`.
     fn check_impl_trait(&self,
                         span: Span,
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..7170a6f2cda 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
-  --> $DIR/E0087.rs:15:11
+error[E0087]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/E0087.rs:15:5
    |
-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
-  --> $DIR/E0087.rs:17:16
+error[E0087]: wrong number of type arguments: expected 1, found 2
+  --> $DIR/E0087.rs:17:5
    |
-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..4666702e1eb 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
-  --> $DIR/E0088.rs:15:9
+error[E0088]: wrong number of lifetime arguments: expected 0, found 1
+  --> $DIR/E0088.rs:15:5
    |
 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
-  --> $DIR/E0088.rs:16:18
+error[E0088]: wrong number of lifetime arguments: expected 1, found 2
+  --> $DIR/E0088.rs:16:5
    |
 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