diff options
| author | bors <bors@rust-lang.org> | 2021-01-23 06:27:21 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-01-23 06:27:21 +0000 |
| commit | 1986b58c646a9523d0a8a0fa8a0bd20492e7795d (patch) | |
| tree | 4fbb2a16a834aad3b18a2a07b445c6ee8d8f3d29 | |
| parent | fe0fa59b50313b30e3bfcf1e3e5e1a71fa3a849d (diff) | |
| parent | 3ba6cf13f42250c1d0d3bab206e37e93df0582c4 (diff) | |
| download | rust-1986b58c646a9523d0a8a0fa8a0bd20492e7795d.tar.gz rust-1986b58c646a9523d0a8a0fa8a0bd20492e7795d.zip | |
Auto merge of #80065 - b-naber:parse-angle-arg-diagnostics, r=petrochenkov
Improve diagnostics when parsing angle args https://github.com/rust-lang/rust/pull/79266 introduced parsing of generic arguments in associated type constraints, this however resulted in possibly very confusing error messages in cases in which closing angle brackets were missing such as in `Vec<(u32, _, _) = vec![]`, which outputs an incorrectly parsed equality constraint error, as noted by `@cynecx.` This PR tries to provide better error messages in such cases. r? `@petrochenkov`
17 files changed, 169 insertions, 88 deletions
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 35435baea70..f2fcce5c226 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2,14 +2,13 @@ use super::ty::AllowPlus; use super::TokenType; use super::{BlockMode, Parser, PathStyle, Restrictions, SemiColonMode, SeqSep, TokenExpectType}; +use rustc_ast as ast; use rustc_ast::ptr::P; use rustc_ast::token::{self, Lit, LitKind, TokenKind}; use rustc_ast::util::parser::AssocOp; -use rustc_ast::{ - self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode, - Block, BlockCheckMode, Expr, ExprKind, GenericArg, Item, ItemKind, Mutability, Param, Pat, - PatKind, Path, PathSegment, QSelf, Ty, TyKind, -}; +use rustc_ast::{AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec}; +use rustc_ast::{BinOpKind, BindingMode, Block, BlockCheckMode, Expr, ExprKind, GenericArg, Item}; +use rustc_ast::{ItemKind, Mutability, Param, Pat, PatKind, Path, PathSegment, QSelf, Ty, TyKind}; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{pluralize, struct_span_err}; @@ -220,6 +219,7 @@ impl<'a> Parser<'a> { edible: &[TokenKind], inedible: &[TokenKind], ) -> PResult<'a, bool /* recovered */> { + debug!("expected_one_of_not_found(edible: {:?}, inedible: {:?})", edible, inedible); fn tokens_to_string(tokens: &[TokenType]) -> String { let mut i = tokens.iter(); // This might be a sign we need a connect method on `Iterator`. @@ -245,6 +245,7 @@ impl<'a> Parser<'a> { .collect::<Vec<_>>(); expected.sort_by_cached_key(|x| x.to_string()); expected.dedup(); + let expect = tokens_to_string(&expected[..]); let actual = super::token_descr(&self.token); let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 { @@ -270,6 +271,16 @@ impl<'a> Parser<'a> { }; self.last_unexpected_token_span = Some(self.token.span); let mut err = self.struct_span_err(self.token.span, &msg_exp); + + // Add suggestion for a missing closing angle bracket if '>' is included in expected_tokens + // there are unclosed angle brackets + if self.unmatched_angle_bracket_count > 0 + && self.token.kind == TokenKind::Eq + && expected.iter().any(|tok| matches!(tok, TokenType::Token(TokenKind::Gt))) + { + err.span_label(self.prev_token.span, "maybe try to close unmatched angle bracket"); + } + let sp = if self.token == token::Eof { // This is EOF; don't want to point at the following char, but rather the last token. self.prev_token.span diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index b332005ca74..f11c6591de9 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -277,7 +277,7 @@ impl TokenCursor { } } -#[derive(Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq)] enum TokenType { Token(TokenKind), Keyword(Symbol), diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index dd36122f6a1..4234740b2b1 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -185,7 +185,6 @@ impl<'a> Parser<'a> { pub(super) fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, PathSegment> { let ident = self.parse_path_segment_ident()?; - let is_args_start = |token: &Token| { matches!( token.kind, @@ -420,7 +419,10 @@ impl<'a> Parser<'a> { match arg { Some(arg) => { if self.check(&token::Colon) | self.check(&token::Eq) { - let (ident, gen_args) = self.get_ident_from_generic_arg(arg, lo)?; + let (ident, gen_args) = match self.get_ident_from_generic_arg(arg) { + Ok(ident_gen_args) => ident_gen_args, + Err(arg) => return Ok(Some(AngleBracketedArg::Arg(arg))), + }; let kind = if self.eat(&token::Colon) { // Parse associated type constraint bound. @@ -561,50 +563,15 @@ impl<'a> Parser<'a> { fn get_ident_from_generic_arg( &self, gen_arg: GenericArg, - lo: Span, - ) -> PResult<'a, (Ident, Option<GenericArgs>)> { - let gen_arg_span = gen_arg.span(); - match gen_arg { - GenericArg::Type(t) => match t.into_inner().kind { - ast::TyKind::Path(qself, mut path) => { - if let Some(qself) = qself { - let mut err = self.struct_span_err( - gen_arg_span, - "qualified paths cannot be used in associated type constraints", - ); - err.span_label( - qself.path_span, - "not allowed in associated type constraints", - ); - return Err(err); - } - if path.segments.len() == 1 { - let path_seg = path.segments.remove(0); - let ident = path_seg.ident; - let gen_args = path_seg.args.map(|args| args.into_inner()); - return Ok((ident, gen_args)); - } - let err = self.struct_span_err( - path.span, - "paths with multiple segments cannot be used in associated type constraints", - ); - return Err(err); - } - _ => { - let span = lo.to(self.prev_token.span); - let err = self.struct_span_err( - span, - "only path types can be used in associated type constraints", - ); - return Err(err); + ) -> Result<(Ident, Option<GenericArgs>), GenericArg> { + if let GenericArg::Type(ty) = &gen_arg { + if let ast::TyKind::Path(qself, path) = &ty.kind { + if qself.is_none() && path.segments.len() == 1 { + let seg = &path.segments[0]; + return Ok((seg.ident, seg.args.as_deref().cloned())); } - }, - _ => { - let span = lo.to(self.prev_token.span); - let err = self - .struct_span_err(span, "only types can be used in associated type constraints"); - return Err(err); } } + Err(gen_arg) } } diff --git a/src/test/ui/generic-associated-types/parse/trait-path-expected-token.stderr b/src/test/ui/generic-associated-types/parse/trait-path-expected-token.stderr index 051253cadc6..8abc4ccc9a5 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-expected-token.stderr +++ b/src/test/ui/generic-associated-types/parse/trait-path-expected-token.stderr @@ -2,7 +2,9 @@ error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=` --> $DIR/trait-path-expected-token.rs:8:33 | LL | fn f1<'a>(arg : Box<dyn X<Y = B = &'a ()>>) {} - | ^ expected one of 7 possible tokens + | - ^ expected one of 7 possible tokens + | | + | maybe try to close unmatched angle bracket warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/trait-path-expected-token.rs:1:12 diff --git a/src/test/ui/generic-associated-types/parse/trait-path-expressions.rs b/src/test/ui/generic-associated-types/parse/trait-path-expressions.rs index de61cfa1cf7..5e50c6b35c9 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-expressions.rs +++ b/src/test/ui/generic-associated-types/parse/trait-path-expressions.rs @@ -17,7 +17,7 @@ mod error2 { } fn f2<'a>(arg : Box<dyn X< { 1 } = 32 >>) {} - //~^ ERROR: only types can be used in associated type constraints + //~^ ERROR: expected one of } fn main() {} 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 a9ba8adcaba..27e1a750b21 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 @@ -6,11 +6,13 @@ LL | fn f1<'a>(arg : Box<dyn X< 1 = 32 >>) {} | | | while parsing a const generic argument starting here -error: only types can be used in associated type constraints - --> $DIR/trait-path-expressions.rs:19:30 +error: expected one of `,`, `:`, or `>`, found `=` + --> $DIR/trait-path-expressions.rs:19:36 | LL | fn f2<'a>(arg : Box<dyn X< { 1 } = 32 >>) {} - | ^^^^^ + | - ^ expected one of `,`, `:`, or `>` + | | + | maybe try to close unmatched angle bracket warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/trait-path-expressions.rs:1:12 diff --git a/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr b/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr index 8a5e2c29c36..f6038566e5b 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr +++ b/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr @@ -28,7 +28,9 @@ error: expected one of `>`, a const expression, lifetime, or type, found `=` --> $DIR/trait-path-missing-gen_arg.rs:17:30 | LL | fn f1<'a>(arg : Box<dyn X< = 32 >>) {} - | ^ expected one of `>`, a const expression, lifetime, or type + | - ^ expected one of `>`, a const expression, lifetime, or type + | | + | maybe try to close unmatched angle bracket warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/trait-path-missing-gen_arg.rs:1:12 diff --git a/src/test/ui/generic-associated-types/parse/trait-path-segments.rs b/src/test/ui/generic-associated-types/parse/trait-path-segments.rs index 0bf48b1f418..eba30e1438f 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-segments.rs +++ b/src/test/ui/generic-associated-types/parse/trait-path-segments.rs @@ -7,7 +7,7 @@ const _: () = { } fn f1<'a>(arg : Box<dyn X<X::Y = u32>>) {} - //~^ ERROR: paths with multiple segments cannot be used in associated type constraints + //~^ ERROR: expected one of }; const _: () = { @@ -18,7 +18,7 @@ const _: () = { trait Z {} impl<T : X<<Self as X>::Y<'a> = &'a u32>> Z for T {} - //~^ ERROR: qualified paths cannot be used in associated type constraints + //~^ ERROR: expected one of }; const _: () = { @@ -29,7 +29,7 @@ const _: () = { trait Z {} impl<T : X<X::Y<'a> = &'a u32>> Z for T {} - //~^ ERROR: paths with multiple segments cannot be used in associated type constraints + //~^ ERROR: expected one of }; fn main() {} 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 4e2b84d0182..c82953aaed7 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 @@ -1,22 +1,26 @@ -error: paths with multiple segments cannot be used in associated type constraints - --> $DIR/trait-path-segments.rs:9:31 +error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, or `>`, found `=` + --> $DIR/trait-path-segments.rs:9:36 | LL | fn f1<'a>(arg : Box<dyn X<X::Y = u32>>) {} - | ^^^^ + | - ^ expected one of 8 possible tokens + | | + | maybe try to close unmatched angle bracket -error: qualified paths cannot be used in associated type constraints - --> $DIR/trait-path-segments.rs:20:16 +error: expected one of `,`, `::`, `:`, or `>`, found `=` + --> $DIR/trait-path-segments.rs:20:35 | LL | impl<T : X<<Self as X>::Y<'a> = &'a u32>> Z for T {} - | ^^^^^^^^^-^^^^^^^^ - | | - | not allowed in associated type constraints + | - ^ expected one of `,`, `::`, `:`, or `>` + | | + | maybe try to close unmatched angle bracket -error: paths with multiple segments cannot be used in associated type constraints - --> $DIR/trait-path-segments.rs:31:16 +error: expected one of `!`, `+`, `,`, `::`, `:`, or `>`, found `=` + --> $DIR/trait-path-segments.rs:31:25 | LL | impl<T : X<X::Y<'a> = &'a u32>> Z for T {} - | ^^^^^^^^ + | - ^ expected one of `!`, `+`, `,`, `::`, `:`, or `>` + | | + | maybe try to close unmatched angle bracket warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/trait-path-segments.rs:1:12 diff --git a/src/test/ui/generic-associated-types/parse/trait-path-types.rs b/src/test/ui/generic-associated-types/parse/trait-path-types.rs index 6cdb501ec65..522b3edc638 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-types.rs +++ b/src/test/ui/generic-associated-types/parse/trait-path-types.rs @@ -7,17 +7,17 @@ trait X { const _: () = { fn f<'a>(arg : Box<dyn X< [u8; 1] = u32>>) {} - //~^ ERROR: only path types can be used in associated type constraints + //~^ ERROR: expected one of }; const _: () = { fn f1<'a>(arg : Box<dyn X<(Y<'a>) = &'a ()>>) {} - //~^ ERROR: only path types can be used in associated type constraints + //~^ ERROR: expected one of }; const _: () = { fn f1<'a>(arg : Box<dyn X< 'a = u32 >>) {} - //~^ ERROR: only types can be used in associated type constraints + //~^ ERROR: expected one of }; fn main() {} 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 f5be084613b..ac791c22481 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 @@ -1,20 +1,26 @@ -error: only path types can be used in associated type constraints - --> $DIR/trait-path-types.rs:9:29 +error: expected one of `,`, `:`, or `>`, found `=` + --> $DIR/trait-path-types.rs:9:37 | LL | fn f<'a>(arg : Box<dyn X< [u8; 1] = u32>>) {} - | ^^^^^^^ + | - ^ expected one of `,`, `:`, or `>` + | | + | maybe try to close unmatched angle bracket -error: only path types can be used in associated type constraints - --> $DIR/trait-path-types.rs:14:29 +error: expected one of `,`, `:`, or `>`, found `=` + --> $DIR/trait-path-types.rs:14:37 | LL | fn f1<'a>(arg : Box<dyn X<(Y<'a>) = &'a ()>>) {} - | ^^^^^^^ + | - ^ expected one of `,`, `:`, or `>` + | | + | maybe try to close unmatched angle bracket -error: only types can be used in associated type constraints - --> $DIR/trait-path-types.rs:19:30 +error: expected one of `,`, `:`, or `>`, found `=` + --> $DIR/trait-path-types.rs:19:33 | LL | fn f1<'a>(arg : Box<dyn X< 'a = u32 >>) {} - | ^^ + | -- ^ expected one of `,`, `:`, or `>` + | | + | maybe try to close unmatched angle bracket warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/trait-path-types.rs:1:12 diff --git a/src/test/ui/issues/issue-34334.rs b/src/test/ui/issues/issue-34334.rs index b45c00f6943..51486bc40de 100644 --- a/src/test/ui/issues/issue-34334.rs +++ b/src/test/ui/issues/issue-34334.rs @@ -1,6 +1,8 @@ fn main () { let sr: Vec<(u32, _, _) = vec![]; - //~^ ERROR only path types can be used in associated type constraints + //~^ ERROR expected one of + let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect(); //~^ ERROR a value of type `Vec<(u32, _, _)>` cannot be built + } diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr index a9b9bf06d7f..acb44ce2c35 100644 --- a/src/test/ui/issues/issue-34334.stderr +++ b/src/test/ui/issues/issue-34334.stderr @@ -1,13 +1,14 @@ -error: only path types can be used in associated type constraints - --> $DIR/issue-34334.rs:2:17 +error: expected one of `,`, `:`, or `>`, found `=` + --> $DIR/issue-34334.rs:2:29 | LL | let sr: Vec<(u32, _, _) = vec![]; - | -- ^^^^^^^^^^^ - | | + | -- - ^ expected one of `,`, `:`, or `>` + | | | + | | maybe try to close unmatched angle bracket | while parsing the type for `sr` error[E0277]: a value of type `Vec<(u32, _, _)>` cannot be built from an iterator over elements of type `()` - --> $DIR/issue-34334.rs:4:87 + --> $DIR/issue-34334.rs:5:87 | LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect(); | ^^^^^^^ value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator<Item=()>` diff --git a/src/test/ui/parser/missing-closing-angle-bracket-eq-constraint.rs b/src/test/ui/parser/missing-closing-angle-bracket-eq-constraint.rs new file mode 100644 index 00000000000..da95c1bfa27 --- /dev/null +++ b/src/test/ui/parser/missing-closing-angle-bracket-eq-constraint.rs @@ -0,0 +1,23 @@ +struct Foo<T1, T2> { + _a : T1, + _b : T2, +} + +fn test1<T>(arg : T) { + let v : Vec<(u32,_) = vec![]; + //~^ ERROR: expected one of + //~| ERROR: type annotations needed +} + +fn test2<T1, T2>(arg1 : T1, arg2 : T2) { + let foo : Foo::<T1, T2 = Foo {_a : arg1, _b : arg2}; + //~^ ERROR: expected one of +} + +fn test3<'a>(arg : &'a u32) { + let v : Vec<'a = vec![]; + //~^ ERROR: expected one of + //~| ERROR: type annotations needed for `Vec<T>` +} + +fn main() {} 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 new file mode 100644 index 00000000000..ae53334f5e0 --- /dev/null +++ b/src/test/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr @@ -0,0 +1,49 @@ +error: expected one of `,`, `:`, or `>`, found `=` + --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:7:23 + | +LL | let v : Vec<(u32,_) = vec![]; + | - - ^ expected one of `,`, `:`, or `>` + | | | + | | maybe try to close unmatched angle bracket + | while parsing the type for `v` + +error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `{` + --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:13:32 + | +LL | let foo : Foo::<T1, T2 = Foo {_a : arg1, _b : arg2}; + | --- ^ expected one of 7 possible tokens + | | + | while parsing the type for `foo` + +error: expected one of `,`, `:`, or `>`, found `=` + --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:18:18 + | +LL | let v : Vec<'a = vec![]; + | - -- ^ expected one of `,`, `:`, or `>` + | | | + | | maybe try to close unmatched angle bracket + | while parsing the type for `v` + +error[E0282]: type annotations needed for `Vec<T>` + --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:7:25 + | +LL | let v : Vec<(u32,_) = vec![]; + | - ^^^^^^ cannot infer type for type parameter `T` + | | + | consider giving `v` the explicit type `Vec<T>`, where the type parameter `T` is specified + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0282]: type annotations needed for `Vec<T>` + --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:18:20 + | +LL | let v : Vec<'a = vec![]; + | - ^^^^^^ cannot infer type for type parameter `T` + | | + | consider giving `v` the explicit type `Vec<T>`, where the type parameter `T` is specified + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/parser/nested-missing-closing-angle-bracket.rs b/src/test/ui/parser/nested-missing-closing-angle-bracket.rs new file mode 100644 index 00000000000..84ffdd176ae --- /dev/null +++ b/src/test/ui/parser/nested-missing-closing-angle-bracket.rs @@ -0,0 +1,4 @@ +fn main() { + let v : Vec::<Vec<(u32,_,_)> = vec![vec![]]; + //~^ ERROR: expected one of +} diff --git a/src/test/ui/parser/nested-missing-closing-angle-bracket.stderr b/src/test/ui/parser/nested-missing-closing-angle-bracket.stderr new file mode 100644 index 00000000000..b85bc02568c --- /dev/null +++ b/src/test/ui/parser/nested-missing-closing-angle-bracket.stderr @@ -0,0 +1,8 @@ +error: expected one of `,` or `>`, found `;` + --> $DIR/nested-missing-closing-angle-bracket.rs:2:46 + | +LL | let v : Vec::<Vec<(u32,_,_)> = vec![vec![]]; + | - while parsing the type for `v` ^ expected one of `,` or `>` + +error: aborting due to previous error + |
