From 6874bd27f527b6c5f40e8fd866d91813da2df35a Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Tue, 1 Mar 2022 19:40:48 +0000 Subject: [PATCH] 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. --- compiler/rustc_parse/src/parser/path.rs | 18 +++++++- .../parse/trait-path-expressions.stderr | 5 +++ .../parse/trait-path-segments.stderr | 15 +++++++ .../parse/trait-path-types.stderr | 15 +++++++ src/test/ui/issues/issue-34334.stderr | 5 +++ .../ui/parser/issues/issue-20616-2.stderr | 5 +++ .../ui/parser/issues/issue-20616-3.stderr | 5 +++ .../ui/parser/issues/issue-20616-4.stderr | 5 +++ .../ui/parser/issues/issue-20616-5.stderr | 5 +++ .../ui/parser/issues/issue-20616-6.stderr | 5 +++ .../ui/parser/issues/issue-20616-7.stderr | 5 +++ src/test/ui/parser/issues/issue-62660.stderr | 5 +++ src/test/ui/parser/issues/issue-84117.stderr | 41 +++++++++++++++---- src/test/ui/parser/lifetime-semicolon.stderr | 5 +++ ...closing-angle-bracket-eq-constraint.stderr | 15 +++++++ ...g-closing-angle-bracket-struct-field-ty.rs | 11 +++++ ...osing-angle-bracket-struct-field-ty.stderr | 15 +++++++ .../removed-syntax-closure-lifetime.stderr | 5 +++ 18 files changed, 175 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.rs create mode 100644 src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 07ce879de8f..596099bf2de 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -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 { diff --git a/src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr b/src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr index b1fea6d33a7..272afc10b17 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr +++ b/src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr @@ -13,6 +13,11 @@ LL | fn f2<'a>(arg : Box>) {} | - ^ 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 = 32 >>) {} + | + error: aborting due to 2 previous errors diff --git a/src/test/ui/generic-associated-types/parse/trait-path-segments.stderr b/src/test/ui/generic-associated-types/parse/trait-path-segments.stderr index bfb109fbfa4..7394393c05e 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-segments.stderr +++ b/src/test/ui/generic-associated-types/parse/trait-path-segments.stderr @@ -5,6 +5,11 @@ LL | fn f1<'a>(arg : Box>) {} | - ^ 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 = u32>>) {} + | + error: expected one of `,`, `::`, `:`, or `>`, found `=` --> $DIR/trait-path-segments.rs:19:35 @@ -13,6 +18,11 @@ LL | impl::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::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 = &'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> = &'a u32>> Z for T {} + | + error: aborting due to 3 previous errors diff --git a/src/test/ui/generic-associated-types/parse/trait-path-types.stderr b/src/test/ui/generic-associated-types/parse/trait-path-types.stderr index c0fa41b9e0e..fe9ed579e34 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-types.stderr +++ b/src/test/ui/generic-associated-types/parse/trait-path-types.stderr @@ -5,6 +5,11 @@ LL | fn f<'a>(arg : Box>) {} | - ^ 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 = u32>>) {} + | + error: expected one of `,`, `:`, or `>`, found `=` --> $DIR/trait-path-types.rs:13:37 @@ -13,6 +18,11 @@ LL | fn f1<'a>(arg : Box) = &'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)> = &'a ()>>) {} + | + error: expected one of `,`, `:`, or `>`, found `=` --> $DIR/trait-path-types.rs:18:33 @@ -21,6 +31,11 @@ LL | fn f1<'a>(arg : Box>) {} | -- ^ 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 = u32 >>) {} + | + error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr index 49d6709a860..cd697445faf 100644 --- a/src/test/ui/issues/issue-34334.stderr +++ b/src/test/ui/issues/issue-34334.stderr @@ -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 diff --git a/src/test/ui/parser/issues/issue-20616-2.stderr b/src/test/ui/parser/issues/issue-20616-2.stderr index 01e3d3dd7cc..13e6aa7d605 100644 --- a/src/test/ui/parser/issues/issue-20616-2.stderr +++ b/src/test/ui/parser/issues/issue-20616-2.stderr @@ -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 diff --git a/src/test/ui/parser/issues/issue-20616-3.stderr b/src/test/ui/parser/issues/issue-20616-3.stderr index b535c7a3267..dbff116e505 100644 --- a/src/test/ui/parser/issues/issue-20616-3.stderr +++ b/src/test/ui/parser/issues/issue-20616-3.stderr @@ -3,6 +3,11 @@ error: expected one of `>`, a const expression, lifetime, or type, found `,` | LL | type Type_3 = Box; | ^ expected one of `>`, a const expression, lifetime, or type + | +help: you might have meant to end the type parameters here + | +LL | type Type_3 = Box,,>; + | + error: aborting due to previous error diff --git a/src/test/ui/parser/issues/issue-20616-4.stderr b/src/test/ui/parser/issues/issue-20616-4.stderr index 2b3b75f3119..48a06e00b24 100644 --- a/src/test/ui/parser/issues/issue-20616-4.stderr +++ b/src/test/ui/parser/issues/issue-20616-4.stderr @@ -3,6 +3,11 @@ error: expected one of `>`, a const expression, lifetime, or type, found `,` | LL | type Type_4 = 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 = Type_1_<'static>,, T>; + | + error: aborting due to previous error diff --git a/src/test/ui/parser/issues/issue-20616-5.stderr b/src/test/ui/parser/issues/issue-20616-5.stderr index 1ec1dbde695..84bee2ad184 100644 --- a/src/test/ui/parser/issues/issue-20616-5.stderr +++ b/src/test/ui/parser/issues/issue-20616-5.stderr @@ -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 diff --git a/src/test/ui/parser/issues/issue-20616-6.stderr b/src/test/ui/parser/issues/issue-20616-6.stderr index 7401abdd091..67de41b9747 100644 --- a/src/test/ui/parser/issues/issue-20616-6.stderr +++ b/src/test/ui/parser/issues/issue-20616-6.stderr @@ -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 diff --git a/src/test/ui/parser/issues/issue-20616-7.stderr b/src/test/ui/parser/issues/issue-20616-7.stderr index e2c3efe8447..3b8e07fa0d0 100644 --- a/src/test/ui/parser/issues/issue-20616-7.stderr +++ b/src/test/ui/parser/issues/issue-20616-7.stderr @@ -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 diff --git a/src/test/ui/parser/issues/issue-62660.stderr b/src/test/ui/parser/issues/issue-62660.stderr index a50ada9056b..be0b9a524df 100644 --- a/src/test/ui/parser/issues/issue-62660.stderr +++ b/src/test/ui/parser/issues/issue-62660.stderr @@ -3,6 +3,11 @@ error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, or `>`, found `) | LL | pub fn foo(_: i32, self: Box) {} + | + error: aborting due to previous error diff --git a/src/test/ui/parser/issues/issue-84117.stderr b/src/test/ui/parser/issues/issue-84117.stderr index 5b9cc53baa5..a2407affeef 100644 --- a/src/test/ui/parser/issues/issue-84117.stderr +++ b/src/test/ui/parser/issues/issue-84117.stderr @@ -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 diff --git a/src/test/ui/parser/lifetime-semicolon.stderr b/src/test/ui/parser/lifetime-semicolon.stderr index 3b67705aae9..948f9655e1e 100644 --- a/src/test/ui/parser/lifetime-semicolon.stderr +++ b/src/test/ui/parser/lifetime-semicolon.stderr @@ -3,6 +3,11 @@ error: expected one of `,`, `:`, `=`, or `>`, found `;` | LL | fn foo<'a, 'b>(x: &mut Foo<'a; 'b>) {} | ^ expected one of `,`, `:`, `=`, or `>` + | +help: you might have meant to end the type parameters here + | +LL | fn foo<'a, 'b>(x: &mut Foo<'a>; 'b>) {} + | + error: aborting due to previous error diff --git a/src/test/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr b/src/test/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr index 93403372bcb..427234e97cf 100644 --- a/src/test/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr +++ b/src/test/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr @@ -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::, 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` --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:7:25 diff --git a/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.rs b/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.rs new file mode 100644 index 00000000000..d69a56c51d3 --- /dev/null +++ b/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.rs @@ -0,0 +1,11 @@ +// run-rustifx +#![allow(unused)] +use std::sync::{Arc, Mutex}; + +pub struct Foo { + a: Mutex, + b: Arc, //~ HELP you might have meant to end the type parameters here + c: Arc>, +} //~ ERROR expected one of + +fn main() {} diff --git a/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr b/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr new file mode 100644 index 00000000000..46ca1f06be6 --- /dev/null +++ b/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr @@ -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>, + | - 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>, + | + + +error: aborting due to previous error + diff --git a/src/test/ui/parser/removed-syntax-closure-lifetime.stderr b/src/test/ui/parser/removed-syntax-closure-lifetime.stderr index 63b6e138ce5..e107c6b78b3 100644 --- a/src/test/ui/parser/removed-syntax-closure-lifetime.stderr +++ b/src/test/ui/parser/removed-syntax-closure-lifetime.stderr @@ -3,6 +3,11 @@ error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, or `>`, found `/ | LL | type closure = Box; | ^ expected one of 9 possible tokens + | +help: you might have meant to end the type parameters here + | +LL | type closure = Box/fn()>; + | + error: aborting due to previous error -- 2.44.0