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.
This commit is contained in:
bors 2022-03-27 18:55:58 +00:00
commit ab0c2e18dc
20 changed files with 208 additions and 14 deletions

View File

@ -272,7 +272,23 @@ pub(super) fn parse_path_segment(
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,
);
}
err
})?;
let span = lo.to(self.prev_token.span);
AngleBracketedArgs { args, span }.into()
} else {
@ -462,6 +478,23 @@ pub(super) fn parse_angle_args(
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

View File

@ -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

View File

@ -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
@ -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
@ -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

View File

@ -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
@ -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
@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
@ -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

View File

@ -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() {}

View File

@ -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() {}

View File

@ -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

View File

@ -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
@ -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
@ -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

View File

@ -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() {}

View File

@ -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

View File

@ -3,6 +3,11 @@ error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, or `>`, found `/
|
LL | type closure = Box<lt/fn()>;
| ^ expected one of 9 possible tokens
|
help: you might have meant to end the type parameters here
|
LL | type closure = Box<lt>/fn()>;
| +
error: aborting due to previous error