Include bounds in generic reordering diagnostic.
This commit extends the existing generic re-ordering diagnostic to include any bounds on the generic parameter, thus producing correct suggestions.
This commit is contained in:
parent
e782d790f1
commit
3829746ef9
4 changed files with 65 additions and 12 deletions
|
@ -361,7 +361,14 @@ enum GenericPosition {
|
|||
|
||||
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,
|
||||
) {
|
||||
|
@ -369,9 +376,9 @@ fn validate_generics_order<'a>(
|
|||
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 {
|
||||
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 {
|
||||
|
@ -385,13 +392,19 @@ fn validate_generics_order<'a>(
|
|||
|
||||
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));
|
||||
let mut first = true;
|
||||
for (_, _, ident) in param_idents {
|
||||
for (_, bounds, _, ident) in param_idents {
|
||||
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);
|
||||
}
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
@ -701,7 +714,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
GenericArg::Lifetime(..) => ParamKindOrd::Lifetime,
|
||||
GenericArg::Type(..) => ParamKindOrd::Type,
|
||||
GenericArg::Const(..) => ParamKindOrd::Const,
|
||||
}, arg.span(), None)
|
||||
}, None, arg.span(), None)
|
||||
}), GenericPosition::Arg, generic_args.span());
|
||||
|
||||
// Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
|
||||
|
@ -736,16 +749,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
}
|
||||
|
||||
validate_generics_order(self.err_handler(), generics.params.iter().map(|param| {
|
||||
let span = param.ident.span;
|
||||
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);
|
||||
(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 {
|
||||
|
|
16
src/test/ui/issue-59508.fixed
Normal file
16
src/test/ui/issue-59508.fixed
Normal file
|
@ -0,0 +1,16 @@
|
|||
// 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() {}
|
16
src/test/ui/issue-59508.rs
Normal file
16
src/test/ui/issue-59508.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
// 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() {}
|
8
src/test/ui/issue-59508.stderr
Normal file
8
src/test/ui/issue-59508.stderr
Normal file
|
@ -0,0 +1,8 @@
|
|||
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
|
||||
|
Loading…
Add table
Reference in a new issue