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:
commit
ab0c2e18dc
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
10
src/test/ui/parser/lifetime-semicolon.fixed
Normal file
10
src/test/ui/parser/lifetime-semicolon.fixed
Normal 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() {}
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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() {}
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user