diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 2573a967985a..4af8dd982a7f 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -92,6 +92,13 @@ struct ConvertedBinding<'tcx> { span: Span, } +#[derive(PartialEq)] +enum GenericArgPosition { + Datatype, + Function, + Method, +} + struct GenericArgMismatchErrorCode { lifetimes: (&'static str, &'static str), types: (&'static str, &'static str), @@ -247,8 +254,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { } else { &empty_args }, - false, // `is_declaration` - is_method_call, + if is_method_call { + GenericArgPosition::Method + } else { + GenericArgPosition::Function + }, def.parent.is_none() && def.has_self, // `has_self` seg.infer_types || suppress_mismatch, // `infer_types` GenericArgMismatchErrorCode { @@ -259,14 +269,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { } /// Check that the correct number of generic arguments have been provided. - /// This is used both for type declarations and function calls. + /// This is used both for datatypes and function calls. fn check_generic_arg_count( tcx: TyCtxt, span: Span, def: &ty::Generics, args: &hir::GenericArgs, - is_declaration: bool, - is_method_call: bool, + position: GenericArgPosition, has_self: bool, infer_types: bool, error_codes: GenericArgMismatchErrorCode, @@ -276,7 +285,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { // 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 = !is_declaration && arg_counts.lifetimes == 0; + let infer_lifetimes = position != GenericArgPosition::Datatype && arg_counts.lifetimes == 0; let mut defaults: ty::GenericParamCount = Default::default(); for param in &def.params { @@ -288,7 +297,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { }; } - if !is_declaration && !args.bindings.is_empty() { + if position != GenericArgPosition::Datatype && !args.bindings.is_empty() { AstConv::prohibit_assoc_ty_binding(tcx, args.bindings[0].span); } @@ -299,7 +308,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { if late bound lifetime parameters are present"; let note = "the late bound lifetime parameter is introduced here"; let span = args.args[0].span(); - if !is_method_call && arg_counts.lifetimes != param_counts.lifetimes { + if position == GenericArgPosition::Function + && arg_counts.lifetimes != param_counts.lifetimes { let mut err = tcx.sess.struct_span_err(span, msg); err.span_note(span_late, note); err.emit(); @@ -328,15 +338,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { // 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, suppress_error) = if required != permitted { + let (bound, quantifier) = if required != permitted { if provided < required { - (required, "at least ", false) + (required, "at least ") } else { // provided > permitted - (permitted, "at most ", true) + (permitted, "at most ") } } else { - (required, "", false) + (required, "") }; + let label = if required == permitted && provided > permitted { let diff = provided - permitted; format!( @@ -373,7 +384,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { }.into()) ).span_label(span, label).emit(); - suppress_error + provided > required // `suppress_error` }; if !infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes { @@ -572,8 +583,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { span, &generic_params, &generic_args, - true, // `is_declaration` - false, // `is_method_call` (irrelevant here) + GenericArgPosition::Datatype, has_self, infer_types, GenericArgMismatchErrorCode { 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 4645142ea66f..1ee70d9bddea 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 for S2 { fn foo<'a>() { let _ = S::new::(1, 1.0); - //~^ ERROR too many type parameters provided + //~^ ERROR wrong number of type arguments let _ = S::<'a,isize>::new::(1, 1.0); //~^ ERROR wrong number of lifetime arguments let _: S2 = Trait::new::(1, 1.0); - //~^ ERROR too many type parameters provided + //~^ ERROR wrong number of type arguments let _: S2 = Trait::<'a,isize>::new::(1, 1.0); - //~^ ERROR too many lifetime parameters provided + //~^ ERROR wrong number of lifetime arguments } fn main() {} diff --git a/src/test/ui/constructor-lifetime-args.rs b/src/test/ui/constructor-lifetime-args.rs index 50db9707355f..1fe50cfebbac 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/methods/method-call-lifetime-args-fail.rs b/src/test/ui/methods/method-call-lifetime-args-fail.rs index f0a87c747038..980ada9020c4 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::(); 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::(S); S::life_and_type::<'static, u8>(S); diff --git a/src/test/ui/traits/trait-test-2.rs b/src/test/ui/traits/trait-test-2.rs index b08aab6da852..dac76fb57fd7 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(&self) {} } impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah(&self) {} } fn main() { - 10.dup::(); //~ ERROR expected at most 0 type parameters, found 1 type parameter - 10.blah::(); //~ ERROR expected at most 1 type parameter, found 2 type parameters + 10.dup::(); //~ ERROR wrong number of type arguments: expected 0, found 1 + 10.blah::(); //~ ERROR wrong number of type arguments: expected 1, found 2 (box 10 as Box).dup(); //~^ ERROR E0038 //~| ERROR E0038 diff --git a/src/test/ui/ufcs/ufcs-qpath-missing-params.rs b/src/test/ui/ufcs/ufcs-qpath-missing-params.rs index 5c108e052160..294a0fa0340c 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() { ::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 }