This commit extends the existing generic re-ordering diagnostic to
include any bounds on the generic parameter, thus producing correct
suggestions.
fn validate_generics_order<'a>(
handler: &errors::Handler,
fn validate_generics_order<'a>(
handler: &errors::Handler,
- generics: impl Iterator<Item = (ParamKindOrd, Span, Option<String>)>,
+ generics: impl Iterator<
+ Item = (
+ ParamKindOrd,
+ Option<&'a [GenericBound]>,
+ Span,
+ Option<String>
+ ),
+ >,
pos: GenericPosition,
span: Span,
) {
pos: GenericPosition,
span: Span,
) {
let mut out_of_order = FxHashMap::default();
let mut param_idents = vec![];
let mut out_of_order = FxHashMap::default();
let mut param_idents = vec![];
- for (kind, span, ident) in generics {
+ for (kind, bounds, span, ident) in generics {
if let Some(ident) = ident {
if let Some(ident) = ident {
- param_idents.push((kind, param_idents.len(), ident));
+ param_idents.push((kind, bounds, param_idents.len(), ident));
}
let max_param = &mut max_param;
match max_param {
}
let max_param = &mut max_param;
match max_param {
let mut ordered_params = "<".to_string();
if !out_of_order.is_empty() {
let mut ordered_params = "<".to_string();
if !out_of_order.is_empty() {
- param_idents.sort_by_key(|&(po, i, _)| (po, i));
+ param_idents.sort_by_key(|&(po, _, i, _)| (po, i));
- for (_, _, ident) in param_idents {
+ for (_, bounds, _, ident) in param_idents {
if !first {
ordered_params += ", ";
}
ordered_params += &ident;
if !first {
ordered_params += ", ";
}
ordered_params += &ident;
+ if let Some(bounds) = bounds {
+ if !bounds.is_empty() {
+ ordered_params += ": ";
+ ordered_params += &pprust::bounds_to_string(&bounds);
+ }
+ }
GenericArg::Lifetime(..) => ParamKindOrd::Lifetime,
GenericArg::Type(..) => ParamKindOrd::Type,
GenericArg::Const(..) => ParamKindOrd::Const,
GenericArg::Lifetime(..) => ParamKindOrd::Lifetime,
GenericArg::Type(..) => ParamKindOrd::Type,
GenericArg::Const(..) => ParamKindOrd::Const,
+ }, None, arg.span(), None)
}), GenericPosition::Arg, generic_args.span());
// Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
}), GenericPosition::Arg, generic_args.span());
// Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
}
validate_generics_order(self.err_handler(), generics.params.iter().map(|param| {
}
validate_generics_order(self.err_handler(), generics.params.iter().map(|param| {
- let span = param.ident.span;
let ident = Some(param.ident.to_string());
let ident = Some(param.ident.to_string());
- match ¶m.kind {
- GenericParamKind::Lifetime { .. } => (ParamKindOrd::Lifetime, span, ident),
- GenericParamKind::Type { .. } => (ParamKindOrd::Type, span, ident),
+ let (kind, ident) = match ¶m.kind {
+ GenericParamKind::Lifetime { .. } => (ParamKindOrd::Lifetime, ident),
+ GenericParamKind::Type { .. } => (ParamKindOrd::Type, ident),
GenericParamKind::Const { ref ty } => {
let ty = pprust::ty_to_string(ty);
GenericParamKind::Const { ref ty } => {
let ty = pprust::ty_to_string(ty);
- (ParamKindOrd::Const, span, Some(format!("const {}: {}", param.ident, ty)))
+ (ParamKindOrd::Const, Some(format!("const {}: {}", param.ident, ty)))
+ };
+ (kind, Some(&*param.bounds), param.ident.span, ident)
}), GenericPosition::Param, generics.span);
for predicate in &generics.where_clause.predicates {
}), GenericPosition::Param, generics.span);
for predicate in &generics.where_clause.predicates {
--- /dev/null
+// run-rustfix
+
+#![allow(dead_code)]
+
+// This test checks that generic parameter re-ordering diagnostic suggestions contain bounds.
+
+struct A;
+
+impl A {
+ pub fn do_things<'a, 'b: 'a, T>() {
+ //~^ ERROR lifetime parameters must be declared prior to type parameters
+ println!("panic");
+ }
+}
+
+fn main() {}
--- /dev/null
+// run-rustfix
+
+#![allow(dead_code)]
+
+// This test checks that generic parameter re-ordering diagnostic suggestions contain bounds.
+
+struct A;
+
+impl A {
+ pub fn do_things<T, 'a, 'b: 'a>() {
+ //~^ ERROR lifetime parameters must be declared prior to type parameters
+ println!("panic");
+ }
+}
+
+fn main() {}
--- /dev/null
+error: lifetime parameters must be declared prior to type parameters
+ --> $DIR/issue-59508.rs:10:25
+ |
+LL | pub fn do_things<T, 'a, 'b: 'a>() {
+ | ----^^--^^----- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b: 'a, T>`
+
+error: aborting due to previous error
+