From 3829746ef9356be7ab766efcbc328aeb1d5a555f Mon Sep 17 00:00:00 2001 From: David Wood Date: Sat, 30 Mar 2019 20:30:36 +0100 Subject: [PATCH] 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. --- src/librustc_passes/ast_validation.rs | 37 ++++++++++++++++++--------- src/test/ui/issue-59508.fixed | 16 ++++++++++++ src/test/ui/issue-59508.rs | 16 ++++++++++++ src/test/ui/issue-59508.stderr | 8 ++++++ 4 files changed, 65 insertions(+), 12 deletions(-) create mode 100644 src/test/ui/issue-59508.fixed create mode 100644 src/test/ui/issue-59508.rs create mode 100644 src/test/ui/issue-59508.stderr diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 4e2aefe6231..917564b17df 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -361,7 +361,14 @@ enum GenericPosition { fn validate_generics_order<'a>( handler: &errors::Handler, - generics: impl Iterator)>, + generics: impl Iterator< + Item = ( + ParamKindOrd, + Option<&'a [GenericBound]>, + Span, + Option + ), + >, 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 @@ fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) { 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` @@ -736,16 +749,16 @@ fn visit_generics(&mut self, generics: &'a Generics) { } 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 { diff --git a/src/test/ui/issue-59508.fixed b/src/test/ui/issue-59508.fixed new file mode 100644 index 00000000000..b5c60a1626f --- /dev/null +++ b/src/test/ui/issue-59508.fixed @@ -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() {} diff --git a/src/test/ui/issue-59508.rs b/src/test/ui/issue-59508.rs new file mode 100644 index 00000000000..0b39c5d8f2a --- /dev/null +++ b/src/test/ui/issue-59508.rs @@ -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() { + //~^ ERROR lifetime parameters must be declared prior to type parameters + println!("panic"); + } +} + +fn main() {} diff --git a/src/test/ui/issue-59508.stderr b/src/test/ui/issue-59508.stderr new file mode 100644 index 00000000000..33e967cebff --- /dev/null +++ b/src/test/ui/issue-59508.stderr @@ -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() { + | ----^^--^^----- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b: 'a, T>` + +error: aborting due to previous error + -- 2.44.0