From 45dfe43887fee6c2ce4cbc3e46b31626330be094 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Mon, 26 Nov 2018 08:32:47 -0800 Subject: Emit one diagnostic for multiple misplaced lifetimes --- src/libsyntax/parse/parser.rs | 31 +++++++++++++--------- src/test/ui/suggestions/suggest-move-lifetimes.rs | 6 +++++ .../ui/suggestions/suggest-move-lifetimes.stderr | 16 ++++++++--- 3 files changed, 38 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 1fdf86d4867..ab5afaf3d99 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5182,6 +5182,8 @@ impl<'a> Parser<'a> { let mut params = Vec::new(); let mut seen_ty_param: Option = None; let mut last_comma_span = None; + let mut bad_lifetime_pos = vec![]; + let mut suggestions = vec![]; loop { let attrs = self.parse_outer_attributes()?; if self.check_lifetime() { @@ -5207,20 +5209,12 @@ impl<'a> Parser<'a> { } else { last_comma_span.unwrap_or(param_span).to(param_span) }; - let mut err = self.struct_span_err( - self.prev_span, - "lifetime parameters must be declared prior to type parameters", - ); + bad_lifetime_pos.push(param_span); + if let Ok(snippet) = self.sess.source_map().span_to_snippet(param_span) { - err.multipart_suggestion( - "move the lifetime parameter prior to the first type parameter", - vec![ - (remove_sp, String::new()), - (sp.shrink_to_lo(), format!("{}, ", snippet)), - ], - ); + suggestions.push((remove_sp, String::new())); + suggestions.push((sp.shrink_to_lo(), format!("{}, ", snippet))); } - err.emit(); if ate_comma { last_comma_span = Some(self.prev_span); continue @@ -5247,6 +5241,19 @@ impl<'a> Parser<'a> { } last_comma_span = Some(self.prev_span); } + if !bad_lifetime_pos.is_empty() { + let mut err = self.struct_span_err( + bad_lifetime_pos, + "lifetime parameters must be declared prior to type parameters", + ); + if !suggestions.is_empty() { + err.multipart_suggestion( + "move the lifetime parameter prior to the first type parameter", + suggestions, + ); + } + err.emit(); + } lifetimes.extend(params); // ensure the correct order of lifetimes and type params Ok(lifetimes) } diff --git a/src/test/ui/suggestions/suggest-move-lifetimes.rs b/src/test/ui/suggestions/suggest-move-lifetimes.rs index be6d29d9337..5051a406078 100644 --- a/src/test/ui/suggestions/suggest-move-lifetimes.rs +++ b/src/test/ui/suggestions/suggest-move-lifetimes.rs @@ -12,4 +12,10 @@ struct C { u: U, } +struct D { + t: &'a T, + u: &'b U, + v: &'c V, +} + fn main() {} diff --git a/src/test/ui/suggestions/suggest-move-lifetimes.stderr b/src/test/ui/suggestions/suggest-move-lifetimes.stderr index fa1cfe66ab5..f3d6469b512 100644 --- a/src/test/ui/suggestions/suggest-move-lifetimes.stderr +++ b/src/test/ui/suggestions/suggest-move-lifetimes.stderr @@ -9,10 +9,10 @@ LL | struct A<'a, T> { | ^^^ -- error: lifetime parameters must be declared prior to type parameters - --> $DIR/suggest-move-lifetimes.rs:5:15 + --> $DIR/suggest-move-lifetimes.rs:5:13 | LL | struct B { - | ^ + | ^^ help: move the lifetime parameter prior to the first type parameter | LL | struct B<'a, T, U> { @@ -28,5 +28,15 @@ help: move the lifetime parameter prior to the first type parameter LL | struct C<'a, T, U> { | ^^^ -- -error: aborting due to 3 previous errors +error: lifetime parameters must be declared prior to type parameters + --> $DIR/suggest-move-lifetimes.rs:15:16 + | +LL | struct D { + | ^^ ^^ ^^ +help: move the lifetime parameter prior to the first type parameter + | +LL | struct D<'a, 'b, 'c, T, U, V> { + | ^^^ ^^^ ^^^ --- + +error: aborting due to 4 previous errors -- cgit 1.4.1-3-g733a5