Skip to content

Commit ab0c2e1

Browse files
committed
Auto merge of #94495 - estebank:missing-closing-gt, r=jackh726
Provide suggestion for missing `>` in a type parameter list When encountering an inproperly terminated type parameter list, provide a suggestion to close it after the last non-constraint type parameter that was successfully parsed. Fix #94058.
2 parents d7aca22 + 157c67b commit ab0c2e1

20 files changed

+208
-14
lines changed

compiler/rustc_parse/src/parser/path.rs

+34-1
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,23 @@ impl<'a> Parser<'a> {
272272
lo,
273273
ty_generics,
274274
)?;
275-
self.expect_gt()?;
275+
self.expect_gt().map_err(|mut err| {
276+
// Attempt to find places where a missing `>` might belong.
277+
if let Some(arg) = args
278+
.iter()
279+
.rev()
280+
.skip_while(|arg| matches!(arg, AngleBracketedArg::Constraint(_)))
281+
.next()
282+
{
283+
err.span_suggestion_verbose(
284+
arg.span().shrink_to_hi(),
285+
"you might have meant to end the type parameters here",
286+
">".to_string(),
287+
Applicability::MaybeIncorrect,
288+
);
289+
}
290+
err
291+
})?;
276292
let span = lo.to(self.prev_token.span);
277293
AngleBracketedArgs { args, span }.into()
278294
} else {
@@ -462,6 +478,23 @@ impl<'a> Parser<'a> {
462478
while let Some(arg) = self.parse_angle_arg(ty_generics)? {
463479
args.push(arg);
464480
if !self.eat(&token::Comma) {
481+
if self.token.kind == token::Semi
482+
&& self.look_ahead(1, |t| t.is_ident() || t.is_lifetime())
483+
{
484+
// Add `>` to the list of expected tokens.
485+
self.check(&token::Gt);
486+
// Handle `,` to `;` substitution
487+
let mut err = self.unexpected::<()>().unwrap_err();
488+
self.bump();
489+
err.span_suggestion_verbose(
490+
self.prev_token.span.until(self.token.span),
491+
"use a comma to separate type parameters",
492+
", ".to_string(),
493+
Applicability::MachineApplicable,
494+
);
495+
err.emit();
496+
continue;
497+
}
465498
if !self.token.kind.should_end_const_arg() {
466499
if self.handle_ambiguous_unbraced_const_arg(&mut args)? {
467500
// We've managed to (partially) recover, so continue trying to parse

src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ LL | fn f2<'a>(arg : Box<dyn X< { 1 } = 32 >>) {}
1313
| - ^ expected one of `,`, `:`, or `>`
1414
| |
1515
| maybe try to close unmatched angle bracket
16+
|
17+
help: you might have meant to end the type parameters here
18+
|
19+
LL | fn f2<'a>(arg : Box<dyn X< { 1 }> = 32 >>) {}
20+
| +
1621

1722
error: aborting due to 2 previous errors
1823

src/test/ui/generic-associated-types/parse/trait-path-segments.stderr

+15
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ LL | fn f1<'a>(arg : Box<dyn X<X::Y = u32>>) {}
55
| - ^ expected one of 8 possible tokens
66
| |
77
| maybe try to close unmatched angle bracket
8+
|
9+
help: you might have meant to end the type parameters here
10+
|
11+
LL | fn f1<'a>(arg : Box<dyn X<X::Y> = u32>>) {}
12+
| +
813

914
error: expected one of `,`, `::`, `:`, or `>`, found `=`
1015
--> $DIR/trait-path-segments.rs:19:35
@@ -13,6 +18,11 @@ LL | impl<T : X<<Self as X>::Y<'a> = &'a u32>> Z for T {}
1318
| - ^ expected one of `,`, `::`, `:`, or `>`
1419
| |
1520
| maybe try to close unmatched angle bracket
21+
|
22+
help: you might have meant to end the type parameters here
23+
|
24+
LL | impl<T : X<<Self as X>::Y<'a>> = &'a u32>> Z for T {}
25+
| +
1626

1727
error: expected one of `!`, `+`, `,`, `::`, `:`, or `>`, found `=`
1828
--> $DIR/trait-path-segments.rs:30:25
@@ -21,6 +31,11 @@ LL | impl<T : X<X::Y<'a> = &'a u32>> Z for T {}
2131
| - ^ expected one of `!`, `+`, `,`, `::`, `:`, or `>`
2232
| |
2333
| maybe try to close unmatched angle bracket
34+
|
35+
help: you might have meant to end the type parameters here
36+
|
37+
LL | impl<T : X<X::Y<'a>> = &'a u32>> Z for T {}
38+
| +
2439

2540
error: aborting due to 3 previous errors
2641

src/test/ui/generic-associated-types/parse/trait-path-types.stderr

+15
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ LL | fn f<'a>(arg : Box<dyn X< [u8; 1] = u32>>) {}
55
| - ^ expected one of `,`, `:`, or `>`
66
| |
77
| maybe try to close unmatched angle bracket
8+
|
9+
help: you might have meant to end the type parameters here
10+
|
11+
LL | fn f<'a>(arg : Box<dyn X< [u8; 1]> = u32>>) {}
12+
| +
813

914
error: expected one of `,`, `:`, or `>`, found `=`
1015
--> $DIR/trait-path-types.rs:13:37
@@ -13,6 +18,11 @@ LL | fn f1<'a>(arg : Box<dyn X<(Y<'a>) = &'a ()>>) {}
1318
| - ^ expected one of `,`, `:`, or `>`
1419
| |
1520
| maybe try to close unmatched angle bracket
21+
|
22+
help: you might have meant to end the type parameters here
23+
|
24+
LL | fn f1<'a>(arg : Box<dyn X<(Y<'a>)> = &'a ()>>) {}
25+
| +
1626

1727
error: expected one of `,`, `:`, or `>`, found `=`
1828
--> $DIR/trait-path-types.rs:18:33
@@ -21,6 +31,11 @@ LL | fn f1<'a>(arg : Box<dyn X< 'a = u32 >>) {}
2131
| -- ^ expected one of `,`, `:`, or `>`
2232
| |
2333
| maybe try to close unmatched angle bracket
34+
|
35+
help: you might have meant to end the type parameters here
36+
|
37+
LL | fn f1<'a>(arg : Box<dyn X< 'a> = u32 >>) {}
38+
| +
2439

2540
error: aborting due to 3 previous errors
2641

src/test/ui/issues/issue-34334.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ LL | let sr: Vec<(u32, _, _) = vec![];
66
| | |
77
| | maybe try to close unmatched angle bracket
88
| while parsing the type for `sr`
9+
|
10+
help: you might have meant to end the type parameters here
11+
|
12+
LL | let sr: Vec<(u32, _, _)> = vec![];
13+
| +
914

1015
error[E0277]: a value of type `Vec<(u32, _, _)>` cannot be built from an iterator over elements of type `()`
1116
--> $DIR/issue-34334.rs:5:87

src/test/ui/parser/issues/issue-20616-2.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ error: expected one of `,`, `:`, `=`, or `>`, found `(`
33
|
44
LL | type Type_2 = Type_1_<'static ()>;
55
| ^ expected one of `,`, `:`, `=`, or `>`
6+
|
7+
help: you might have meant to end the type parameters here
8+
|
9+
LL | type Type_2 = Type_1_<'static> ()>;
10+
| +
611

712
error: aborting due to previous error
813

src/test/ui/parser/issues/issue-20616-3.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ error: expected one of `>`, a const expression, lifetime, or type, found `,`
33
|
44
LL | type Type_3<T> = Box<T,,>;
55
| ^ expected one of `>`, a const expression, lifetime, or type
6+
|
7+
help: you might have meant to end the type parameters here
8+
|
9+
LL | type Type_3<T> = Box<T>,,>;
10+
| +
611

712
error: aborting due to previous error
813

src/test/ui/parser/issues/issue-20616-4.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ error: expected one of `>`, a const expression, lifetime, or type, found `,`
33
|
44
LL | type Type_4<T> = Type_1_<'static,, T>;
55
| ^ expected one of `>`, a const expression, lifetime, or type
6+
|
7+
help: you might have meant to end the type parameters here
8+
|
9+
LL | type Type_4<T> = Type_1_<'static>,, T>;
10+
| +
611

712
error: aborting due to previous error
813

src/test/ui/parser/issues/issue-20616-5.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ error: expected one of `>`, a const expression, lifetime, or type, found `,`
33
|
44
LL | type Type_5<'a> = Type_1_<'a, (),,>;
55
| ^ expected one of `>`, a const expression, lifetime, or type
6+
|
7+
help: you might have meant to end the type parameters here
8+
|
9+
LL | type Type_5<'a> = Type_1_<'a, ()>,,>;
10+
| +
611

712
error: aborting due to previous error
813

src/test/ui/parser/issues/issue-20616-6.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ error: expected one of `>`, a const expression, lifetime, or type, found `,`
33
|
44
LL | type Type_6 = Type_5_<'a,,>;
55
| ^ expected one of `>`, a const expression, lifetime, or type
6+
|
7+
help: you might have meant to end the type parameters here
8+
|
9+
LL | type Type_6 = Type_5_<'a>,,>;
10+
| +
611

712
error: aborting due to previous error
813

src/test/ui/parser/issues/issue-20616-7.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ error: expected one of `>`, a const expression, lifetime, or type, found `,`
33
|
44
LL | type Type_7 = Box<(),,>;
55
| ^ expected one of `>`, a const expression, lifetime, or type
6+
|
7+
help: you might have meant to end the type parameters here
8+
|
9+
LL | type Type_7 = Box<()>,,>;
10+
| +
611

712
error: aborting due to previous error
813

src/test/ui/parser/issues/issue-62660.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, or `>`, found `)
33
|
44
LL | pub fn foo(_: i32, self: Box<Self) {}
55
| ^ expected one of 9 possible tokens
6+
|
7+
help: you might have meant to end the type parameters here
8+
|
9+
LL | pub fn foo(_: i32, self: Box<Self>) {}
10+
| +
611

712
error: aborting due to previous error
813

src/test/ui/parser/issues/issue-84117.stderr

+32-9
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,18 @@ error: expected one of `>`, a const expression, lifetime, or type, found `}`
22
--> $DIR/issue-84117.rs:2:67
33
|
44
LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }
5-
| ------------ ^ expected one of `>`, a const expression, lifetime, or type
6-
| | |
7-
| | help: use `=` if you meant to assign
5+
| ----------- ^ expected one of `>`, a const expression, lifetime, or type
6+
| |
87
| while parsing the type for `inner_local`
8+
|
9+
help: you might have meant to end the type parameters here
10+
|
11+
LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str>, }
12+
| +
13+
help: use `=` if you meant to assign
14+
|
15+
LL | let outer_local:e_outer<&str, { let inner_local =e_inner<&str, }
16+
| ~
917

1018
error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,`
1119
--> $DIR/issue-84117.rs:2:65
@@ -17,21 +25,36 @@ error: expected one of `,`, `:`, `=`, or `>`, found `}`
1725
--> $DIR/issue-84117.rs:8:1
1826
|
1927
LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }
20-
| ------------ help: use `=` if you meant to assign - expected one of `,`, `:`, `=`, or `>`
21-
| |
22-
| while parsing the type for `outer_local`
28+
| ----------- while parsing the type for `outer_local` - expected one of `,`, `:`, `=`, or `>`
2329
...
2430
LL | }
2531
| ^ unexpected token
32+
|
33+
help: you might have meant to end the type parameters here
34+
|
35+
LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }>
36+
| +
37+
help: use `=` if you meant to assign
38+
|
39+
LL | let outer_local =e_outer<&str, { let inner_local:e_inner<&str, }
40+
| ~
2641

2742
error: expected one of `>`, a const expression, lifetime, or type, found `}`
2843
--> $DIR/issue-84117.rs:2:67
2944
|
3045
LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }
31-
| ------------ ^ expected one of `>`, a const expression, lifetime, or type
32-
| | |
33-
| | help: use `=` if you meant to assign
46+
| ----------- ^ expected one of `>`, a const expression, lifetime, or type
47+
| |
3448
| while parsing the type for `inner_local`
49+
|
50+
help: you might have meant to end the type parameters here
51+
|
52+
LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str>, }
53+
| +
54+
help: use `=` if you meant to assign
55+
|
56+
LL | let outer_local:e_outer<&str, { let inner_local =e_inner<&str, }
57+
| ~
3558

3659
error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,`
3760
--> $DIR/issue-84117.rs:2:65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// run-rustfix
2+
#![allow(unused)]
3+
struct Foo<'a, 'b> {
4+
a: &'a &'b i32
5+
}
6+
7+
fn foo<'a, 'b>(_x: &mut Foo<'a, 'b>) {}
8+
//~^ ERROR expected one of `,`, `:`, `=`, or `>`, found `;`
9+
10+
fn main() {}
+3-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
// run-rustfix
2+
#![allow(unused)]
13
struct Foo<'a, 'b> {
24
a: &'a &'b i32
35
}
46

5-
fn foo<'a, 'b>(x: &mut Foo<'a; 'b>) {}
7+
fn foo<'a, 'b>(_x: &mut Foo<'a; 'b>) {}
68
//~^ ERROR expected one of `,`, `:`, `=`, or `>`, found `;`
79

810
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
error: expected one of `,`, `:`, `=`, or `>`, found `;`
2-
--> $DIR/lifetime-semicolon.rs:5:30
2+
--> $DIR/lifetime-semicolon.rs:7:31
33
|
4-
LL | fn foo<'a, 'b>(x: &mut Foo<'a; 'b>) {}
5-
| ^ expected one of `,`, `:`, `=`, or `>`
4+
LL | fn foo<'a, 'b>(_x: &mut Foo<'a; 'b>) {}
5+
| ^ expected one of `,`, `:`, `=`, or `>`
6+
|
7+
help: use a comma to separate type parameters
8+
|
9+
LL | fn foo<'a, 'b>(_x: &mut Foo<'a, 'b>) {}
10+
| ~
611

712
error: aborting due to previous error
813

src/test/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr

+15
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ LL | let v : Vec<(u32,_) = vec![];
66
| | |
77
| | maybe try to close unmatched angle bracket
88
| while parsing the type for `v`
9+
|
10+
help: you might have meant to end the type parameters here
11+
|
12+
LL | let v : Vec<(u32,_)> = vec![];
13+
| +
914

1015
error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `{`
1116
--> $DIR/missing-closing-angle-bracket-eq-constraint.rs:13:32
@@ -14,6 +19,11 @@ LL | let foo : Foo::<T1, T2 = Foo {_a : arg1, _b : arg2};
1419
| --- ^ expected one of 7 possible tokens
1520
| |
1621
| while parsing the type for `foo`
22+
|
23+
help: you might have meant to end the type parameters here
24+
|
25+
LL | let foo : Foo::<T1>, T2 = Foo {_a : arg1, _b : arg2};
26+
| +
1727

1828
error: expected one of `,`, `:`, or `>`, found `=`
1929
--> $DIR/missing-closing-angle-bracket-eq-constraint.rs:18:18
@@ -23,6 +33,11 @@ LL | let v : Vec<'a = vec![];
2333
| | |
2434
| | maybe try to close unmatched angle bracket
2535
| while parsing the type for `v`
36+
|
37+
help: you might have meant to end the type parameters here
38+
|
39+
LL | let v : Vec<'a> = vec![];
40+
| +
2641

2742
error[E0282]: type annotations needed for `Vec<T>`
2843
--> $DIR/missing-closing-angle-bracket-eq-constraint.rs:7:25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// run-rustifx
2+
#![allow(unused)]
3+
use std::sync::{Arc, Mutex};
4+
5+
pub struct Foo {
6+
a: Mutex<usize>,
7+
b: Arc<Mutex<usize>, //~ HELP you might have meant to end the type parameters here
8+
c: Arc<Mutex<usize>>,
9+
} //~ ERROR expected one of
10+
11+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: expected one of `>`, a const expression, lifetime, or type, found `}`
2+
--> $DIR/missing-closing-angle-bracket-struct-field-ty.rs:9:1
3+
|
4+
LL | c: Arc<Mutex<usize>>,
5+
| - expected one of `>`, a const expression, lifetime, or type
6+
LL | }
7+
| ^ unexpected token
8+
|
9+
help: you might have meant to end the type parameters here
10+
|
11+
LL | b: Arc<Mutex<usize>>,
12+
| +
13+
14+
error: aborting due to previous error
15+

0 commit comments

Comments
 (0)