From 7a0abbff8be746e46841ac7eef5a17364d6b8b51 Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 25 Jan 2019 00:36:28 +0100 Subject: [PATCH] Combining move lifetime and type suggestions. This commit combines the move lifetime and move type suggestions so that when rustfix applies them they don't conflict with each other. --- src/libsyntax/parse/parser.rs | 103 +++++++++++++----- src/test/ui/suggestions/suggest-move-types.rs | 43 ++++++++ .../ui/suggestions/suggest-move-types.stderr | 68 +++++++++++- 3 files changed, 179 insertions(+), 35 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 232b8bb5966c7..955dce47721e2 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5611,49 +5611,92 @@ impl<'a> Parser<'a> { } } - if !bad_lifetime_pos.is_empty() { - let mut err = self.struct_span_err( + self.maybe_report_incorrect_generic_argument_order( + bad_lifetime_pos, bad_type_pos, lifetime_suggestions, type_suggestions + ); + + Ok((args, bindings)) + } + + /// Maybe report an error about incorrect generic argument order - "lifetime parameters + /// must be declared before type parameters", "type parameters must be declared before + /// associated type bindings" or both. + fn maybe_report_incorrect_generic_argument_order( + &self, + bad_lifetime_pos: Vec, + bad_type_pos: Vec, + lifetime_suggestions: Vec<(Span, String)>, + type_suggestions: Vec<(Span, String)>, + ) { + let mut err = if !bad_lifetime_pos.is_empty() && !bad_type_pos.is_empty() { + let mut positions = bad_lifetime_pos.clone(); + positions.extend_from_slice(&bad_type_pos); + + self.struct_span_err( + positions, + "generic arguments must declare lifetimes, types and associated type bindings in \ + that order", + ) + } else if !bad_lifetime_pos.is_empty() { + self.struct_span_err( bad_lifetime_pos.clone(), "lifetime parameters must be declared prior to type parameters" - ); + ) + } else if !bad_type_pos.is_empty() { + self.struct_span_err( + bad_type_pos.clone(), + "type parameters must be declared prior to associated type bindings" + ) + } else { + return; + }; + + if !bad_lifetime_pos.is_empty() { for sp in &bad_lifetime_pos { err.span_label(*sp, "must be declared prior to type parameters"); } - if !lifetime_suggestions.is_empty() { - err.multipart_suggestion_with_applicability( - &format!( - "move the lifetime parameter{} prior to the first type parameter", - if bad_lifetime_pos.len() > 1 { "s" } else { "" }, - ), - lifetime_suggestions, - Applicability::MachineApplicable, - ); - } - err.emit(); } if !bad_type_pos.is_empty() { - let mut err = self.struct_span_err( - bad_type_pos.clone(), - "type parameters must be declared prior to associated type bindings" - ); for sp in &bad_type_pos { err.span_label(*sp, "must be declared prior to associated type bindings"); } - if !type_suggestions.is_empty() { - err.multipart_suggestion_with_applicability( - &format!( - "move the type parameter{} prior to the first associated type binding", - if bad_type_pos.len() > 1 { "s" } else { "" }, - ), - type_suggestions, - Applicability::MachineApplicable, - ); - } - err.emit(); } - Ok((args, bindings)) + if !lifetime_suggestions.is_empty() && !type_suggestions.is_empty() { + let mut suggestions = lifetime_suggestions; + suggestions.extend_from_slice(&type_suggestions); + + let plural = bad_lifetime_pos.len() + bad_type_pos.len() > 1; + err.multipart_suggestion_with_applicability( + &format!( + "move the parameter{}", + if plural { "s" } else { "" }, + ), + suggestions, + Applicability::MachineApplicable, + ); + } else if !lifetime_suggestions.is_empty() { + err.multipart_suggestion_with_applicability( + &format!( + "move the lifetime parameter{} prior to the first type parameter", + if bad_lifetime_pos.len() > 1 { "s" } else { "" }, + ), + lifetime_suggestions, + Applicability::MachineApplicable, + ); + } else if !type_suggestions.is_empty() { + err.multipart_suggestion_with_applicability( + &format!( + "move the type parameter{} prior to the first associated type binding", + if bad_type_pos.len() > 1 { "s" } else { "" }, + ), + type_suggestions, + Applicability::MachineApplicable, + ); + } + + err.emit(); } /// Parses an optional `where` clause and places it in `generics`. diff --git a/src/test/ui/suggestions/suggest-move-types.rs b/src/test/ui/suggestions/suggest-move-types.rs index 8f35e4ecbcace..fd10ba4350c4a 100644 --- a/src/test/ui/suggestions/suggest-move-types.rs +++ b/src/test/ui/suggestions/suggest-move-types.rs @@ -1,3 +1,5 @@ +// ignore-tidy-linelength + #![allow(warnings)] // This test verifies that the suggestion to move types before associated type bindings @@ -7,17 +9,34 @@ trait One { type A; } +trait OneWithLifetime<'a, T> { + type A; +} + trait Three { type A; type B; type C; } +trait ThreeWithLifetime<'a, 'b, 'c, T, U, V> { + type A; + type B; + type C; +} + struct A> { //~ ERROR type parameters must be declared m: M, t: T, } + +struct Al<'a, T, M: OneWithLifetime> { +//~^ ERROR generic arguments must declare lifetimes, types and associated type bindings in that order + m: M, + t: &'a T, +} + struct B> { //~ ERROR type parameters must be declared m: M, t: T, @@ -25,6 +44,14 @@ struct B> { //~ ERROR type paramete v: V, } +struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { +//~^ ERROR generic arguments must declare lifetimes, types and associated type bindings in that order + m: M, + t: &'a T, + u: &'b U, + v: &'c V, +} + struct C> { //~ ERROR type parameters must be declared m: M, t: T, @@ -32,6 +59,14 @@ struct C> { //~ ERROR type paramete v: V, } +struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { +//~^ ERROR generic arguments must declare lifetimes, types and associated type bindings in that order + m: M, + t: &'a T, + u: &'b U, + v: &'c V, +} + struct D> { //~ ERROR type parameters must be declared m: M, t: T, @@ -39,4 +74,12 @@ struct D> { //~ ERROR type paramete v: V, } +struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { +//~^ ERROR generic arguments must declare lifetimes, types and associated type bindings in that order + m: M, + t: &'a T, + u: &'b U, + v: &'c V, +} + fn main() {} diff --git a/src/test/ui/suggestions/suggest-move-types.stderr b/src/test/ui/suggestions/suggest-move-types.stderr index c74f79a00c78c..3643d9a912455 100644 --- a/src/test/ui/suggestions/suggest-move-types.stderr +++ b/src/test/ui/suggestions/suggest-move-types.stderr @@ -1,5 +1,5 @@ error: type parameters must be declared prior to associated type bindings - --> $DIR/suggest-move-types.rs:16:26 + --> $DIR/suggest-move-types.rs:28:26 | LL | struct A> { //~ ERROR type parameters must be declared | ^ must be declared prior to associated type bindings @@ -8,8 +8,20 @@ help: move the type parameter prior to the first associated type binding LL | struct A> { //~ ERROR type parameters must be declared | ^^ -- +error: generic arguments must declare lifetimes, types and associated type bindings in that order + --> $DIR/suggest-move-types.rs:34:46 + | +LL | struct Al<'a, T, M: OneWithLifetime> { + | ^ ^^ must be declared prior to type parameters + | | + | must be declared prior to associated type bindings +help: move the parameters + | +LL | struct Al<'a, T, M: OneWithLifetime<'a, T, A=()>> { + | ^^^ ^^ -- + error: type parameters must be declared prior to associated type bindings - --> $DIR/suggest-move-types.rs:21:46 + --> $DIR/suggest-move-types.rs:40:46 | LL | struct B> { //~ ERROR type parameters must be declared | ^ ^ ^ must be declared prior to associated type bindings @@ -21,8 +33,24 @@ help: move the type parameters prior to the first associated type binding LL | struct B> { //~ ERROR type parameters must be declared | ^^ ^^ ^^ -- +error: generic arguments must declare lifetimes, types and associated type bindings in that order + --> $DIR/suggest-move-types.rs:47:80 + | +LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { + | ^ ^ ^ ^^ ^^ ^^ must be declared prior to type parameters + | | | | | | + | | | | | must be declared prior to type parameters + | | | | must be declared prior to type parameters + | | | must be declared prior to associated type bindings + | | must be declared prior to associated type bindings + | must be declared prior to associated type bindings +help: move the parameters + | +LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<'a, 'b, 'c, T, U, V, A=(), B=(), C=()>> { + | ^^^ ^^^ ^^^ ^^ ^^ ^^ -- + error: type parameters must be declared prior to associated type bindings - --> $DIR/suggest-move-types.rs:28:49 + --> $DIR/suggest-move-types.rs:55:49 | LL | struct C> { //~ ERROR type parameters must be declared | ^ ^ must be declared prior to associated type bindings @@ -33,8 +61,23 @@ help: move the type parameters prior to the first associated type binding LL | struct C> { //~ ERROR type parameters must be declared | ^^ ^^ -- +error: generic arguments must declare lifetimes, types and associated type bindings in that order + --> $DIR/suggest-move-types.rs:62:56 + | +LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { + | ^^ ^ ^^ ^ ^^ must be declared prior to type parameters + | | | | | + | | | | must be declared prior to associated type bindings + | | | must be declared prior to type parameters + | | must be declared prior to associated type bindings + | must be declared prior to type parameters +help: move the parameters + | +LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<'a, 'b, 'c, T, U, V, A=(), B=(), C=()>> { + | ^^^ ^^^ ^^^ -- ^^ ^^ -- + error: type parameters must be declared prior to associated type bindings - --> $DIR/suggest-move-types.rs:35:43 + --> $DIR/suggest-move-types.rs:70:43 | LL | struct D> { //~ ERROR type parameters must be declared | ^ ^ must be declared prior to associated type bindings @@ -45,5 +88,20 @@ help: move the type parameters prior to the first associated type binding LL | struct D> { //~ ERROR type parameters must be declared | ^^ ^^ -- -- -error: aborting due to 4 previous errors +error: generic arguments must declare lifetimes, types and associated type bindings in that order + --> $DIR/suggest-move-types.rs:77:56 + | +LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { + | ^^ ^ ^^ ^ ^^ must be declared prior to type parameters + | | | | | + | | | | must be declared prior to associated type bindings + | | | must be declared prior to type parameters + | | must be declared prior to associated type bindings + | must be declared prior to type parameters +help: move the parameters + | +LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<'a, 'b, 'c, T, U, V, A=(), B=(), C=()>> { + | ^^^ ^^^ ^^^ -- ^^ ^^ -- -- + +error: aborting due to 8 previous errors