@@ -481,6 +481,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
481481 parent_substs : & [ subst:: GenericArg < ' tcx > ] ,
482482 has_self : bool ,
483483 self_ty : Option < Ty < ' tcx > > ,
484+ arg_count_mismatch : bool ,
484485 args_for_def_id : impl Fn ( DefId ) -> ( Option < & ' b GenericArgs < ' b > > , bool ) ,
485486 provided_kind : impl Fn ( & GenericParamDef , & GenericArg < ' _ > ) -> subst:: GenericArg < ' tcx > ,
486487 mut inferred_kind : impl FnMut (
@@ -504,7 +505,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
504505 // methods in `subst.rs`, so that we can iterate over the arguments and
505506 // parameters in lock-step linearly, instead of trying to match each pair.
506507 let mut substs: SmallVec < [ subst:: GenericArg < ' tcx > ; 8 ] > = SmallVec :: with_capacity ( count) ;
507-
508508 // Iterate over each segment of the path.
509509 while let Some ( ( def_id, defs) ) = stack. pop ( ) {
510510 let mut params = defs. params . iter ( ) . peekable ( ) ;
@@ -541,6 +541,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
541541 let mut args =
542542 generic_args. iter ( ) . flat_map ( |generic_args| generic_args. args . iter ( ) ) . peekable ( ) ;
543543
544+ let arg_kind = |arg| match arg {
545+ & GenericArg :: Lifetime ( _) => "lifetime" ,
546+ & GenericArg :: Type ( _) => "type" ,
547+ & GenericArg :: Const ( _) => "constant" ,
548+ } ;
549+
550+ // If we encounter a type or const when we expect a lifetime, we infer the lifetimes.
551+ // If we later encounter a lifetime, we know that the arguments were provided in the
552+ // wrong order. `force_infer_lt` records the type or const that forced lifetimes to be
553+ // inferred, so we can use it for diagnostics later.
554+ let mut force_infer_lt = None ;
555+
544556 loop {
545557 // We're going to iterate through the generic arguments that the user
546558 // provided, matching them with the generic parameters we expect.
@@ -561,28 +573,74 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
561573 // We expected a lifetime argument, but got a type or const
562574 // argument. That means we're inferring the lifetimes.
563575 substs. push ( inferred_kind ( None , param, infer_args) ) ;
576+ force_infer_lt = Some ( arg) ;
564577 params. next ( ) ;
565578 }
566- ( _, _ ) => {
579+ ( _, kind ) => {
567580 // We expected one kind of parameter, but the user provided
568- // another. This is an error, but we need to handle it
569- // gracefully so we can report sensible errors.
570- // In this case, we're simply going to infer this argument.
571- args. next ( ) ;
581+ // another. This is an error. However, if we already know that
582+ // the arguments don't match up with the parameters, we won't issue
583+ // an additional error, as the user already knows what's wrong.
584+ if !arg_count_mismatch {
585+ let param_kind = match kind {
586+ GenericParamDefKind :: Lifetime => "lifetime" ,
587+ GenericParamDefKind :: Type { .. } => "type" ,
588+ GenericParamDefKind :: Const => "constant" ,
589+ } ;
590+ struct_span_err ! (
591+ tcx. sess,
592+ arg. span( ) ,
593+ E0747 ,
594+ "{} provided when a {} was expected" ,
595+ arg_kind( arg) ,
596+ param_kind,
597+ )
598+ . emit ( ) ;
599+ }
600+
601+ // We've reported the error, but we want to make sure that this
602+ // problem doesn't bubble down and create additional, irrelevant
603+ // errors. In this case, we're simply going to ignore the argument
604+ // and any following arguments. The rest of the parameters will be
605+ // inferred.
606+ while args. next ( ) . is_some ( ) { }
572607 }
573608 }
574609 }
575- ( Some ( _ ) , None ) => {
610+ ( Some ( & arg ) , None ) => {
576611 // We should never be able to reach this point with well-formed input.
577- // Getting to this point means the user supplied more arguments than
578- // there are parameters.
579- args. next ( ) ;
612+ // There are two situations in which we can encounter this issue.
613+ //
614+ // 1. The number of arguments is incorrect. In this case, an error
615+ // will already have been emitted, and we can ignore it. This case
616+ // also occurs when late-bound lifetime parameters are present, yet
617+ // the lifetime arguments have also been explicitly specified by the
618+ // user.
619+ // 2. We've inferred some lifetimes, which have been provided later (i.e.
620+ // after a type or const). We want to throw an error in this case.
621+
622+ if !arg_count_mismatch {
623+ let kind = arg_kind ( arg) ;
624+ assert_eq ! ( kind, "lifetime" ) ;
625+ let provided =
626+ force_infer_lt. expect ( "lifetimes ought to have been inferred" ) ;
627+ struct_span_err ! (
628+ tcx. sess,
629+ provided. span( ) ,
630+ E0747 ,
631+ "{} provided when a {} was expected" ,
632+ arg_kind( provided) ,
633+ kind,
634+ )
635+ . emit ( ) ;
636+ }
637+
638+ break ;
580639 }
581640 ( None , Some ( & param) ) => {
582641 // If there are fewer arguments than parameters, it means
583642 // we're inferring the remaining arguments.
584643 substs. push ( inferred_kind ( Some ( & substs) , param, infer_args) ) ;
585- args. next ( ) ;
586644 params. next ( ) ;
587645 }
588646 ( None , None ) => break ,
@@ -658,7 +716,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
658716 assert ! ( self_ty. is_none( ) && parent_substs. is_empty( ) ) ;
659717 }
660718
661- let ( _ , potential_assoc_types) = Self :: check_generic_arg_count (
719+ let ( arg_count_mismatch , potential_assoc_types) = Self :: check_generic_arg_count (
662720 tcx,
663721 span,
664722 & generic_params,
@@ -691,6 +749,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
691749 parent_substs,
692750 self_ty. is_some ( ) ,
693751 self_ty,
752+ arg_count_mismatch,
694753 // Provide the generic args, and whether types should be inferred.
695754 |did| {
696755 if did == def_id {
0 commit comments