88use crate :: collect:: PlaceholderHirTyCollector ;
99use crate :: middle:: resolve_lifetime as rl;
1010use crate :: require_c_abi_if_c_variadic;
11- use rustc_ast:: ast:: ParamKindOrd ;
12- use rustc_ast:: util:: lev_distance:: find_best_match_for_name;
11+ use rustc_ast:: { ast:: ParamKindOrd , util:: lev_distance:: find_best_match_for_name} ;
1312use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
1413use rustc_errors:: ErrorReported ;
1514use rustc_errors:: { pluralize, struct_span_err, Applicability , DiagnosticId , FatalError } ;
@@ -27,7 +26,7 @@ use rustc_middle::ty::{GenericParamDef, GenericParamDefKind};
2726use rustc_session:: lint:: builtin:: { AMBIGUOUS_ASSOCIATED_ITEMS , LATE_BOUND_LIFETIME_ARGUMENTS } ;
2827use rustc_session:: parse:: feature_err;
2928use rustc_session:: Session ;
30- use rustc_span:: symbol:: { sym, Ident , Symbol } ;
29+ use rustc_span:: symbol:: { kw , sym, Ident , Symbol } ;
3130use rustc_span:: { MultiSpan , Span , DUMMY_SP } ;
3231use rustc_target:: spec:: abi;
3332use rustc_trait_selection:: traits;
@@ -475,7 +474,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
475474
476475 /// Report an error that a generic argument did not match the generic parameter that was
477476 /// expected.
478- fn generic_arg_mismatch_err ( sess : & Session , arg : & GenericArg < ' _ > , kind : & ' static str ) {
477+ fn generic_arg_mismatch_err (
478+ sess : & Session ,
479+ arg : & GenericArg < ' _ > ,
480+ kind : & ' static str ,
481+ help : Option < & str > ,
482+ ) {
479483 let mut err = struct_span_err ! (
480484 sess,
481485 arg. span( ) ,
@@ -503,6 +507,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
503507 let ( first, last) =
504508 if kind_ord < arg_ord { ( kind, arg. descr ( ) ) } else { ( arg. descr ( ) , kind) } ;
505509 err. note ( & format ! ( "{} arguments must be provided before {} arguments" , first, last) ) ;
510+
511+ if let Some ( help) = help {
512+ err. help ( help) ;
513+ }
506514 err. emit ( ) ;
507515 }
508516
@@ -648,7 +656,60 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
648656 if arg_count. correct . is_ok ( )
649657 && arg_count. explicit_late_bound == ExplicitLateBound :: No
650658 {
651- Self :: generic_arg_mismatch_err ( tcx. sess , arg, kind. descr ( ) ) ;
659+ // We're going to iterate over the parameters to sort them out, and
660+ // show that order to the user as a possible order for the parameters
661+ let mut param_types_present = defs
662+ . params
663+ . clone ( )
664+ . into_iter ( )
665+ . map ( |param| {
666+ (
667+ match param. kind {
668+ GenericParamDefKind :: Lifetime => {
669+ ParamKindOrd :: Lifetime
670+ }
671+ GenericParamDefKind :: Type { .. } => {
672+ ParamKindOrd :: Type
673+ }
674+ GenericParamDefKind :: Const => {
675+ ParamKindOrd :: Const
676+ }
677+ } ,
678+ param,
679+ )
680+ } )
681+ . collect :: < Vec < ( ParamKindOrd , GenericParamDef ) > > ( ) ;
682+ param_types_present. sort_by_key ( |( ord, _) | * ord) ;
683+ let ( mut param_types_present, ordered_params) : (
684+ Vec < ParamKindOrd > ,
685+ Vec < GenericParamDef > ,
686+ ) = param_types_present. into_iter ( ) . unzip ( ) ;
687+ param_types_present. dedup ( ) ;
688+
689+ Self :: generic_arg_mismatch_err (
690+ tcx. sess ,
691+ arg,
692+ kind. descr ( ) ,
693+ Some ( & format ! (
694+ "reorder the arguments: {}: `<{}>`" ,
695+ param_types_present
696+ . into_iter( )
697+ . map( |ord| format!( "{}s" , ord. to_string( ) ) )
698+ . collect:: <Vec <String >>( )
699+ . join( ", then " ) ,
700+ ordered_params
701+ . into_iter( )
702+ . filter_map( |param| {
703+ if param. name == kw:: SelfUpper {
704+ None
705+ } else {
706+ Some ( param. name. to_string( ) )
707+ }
708+ } )
709+ . collect:: <Vec <String >>( )
710+ . join( ", " )
711+ ) ) ,
712+ ) ;
652713 }
653714
654715 // We've reported the error, but we want to make sure that this
@@ -680,7 +741,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
680741 assert_eq ! ( kind, "lifetime" ) ;
681742 let provided =
682743 force_infer_lt. expect ( "lifetimes ought to have been inferred" ) ;
683- Self :: generic_arg_mismatch_err ( tcx. sess , provided, kind) ;
744+ Self :: generic_arg_mismatch_err ( tcx. sess , provided, kind, None ) ;
684745 }
685746
686747 break ;
0 commit comments