Skip to content

Provide suggestion for missing > in a type parameter list #94495

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion compiler/rustc_parse/src/parser/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,23 @@ impl<'a> Parser<'a> {
lo,
ty_generics,
)?;
self.expect_gt()?;
self.expect_gt().map_err(|mut err| {
// Attempt to find places where a missing `>` might belong.
if let Some(arg) = args
.iter()
.rev()
.skip_while(|arg| matches!(arg, AngleBracketedArg::Constraint(_)))
.next()
{
err.span_suggestion_verbose(
arg.span().shrink_to_hi(),
"you might have meant to end the type parameters here",
">".to_string(),
Applicability::MaybeIncorrect,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if MaybeIncorrect is the right choice here. A lot of the suggestions in tests don't result in valid code (namely when we later have a closing >. But 🤷‍♀️

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's the best of the available Applicabilitys we have available today :)

);
}
err
})?;
let span = lo.to(self.prev_token.span);
AngleBracketedArgs { args, span }.into()
} else {
Expand Down Expand Up @@ -462,6 +478,23 @@ impl<'a> Parser<'a> {
while let Some(arg) = self.parse_angle_arg(ty_generics)? {
args.push(arg);
if !self.eat(&token::Comma) {
if self.token.kind == token::Semi
&& self.look_ahead(1, |t| t.is_ident() || t.is_lifetime())
{
// Add `>` to the list of expected tokens.
self.check(&token::Gt);
// Handle `,` to `;` substitution
let mut err = self.unexpected::<()>().unwrap_err();
self.bump();
err.span_suggestion_verbose(
self.prev_token.span.until(self.token.span),
"use a comma to separate type parameters",
", ".to_string(),
Applicability::MachineApplicable,
);
err.emit();
continue;
}
if !self.token.kind.should_end_const_arg() {
if self.handle_ambiguous_unbraced_const_arg(&mut args)? {
// We've managed to (partially) recover, so continue trying to parse
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ LL | fn f2<'a>(arg : Box<dyn X< { 1 } = 32 >>) {}
| - ^ expected one of `,`, `:`, or `>`
| |
| maybe try to close unmatched angle bracket
|
help: you might have meant to end the type parameters here
|
LL | fn f2<'a>(arg : Box<dyn X< { 1 }> = 32 >>) {}
| +

error: aborting due to 2 previous errors

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

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

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

error: aborting due to 3 previous errors

15 changes: 15 additions & 0 deletions src/test/ui/generic-associated-types/parse/trait-path-types.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ LL | fn f<'a>(arg : Box<dyn X< [u8; 1] = u32>>) {}
| - ^ expected one of `,`, `:`, or `>`
| |
| maybe try to close unmatched angle bracket
|
help: you might have meant to end the type parameters here
|
LL | fn f<'a>(arg : Box<dyn X< [u8; 1]> = u32>>) {}
| +

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

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

error: aborting due to 3 previous errors

5 changes: 5 additions & 0 deletions src/test/ui/issues/issue-34334.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ LL | let sr: Vec<(u32, _, _) = vec![];
| | |
| | maybe try to close unmatched angle bracket
| while parsing the type for `sr`
|
help: you might have meant to end the type parameters here
|
LL | let sr: Vec<(u32, _, _)> = vec![];
| +

error[E0277]: a value of type `Vec<(u32, _, _)>` cannot be built from an iterator over elements of type `()`
--> $DIR/issue-34334.rs:5:87
Expand Down
5 changes: 5 additions & 0 deletions src/test/ui/parser/issues/issue-20616-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ error: expected one of `,`, `:`, `=`, or `>`, found `(`
|
LL | type Type_2 = Type_1_<'static ()>;
| ^ expected one of `,`, `:`, `=`, or `>`
|
help: you might have meant to end the type parameters here
|
LL | type Type_2 = Type_1_<'static> ()>;
| +

error: aborting due to previous error

5 changes: 5 additions & 0 deletions src/test/ui/parser/issues/issue-20616-3.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ error: expected one of `>`, a const expression, lifetime, or type, found `,`
|
LL | type Type_3<T> = Box<T,,>;
| ^ expected one of `>`, a const expression, lifetime, or type
|
help: you might have meant to end the type parameters here
|
LL | type Type_3<T> = Box<T>,,>;
| +

error: aborting due to previous error

5 changes: 5 additions & 0 deletions src/test/ui/parser/issues/issue-20616-4.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ error: expected one of `>`, a const expression, lifetime, or type, found `,`
|
LL | type Type_4<T> = Type_1_<'static,, T>;
| ^ expected one of `>`, a const expression, lifetime, or type
|
help: you might have meant to end the type parameters here
|
LL | type Type_4<T> = Type_1_<'static>,, T>;
| +

error: aborting due to previous error

5 changes: 5 additions & 0 deletions src/test/ui/parser/issues/issue-20616-5.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ error: expected one of `>`, a const expression, lifetime, or type, found `,`
|
LL | type Type_5<'a> = Type_1_<'a, (),,>;
| ^ expected one of `>`, a const expression, lifetime, or type
|
help: you might have meant to end the type parameters here
|
LL | type Type_5<'a> = Type_1_<'a, ()>,,>;
| +

error: aborting due to previous error

5 changes: 5 additions & 0 deletions src/test/ui/parser/issues/issue-20616-6.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ error: expected one of `>`, a const expression, lifetime, or type, found `,`
|
LL | type Type_6 = Type_5_<'a,,>;
| ^ expected one of `>`, a const expression, lifetime, or type
|
help: you might have meant to end the type parameters here
|
LL | type Type_6 = Type_5_<'a>,,>;
| +

error: aborting due to previous error

5 changes: 5 additions & 0 deletions src/test/ui/parser/issues/issue-20616-7.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ error: expected one of `>`, a const expression, lifetime, or type, found `,`
|
LL | type Type_7 = Box<(),,>;
| ^ expected one of `>`, a const expression, lifetime, or type
|
help: you might have meant to end the type parameters here
|
LL | type Type_7 = Box<()>,,>;
| +

error: aborting due to previous error

5 changes: 5 additions & 0 deletions src/test/ui/parser/issues/issue-62660.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, or `>`, found `)
|
LL | pub fn foo(_: i32, self: Box<Self) {}
| ^ expected one of 9 possible tokens
|
help: you might have meant to end the type parameters here
|
LL | pub fn foo(_: i32, self: Box<Self>) {}
| +

error: aborting due to previous error

41 changes: 32 additions & 9 deletions src/test/ui/parser/issues/issue-84117.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@ error: expected one of `>`, a const expression, lifetime, or type, found `}`
--> $DIR/issue-84117.rs:2:67
|
LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }
| ------------ ^ expected one of `>`, a const expression, lifetime, or type
| | |
| | help: use `=` if you meant to assign
| ----------- ^ expected one of `>`, a const expression, lifetime, or type
| |
| while parsing the type for `inner_local`
|
help: you might have meant to end the type parameters here
|
LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str>, }
| +
help: use `=` if you meant to assign
|
LL | let outer_local:e_outer<&str, { let inner_local =e_inner<&str, }
| ~

error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,`
--> $DIR/issue-84117.rs:2:65
Expand All @@ -17,21 +25,36 @@ error: expected one of `,`, `:`, `=`, or `>`, found `}`
--> $DIR/issue-84117.rs:8:1
|
LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }
| ------------ help: use `=` if you meant to assign - expected one of `,`, `:`, `=`, or `>`
| |
| while parsing the type for `outer_local`
| ----------- while parsing the type for `outer_local` - expected one of `,`, `:`, `=`, or `>`
...
LL | }
| ^ unexpected token
|
help: you might have meant to end the type parameters here
|
LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }>
| +
help: use `=` if you meant to assign
|
LL | let outer_local =e_outer<&str, { let inner_local:e_inner<&str, }
| ~

error: expected one of `>`, a const expression, lifetime, or type, found `}`
--> $DIR/issue-84117.rs:2:67
|
LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }
| ------------ ^ expected one of `>`, a const expression, lifetime, or type
| | |
| | help: use `=` if you meant to assign
| ----------- ^ expected one of `>`, a const expression, lifetime, or type
| |
| while parsing the type for `inner_local`
|
help: you might have meant to end the type parameters here
|
LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str>, }
| +
help: use `=` if you meant to assign
|
LL | let outer_local:e_outer<&str, { let inner_local =e_inner<&str, }
| ~

error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,`
--> $DIR/issue-84117.rs:2:65
Expand Down
10 changes: 10 additions & 0 deletions src/test/ui/parser/lifetime-semicolon.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// run-rustfix
#![allow(unused)]
struct Foo<'a, 'b> {
a: &'a &'b i32
}

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

fn main() {}
4 changes: 3 additions & 1 deletion src/test/ui/parser/lifetime-semicolon.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
// run-rustfix
#![allow(unused)]
struct Foo<'a, 'b> {
a: &'a &'b i32
}

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

fn main() {}
11 changes: 8 additions & 3 deletions src/test/ui/parser/lifetime-semicolon.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
error: expected one of `,`, `:`, `=`, or `>`, found `;`
--> $DIR/lifetime-semicolon.rs:5:30
--> $DIR/lifetime-semicolon.rs:7:31
|
LL | fn foo<'a, 'b>(x: &mut Foo<'a; 'b>) {}
| ^ expected one of `,`, `:`, `=`, or `>`
LL | fn foo<'a, 'b>(_x: &mut Foo<'a; 'b>) {}
| ^ expected one of `,`, `:`, `=`, or `>`
|
help: use a comma to separate type parameters
|
LL | fn foo<'a, 'b>(_x: &mut Foo<'a, 'b>) {}
| ~

error: aborting due to previous error

Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ LL | let v : Vec<(u32,_) = vec![];
| | |
| | maybe try to close unmatched angle bracket
| while parsing the type for `v`
|
help: you might have meant to end the type parameters here
|
LL | let v : Vec<(u32,_)> = vec![];
| +

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

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

error[E0282]: type annotations needed for `Vec<T>`
--> $DIR/missing-closing-angle-bracket-eq-constraint.rs:7:25
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// run-rustifx
#![allow(unused)]
use std::sync::{Arc, Mutex};

pub struct Foo {
a: Mutex<usize>,
b: Arc<Mutex<usize>, //~ HELP you might have meant to end the type parameters here
c: Arc<Mutex<usize>>,
} //~ ERROR expected one of

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error: expected one of `>`, a const expression, lifetime, or type, found `}`
--> $DIR/missing-closing-angle-bracket-struct-field-ty.rs:9:1
|
LL | c: Arc<Mutex<usize>>,
| - expected one of `>`, a const expression, lifetime, or type
LL | }
| ^ unexpected token
|
help: you might have meant to end the type parameters here
|
LL | b: Arc<Mutex<usize>>,
| +

error: aborting due to previous error

Loading