@@ -29,7 +29,7 @@ use std::slice;
2929use require_c_abi_if_variadic;
3030use util:: common:: ErrorReported ;
3131use util:: nodemap:: { FxHashSet , FxHashMap } ;
32- use errors:: FatalError ;
32+ use errors:: { FatalError , DiagnosticId } ;
3333
3434use std:: iter;
3535use syntax:: ast;
@@ -89,11 +89,6 @@ struct ConvertedBinding<'tcx> {
8989 span : Span ,
9090}
9191
92- struct ParamRange {
93- required : usize ,
94- accepted : usize
95- }
96-
9792/// Dummy type used for the `Self` of a `TraitRef` created for converting
9893/// a trait object, and which gets removed in `ExistentialTraitRef`.
9994/// This type must not appear anywhere in other converted types.
@@ -346,56 +341,21 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
346341 self_ty : Option < Ty < ' tcx > > )
347342 -> ( & ' tcx Substs < ' tcx > , Vec < ConvertedBinding < ' tcx > > )
348343 {
349- let tcx = self . tcx ( ) ;
350-
351- debug ! ( "create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \
352- generic_args={:?})",
353- def_id, self_ty, generic_args) ;
354-
355344 // If the type is parameterized by this region, then replace this
356345 // region with the current anon region binding (in other words,
357346 // whatever & would get replaced with).
358- let mut lt_provided = 0 ;
359- let mut ty_provided = 0 ;
360- for arg in & generic_args. args {
361- match arg {
362- GenericArg :: Lifetime ( _) => lt_provided += 1 ,
363- GenericArg :: Type ( _) => ty_provided += 1 ,
364- }
365- }
366-
367- let decl_generics = tcx. generics_of ( def_id) ;
368- let mut lt_accepted = 0 ;
369- let mut ty_params = ParamRange { required : 0 , accepted : 0 } ;
370- for param in & decl_generics. params {
371- match param. kind {
372- GenericParamDefKind :: Lifetime => {
373- lt_accepted += 1 ;
374- }
375- GenericParamDefKind :: Type { has_default, .. } => {
376- ty_params. accepted += 1 ;
377- if !has_default {
378- ty_params. required += 1 ;
379- }
380- }
381- } ;
382- }
383- if self_ty. is_some ( ) {
384- ty_params. required -= 1 ;
385- ty_params. accepted -= 1 ;
386- }
347+ debug ! ( "create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \
348+ generic_args={:?})",
349+ def_id, self_ty, generic_args) ;
387350
388- if lt_accepted != lt_provided {
389- report_lifetime_number_error ( tcx, span, lt_provided, lt_accepted) ;
390- }
351+ let tcx = self . tcx ( ) ;
352+ let generic_params = tcx. generics_of ( def_id) ;
391353
392354 // If a self-type was declared, one should be provided.
393- assert_eq ! ( decl_generics . has_self, self_ty. is_some( ) ) ;
355+ assert_eq ! ( generic_params . has_self, self_ty. is_some( ) ) ;
394356
395- // Check the number of type parameters supplied by the user.
396- if !infer_types || ty_provided > ty_params. required {
397- check_type_argument_count ( tcx, span, ty_provided, ty_params) ;
398- }
357+ let has_self = generic_params. has_self ;
358+ check_generic_arg_count ( tcx, span, & generic_params, & generic_args, has_self, infer_types) ;
399359
400360 let is_object = self_ty. map_or ( false , |ty| ty. sty == TRAIT_OBJECT_DUMMY_SELF ) ;
401361 let default_needs_object_self = |param : & ty:: GenericParamDef | {
@@ -492,8 +452,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
492452 }
493453 } ) . collect ( ) ;
494454
495- debug ! ( "create_substs_for_ast_path(decl_generics ={:?}, self_ty={:?}) -> {:?}" ,
496- decl_generics , self_ty, substs) ;
455+ debug ! ( "create_substs_for_ast_path(generic_params ={:?}, self_ty={:?}) -> {:?}" ,
456+ generic_params , self_ty, substs) ;
497457
498458 ( substs, assoc_bindings)
499459 }
@@ -1537,70 +1497,107 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
15371497 ( auto_traits, trait_bounds)
15381498}
15391499
1540- fn check_type_argument_count ( tcx : TyCtxt ,
1541- span : Span ,
1542- supplied : usize ,
1543- ty_params : ParamRange )
1544- {
1545- let ( required, accepted) = ( ty_params. required , ty_params. accepted ) ;
1546- if supplied < required {
1547- let expected = if required < accepted {
1548- "expected at least"
1549- } else {
1550- "expected"
1551- } ;
1552- let arguments_plural = if required == 1 { "" } else { "s" } ;
1553-
1554- struct_span_err ! ( tcx. sess, span, E0243 ,
1555- "wrong number of type arguments: {} {}, found {}" ,
1556- expected, required, supplied)
1557- . span_label ( span,
1558- format ! ( "{} {} type argument{}" ,
1559- expected,
1560- required,
1561- arguments_plural) )
1562- . emit ( ) ;
1563- } else if supplied > accepted {
1564- let expected = if required < accepted {
1565- format ! ( "expected at most {}" , accepted)
1566- } else {
1567- format ! ( "expected {}" , accepted)
1500+ pub fn check_generic_arg_count (
1501+ tcx : TyCtxt ,
1502+ span : Span ,
1503+ def : & ty:: Generics ,
1504+ args : & hir:: GenericArgs ,
1505+ has_self : bool ,
1506+ infer_types : bool ,
1507+ ) {
1508+ // At this stage we are guaranteed that the generic arguments are in the correct order, e.g.
1509+ // that lifetimes will proceed types. So it suffices to check the number of each generic
1510+ // arguments in order to validate them with respect to the generic parameters.
1511+ let param_counts = def. own_counts ( ) ;
1512+ let arg_counts = args. own_counts ( ) ;
1513+
1514+ let mut defaults: ty:: GenericParamCount = Default :: default ( ) ;
1515+ for param in & def. params {
1516+ match param. kind {
1517+ GenericParamDefKind :: Lifetime => { }
1518+ GenericParamDefKind :: Type { has_default, .. } => defaults. types += has_default as usize ,
15681519 } ;
1569- let arguments_plural = if accepted == 1 { "" } else { "s" } ;
1570-
1571- struct_span_err ! ( tcx. sess, span, E0244 ,
1572- "wrong number of type arguments: {}, found {}" ,
1573- expected, supplied)
1574- . span_label (
1575- span,
1576- format ! ( "{} type argument{}" ,
1577- if accepted == 0 { "expected no" } else { & expected } ,
1578- arguments_plural)
1579- )
1580- . emit ( ) ;
15811520 }
1582- }
15831521
1584- fn report_lifetime_number_error ( tcx : TyCtxt , span : Span , number : usize , expected : usize ) {
1585- let label = if number < expected {
1586- if expected == 1 {
1587- format ! ( "expected {} lifetime parameter" , expected)
1588- } else {
1589- format ! ( "expected {} lifetime parameters" , expected)
1522+ let check_kind_count = |error_code_less : & str ,
1523+ error_code_more : & str ,
1524+ kind,
1525+ required,
1526+ permitted,
1527+ provided| {
1528+ // We enforce the following: `required` <= `provided` <= `permitted`.
1529+ // For kinds without defaults (i.e. lifetimes), `required == permitted`.
1530+ // For other kinds (i.e. types), `permitted` may be greater than `required`.
1531+ if required <= provided && provided <= permitted {
1532+ return ;
15901533 }
1591- } else {
1592- let additional = number - expected;
1593- if additional == 1 {
1594- "unexpected lifetime parameter" . to_string ( )
1534+
1535+ // Unfortunately lifetime and type parameter mismatches are typically styled
1536+ // differently in diagnostics, which means we have a few cases to consider here.
1537+ let ( bound, quantifier) = if required != permitted {
1538+ if provided < required {
1539+ ( required, "at least " )
1540+ } else { // provided > permitted
1541+ ( permitted, "at most " )
1542+ }
15951543 } else {
1596- format ! ( "{} unexpected lifetime parameters" , additional)
1597- }
1544+ ( required, "" )
1545+ } ;
1546+ let label = if required == permitted && provided > permitted {
1547+ let diff = provided - permitted;
1548+ format ! (
1549+ "{}unexpected {} argument{}" ,
1550+ if diff != 1 { format!( "{} " , diff) } else { String :: new( ) } ,
1551+ kind,
1552+ if diff != 1 { "s" } else { "" } ,
1553+ )
1554+ } else {
1555+ format ! (
1556+ "expected {}{} {} argument{}" ,
1557+ quantifier,
1558+ bound,
1559+ kind,
1560+ if required != 1 { "s" } else { "" } ,
1561+ )
1562+ } ;
1563+
1564+ tcx. sess . struct_span_err_with_code (
1565+ span,
1566+ & format ! (
1567+ "wrong number of {} arguments: expected {}{}, found {}" ,
1568+ kind,
1569+ quantifier,
1570+ bound,
1571+ provided,
1572+ ) ,
1573+ DiagnosticId :: Error ( {
1574+ if provided <= permitted {
1575+ error_code_less
1576+ } else {
1577+ error_code_more
1578+ }
1579+ } . into ( ) )
1580+ ) . span_label ( span, label) . emit ( ) ;
15981581 } ;
1599- struct_span_err ! ( tcx. sess, span, E0107 ,
1600- "wrong number of lifetime parameters: expected {}, found {}" ,
1601- expected, number)
1602- . span_label ( span, label)
1603- . emit ( ) ;
1582+
1583+ check_kind_count (
1584+ "E0107" ,
1585+ "E0107" ,
1586+ "lifetime" ,
1587+ param_counts. lifetimes ,
1588+ param_counts. lifetimes ,
1589+ arg_counts. lifetimes ,
1590+ ) ;
1591+ if !infer_types || arg_counts. types > param_counts. types - defaults. types - has_self as usize {
1592+ check_kind_count (
1593+ "E0243" ,
1594+ "E0244" , // FIXME: E0243 and E0244 should be unified.
1595+ "type" ,
1596+ param_counts. types - defaults. types - has_self as usize ,
1597+ param_counts. types - has_self as usize ,
1598+ arg_counts. types ,
1599+ ) ;
1600+ }
16041601}
16051602
16061603// A helper struct for conveniently grouping a set of bounds which we pass to
0 commit comments