Skip to content

Commit 45dfe43

Browse files
committed
Emit one diagnostic for multiple misplaced lifetimes
1 parent 234d043 commit 45dfe43

File tree

3 files changed

+38
-15
lines changed

3 files changed

+38
-15
lines changed

src/libsyntax/parse/parser.rs

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5182,6 +5182,8 @@ impl<'a> Parser<'a> {
51825182
let mut params = Vec::new();
51835183
let mut seen_ty_param: Option<Span> = None;
51845184
let mut last_comma_span = None;
5185+
let mut bad_lifetime_pos = vec![];
5186+
let mut suggestions = vec![];
51855187
loop {
51865188
let attrs = self.parse_outer_attributes()?;
51875189
if self.check_lifetime() {
@@ -5207,20 +5209,12 @@ impl<'a> Parser<'a> {
52075209
} else {
52085210
last_comma_span.unwrap_or(param_span).to(param_span)
52095211
};
5210-
let mut err = self.struct_span_err(
5211-
self.prev_span,
5212-
"lifetime parameters must be declared prior to type parameters",
5213-
);
5212+
bad_lifetime_pos.push(param_span);
5213+
52145214
if let Ok(snippet) = self.sess.source_map().span_to_snippet(param_span) {
5215-
err.multipart_suggestion(
5216-
"move the lifetime parameter prior to the first type parameter",
5217-
vec![
5218-
(remove_sp, String::new()),
5219-
(sp.shrink_to_lo(), format!("{}, ", snippet)),
5220-
],
5221-
);
5215+
suggestions.push((remove_sp, String::new()));
5216+
suggestions.push((sp.shrink_to_lo(), format!("{}, ", snippet)));
52225217
}
5223-
err.emit();
52245218
if ate_comma {
52255219
last_comma_span = Some(self.prev_span);
52265220
continue
@@ -5247,6 +5241,19 @@ impl<'a> Parser<'a> {
52475241
}
52485242
last_comma_span = Some(self.prev_span);
52495243
}
5244+
if !bad_lifetime_pos.is_empty() {
5245+
let mut err = self.struct_span_err(
5246+
bad_lifetime_pos,
5247+
"lifetime parameters must be declared prior to type parameters",
5248+
);
5249+
if !suggestions.is_empty() {
5250+
err.multipart_suggestion(
5251+
"move the lifetime parameter prior to the first type parameter",
5252+
suggestions,
5253+
);
5254+
}
5255+
err.emit();
5256+
}
52505257
lifetimes.extend(params); // ensure the correct order of lifetimes and type params
52515258
Ok(lifetimes)
52525259
}

src/test/ui/suggestions/suggest-move-lifetimes.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,10 @@ struct C<T, U, 'a> {
1212
u: U,
1313
}
1414

15+
struct D<T, U, 'a, 'b, V, 'c> {
16+
t: &'a T,
17+
u: &'b U,
18+
v: &'c V,
19+
}
20+
1521
fn main() {}

src/test/ui/suggestions/suggest-move-lifetimes.stderr

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ LL | struct A<'a, T> {
99
| ^^^ --
1010

1111
error: lifetime parameters must be declared prior to type parameters
12-
--> $DIR/suggest-move-lifetimes.rs:5:15
12+
--> $DIR/suggest-move-lifetimes.rs:5:13
1313
|
1414
LL | struct B<T, 'a, U> {
15-
| ^
15+
| ^^
1616
help: move the lifetime parameter prior to the first type parameter
1717
|
1818
LL | struct B<'a, T, U> {
@@ -28,5 +28,15 @@ help: move the lifetime parameter prior to the first type parameter
2828
LL | struct C<'a, T, U> {
2929
| ^^^ --
3030

31-
error: aborting due to 3 previous errors
31+
error: lifetime parameters must be declared prior to type parameters
32+
--> $DIR/suggest-move-lifetimes.rs:15:16
33+
|
34+
LL | struct D<T, U, 'a, 'b, V, 'c> {
35+
| ^^ ^^ ^^
36+
help: move the lifetime parameter prior to the first type parameter
37+
|
38+
LL | struct D<'a, 'b, 'c, T, U, V> {
39+
| ^^^ ^^^ ^^^ ---
40+
41+
error: aborting due to 4 previous errors
3242

0 commit comments

Comments
 (0)