Change:
The current diagnostics are a little ad hoc and rely on counting the number of mismatches (e.g. they will only produce an error for the first mismatch). It would be nice to produce diagnostics like: cc <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --This issue has been assigned to via . <!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
This is follow up work for
Please give more context on this. I am not sure the error message of which test should be improved.
This is more of the kind of issue opened to avoid forgetting about finishing some work, sorry for the confusion. That is, this is leaving a TODO to themselves about improving the diagnostics from .
Ok. I see. Thanks for the explanation.
That said, if is too busy to work on this, you could talk to them on Discord or Zulip to see what their plans were, and maybe turn this into a mentored issue.
The idea is essentially this. We currently emit errors telling the user that the generic arguments they provide are in the wrong order: However, what we'd like to do is suggest reordering the parameters, and let rustfix automatically apply the suggestion. I don't have the bandwidth to work on this at the moment, or any time soon, so if anyone is interested in tackling it, I'll be happy to mentor the issue.
would you mind if I take this up?
you're very welcome to! Let me know if you need any guidance in tackling this issue!
claim

Discussion:
use crate::collect::PlaceholderHirTyCollector; use crate::middle::resolve_lifetime as rl; use crate::require_c_abi_if_c_variadic; <del> use rustc_ast::ast::ParamKindOrd; use rustc_ast::util::lev_distance::find_best_match_for_name; </del> <ins> use rustc_ast::{ast::ParamKindOrd, util::lev_distance::find_best_match_for_name}; </ins> use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::ErrorReported; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, FatalError};

use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, LATE_BOUND_LIFETIME_ARGUMENTS}; use rustc_session::parse::feature_err; use rustc_session::Session; <del> use rustc_span::symbol::{sym, Ident, Symbol}; </del> <ins> use rustc_span::symbol::{kw, sym, Ident, Symbol}; </ins> use rustc_span::{MultiSpan, Span, DUMMY_SP}; use rustc_target::spec::abi; use rustc_trait_selection::traits;

/// Report an error that a generic argument did not match the generic parameter that was /// expected. <del> fn generic_arg_mismatch_err(sess: &Session, arg: &GenericArg<'_>, kind: &'static str) { </del> <ins> fn generic_arg_mismatch_err( sess: &Session, arg: &GenericArg<'_>, kind: &'static str, help: Option<&str>, ) { </ins> let mut err = struct_span_err!( sess, arg.span(),

let (first, last) = if kind_ord < arg_ord { (kind, arg.descr()) } else { (arg.descr(), kind) }; err.note(&format!("{} arguments must be provided before {} arguments", first, last)); <ins> if let Some(help) = help { err.help(help); } </ins> err.emit(); }

if arg_count.correct.is_ok() && arg_count.explicit_late_bound == ExplicitLateBound::No { <del> Self::generic_arg_mismatch_err(tcx.sess, arg, kind.descr()); </del> <ins> // We're going to iterate over the parameters to sort them out, and // show that order to the user as a possible order for the parameters let mut param_types_present = defs .params .clone() .into_iter() .map(|param| { ( match param.kind { GenericParamDefKind::Lifetime => { ParamKindOrd::Lifetime } GenericParamDefKind::Type { .. } => { ParamKindOrd::Type } GenericParamDefKind::Const => { ParamKindOrd::Const } }, param, ) }) .collect::<Vec<(ParamKindOrd, GenericParamDef)>>(); param_types_present.sort_by_key(|(ord, _)| *ord); let (mut param_types_present, ordered_params): ( Vec<ParamKindOrd>, Vec<GenericParamDef>, ) = param_types_present.into_iter().unzip(); param_types_present.dedup(); Self::generic_arg_mismatch_err( tcx.sess, arg, kind.descr(), Some(&format!( "reorder the arguments: {}: `<{}>`", param_types_present .into_iter() .map(|ord| format!("{}s", ord.to_string())) .collect::<Vec<String>>() .join(", then "), ordered_params .into_iter() .filter_map(|param| { if param.name == kw::SelfUpper { None } else { Some(param.name.to_string()) } }) .collect::<Vec<String>>() .join(", ") )), ); </ins> } // We've reported the error, but we want to make sure that this

assert_eq!(kind, "lifetime"); let provided = force_infer_lt.expect("lifetimes ought to have been inferred"); <del> Self::generic_arg_mismatch_err(tcx.sess, provided, kind); </del> <ins> Self::generic_arg_mismatch_err(tcx.sess, provided, kind, None); </ins> } break;

|                                   ^ | = note: type arguments must be provided before constant arguments <ins> = help: reorder the arguments: types, then consts: `<T, N>` </ins> error: aborting due to previous error; 1 warning emitted

|                                                        ^^ | = note: lifetime arguments must be provided before type arguments <ins> = help: reorder the arguments: lifetimes, then types: `<'a, 'b, 'c, T, U, V>` </ins> error[E0747]: lifetime provided when a type was expected --> $DIR/suggest-move-types.rs:82:56

|                                                        ^^ | = note: lifetime arguments must be provided before type arguments <ins> = help: reorder the arguments: lifetimes, then types: `<'a, 'b, 'c, T, U, V>` </ins> error: aborting due to 12 previous errors