8
8
use crate :: collect:: PlaceholderHirTyCollector ;
9
9
use crate :: middle:: resolve_lifetime as rl;
10
10
use 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} ;
13
12
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
14
13
use rustc_errors:: ErrorReported ;
15
14
use rustc_errors:: { pluralize, struct_span_err, Applicability , DiagnosticId , FatalError } ;
@@ -27,7 +26,7 @@ use rustc_middle::ty::{GenericParamDef, GenericParamDefKind};
27
26
use rustc_session:: lint:: builtin:: { AMBIGUOUS_ASSOCIATED_ITEMS , LATE_BOUND_LIFETIME_ARGUMENTS } ;
28
27
use rustc_session:: parse:: feature_err;
29
28
use rustc_session:: Session ;
30
- use rustc_span:: symbol:: { sym, Ident , Symbol } ;
29
+ use rustc_span:: symbol:: { kw , sym, Ident , Symbol } ;
31
30
use rustc_span:: { MultiSpan , Span , DUMMY_SP } ;
32
31
use rustc_target:: spec:: abi;
33
32
use rustc_trait_selection:: traits;
@@ -475,7 +474,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
475
474
476
475
/// Report an error that a generic argument did not match the generic parameter that was
477
476
/// 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
+ ) {
479
483
let mut err = struct_span_err ! (
480
484
sess,
481
485
arg. span( ) ,
@@ -503,6 +507,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
503
507
let ( first, last) =
504
508
if kind_ord < arg_ord { ( kind, arg. descr ( ) ) } else { ( arg. descr ( ) , kind) } ;
505
509
err. note ( & format ! ( "{} arguments must be provided before {} arguments" , first, last) ) ;
510
+
511
+ if let Some ( help) = help {
512
+ err. help ( help) ;
513
+ }
506
514
err. emit ( ) ;
507
515
}
508
516
@@ -648,7 +656,60 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
648
656
if arg_count. correct . is_ok ( )
649
657
&& arg_count. explicit_late_bound == ExplicitLateBound :: No
650
658
{
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
+ ) ;
652
713
}
653
714
654
715
// We've reported the error, but we want to make sure that this
@@ -680,7 +741,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
680
741
assert_eq ! ( kind, "lifetime" ) ;
681
742
let provided =
682
743
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 ) ;
684
745
}
685
746
686
747
break ;
0 commit comments