Skip to content

Commit 3829746

Browse files
committed
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.
1 parent e782d79 commit 3829746

File tree

4 files changed

+65
-12
lines changed

4 files changed

+65
-12
lines changed

src/librustc_passes/ast_validation.rs

+25-12
Original file line numberDiff line numberDiff line change
@@ -361,17 +361,24 @@ enum GenericPosition {
361361

362362
fn validate_generics_order<'a>(
363363
handler: &errors::Handler,
364-
generics: impl Iterator<Item = (ParamKindOrd, Span, Option<String>)>,
364+
generics: impl Iterator<
365+
Item = (
366+
ParamKindOrd,
367+
Option<&'a [GenericBound]>,
368+
Span,
369+
Option<String>
370+
),
371+
>,
365372
pos: GenericPosition,
366373
span: Span,
367374
) {
368375
let mut max_param: Option<ParamKindOrd> = None;
369376
let mut out_of_order = FxHashMap::default();
370377
let mut param_idents = vec![];
371378

372-
for (kind, span, ident) in generics {
379+
for (kind, bounds, span, ident) in generics {
373380
if let Some(ident) = ident {
374-
param_idents.push((kind, param_idents.len(), ident));
381+
param_idents.push((kind, bounds, param_idents.len(), ident));
375382
}
376383
let max_param = &mut max_param;
377384
match max_param {
@@ -385,13 +392,19 @@ fn validate_generics_order<'a>(
385392

386393
let mut ordered_params = "<".to_string();
387394
if !out_of_order.is_empty() {
388-
param_idents.sort_by_key(|&(po, i, _)| (po, i));
395+
param_idents.sort_by_key(|&(po, _, i, _)| (po, i));
389396
let mut first = true;
390-
for (_, _, ident) in param_idents {
397+
for (_, bounds, _, ident) in param_idents {
391398
if !first {
392399
ordered_params += ", ";
393400
}
394401
ordered_params += &ident;
402+
if let Some(bounds) = bounds {
403+
if !bounds.is_empty() {
404+
ordered_params += ": ";
405+
ordered_params += &pprust::bounds_to_string(&bounds);
406+
}
407+
}
395408
first = false;
396409
}
397410
}
@@ -701,7 +714,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
701714
GenericArg::Lifetime(..) => ParamKindOrd::Lifetime,
702715
GenericArg::Type(..) => ParamKindOrd::Type,
703716
GenericArg::Const(..) => ParamKindOrd::Const,
704-
}, arg.span(), None)
717+
}, None, arg.span(), None)
705718
}), GenericPosition::Arg, generic_args.span());
706719

707720
// Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
@@ -736,16 +749,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
736749
}
737750

738751
validate_generics_order(self.err_handler(), generics.params.iter().map(|param| {
739-
let span = param.ident.span;
740752
let ident = Some(param.ident.to_string());
741-
match &param.kind {
742-
GenericParamKind::Lifetime { .. } => (ParamKindOrd::Lifetime, span, ident),
743-
GenericParamKind::Type { .. } => (ParamKindOrd::Type, span, ident),
753+
let (kind, ident) = match &param.kind {
754+
GenericParamKind::Lifetime { .. } => (ParamKindOrd::Lifetime, ident),
755+
GenericParamKind::Type { .. } => (ParamKindOrd::Type, ident),
744756
GenericParamKind::Const { ref ty } => {
745757
let ty = pprust::ty_to_string(ty);
746-
(ParamKindOrd::Const, span, Some(format!("const {}: {}", param.ident, ty)))
758+
(ParamKindOrd::Const, Some(format!("const {}: {}", param.ident, ty)))
747759
}
748-
}
760+
};
761+
(kind, Some(&*param.bounds), param.ident.span, ident)
749762
}), GenericPosition::Param, generics.span);
750763

751764
for predicate in &generics.where_clause.predicates {

src/test/ui/issue-59508.fixed

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// run-rustfix
2+
3+
#![allow(dead_code)]
4+
5+
// This test checks that generic parameter re-ordering diagnostic suggestions contain bounds.
6+
7+
struct A;
8+
9+
impl A {
10+
pub fn do_things<'a, 'b: 'a, T>() {
11+
//~^ ERROR lifetime parameters must be declared prior to type parameters
12+
println!("panic");
13+
}
14+
}
15+
16+
fn main() {}

src/test/ui/issue-59508.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// run-rustfix
2+
3+
#![allow(dead_code)]
4+
5+
// This test checks that generic parameter re-ordering diagnostic suggestions contain bounds.
6+
7+
struct A;
8+
9+
impl A {
10+
pub fn do_things<T, 'a, 'b: 'a>() {
11+
//~^ ERROR lifetime parameters must be declared prior to type parameters
12+
println!("panic");
13+
}
14+
}
15+
16+
fn main() {}

src/test/ui/issue-59508.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: lifetime parameters must be declared prior to type parameters
2+
--> $DIR/issue-59508.rs:10:25
3+
|
4+
LL | pub fn do_things<T, 'a, 'b: 'a>() {
5+
| ----^^--^^----- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b: 'a, T>`
6+
7+
error: aborting due to previous error
8+

0 commit comments

Comments
 (0)