From 1d23adaef0c8a92d23c2014aaa87c83e1448e2ae Mon Sep 17 00:00:00 2001 From: Daniel Sedlak Date: Thu, 7 Mar 2024 19:06:09 +0100 Subject: [PATCH] Improve diagnostics for parenthesized type arguments --- compiler/rustc_parse/src/parser/path.rs | 48 ++++++++++++++++++- ...nthesized-type-arguments-issue-120892-1.rs | 14 ++++++ ...sized-type-arguments-issue-120892-1.stderr | 17 +++++++ ...nthesized-type-arguments-issue-120892-2.rs | 5 ++ ...sized-type-arguments-issue-120892-2.stderr | 10 ++++ ...nthesized-type-arguments-issue-120892-3.rs | 14 ++++++ ...sized-type-arguments-issue-120892-3.stderr | 16 +++++++ 7 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-1.rs create mode 100644 tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-1.stderr create mode 100644 tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-2.rs create mode 100644 tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-2.stderr create mode 100644 tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-3.rs create mode 100644 tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-3.stderr diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 545db5138a3ab..10fcabadaf4e9 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -1,6 +1,7 @@ use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{Parser, Restrictions, TokenType}; use crate::errors::PathSingleColon; +use crate::parser::{CommaRecoveryMode, RecoverColon, RecoverComma}; use crate::{errors, maybe_whole}; use ast::token::IdentIsRaw; use rustc_ast::ptr::P; @@ -373,7 +374,52 @@ impl<'a> Parser<'a> { .into() } else { // `(T, U) -> R` - let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?; + let prev_token_before_parsing = self.prev_token.clone(); + + let mut snapshot = None; + if self.may_recover() + && (self.token.can_begin_expr() || self.token.can_begin_pattern()) + { + snapshot = Some(self.create_snapshot_for_diagnostic()); + } + + let (inputs, _) = match self.parse_paren_comma_seq(|p| p.parse_ty()) { + Ok(output) => output, + Err(mut error) if prev_token_before_parsing.kind == token::ModSep => { + error.span_label(prev_token_before_parsing.span.with_hi(prev_token_before_parsing.span.hi() + BytePos(1)), "while parsing this list of parenthesized type arguments starting here"); + + if let Some(mut snapshot) = snapshot { + if ((style == PathStyle::Expr + && snapshot.parse_paren_comma_seq(|p| p.parse_expr()).is_ok()) + || (style == PathStyle::Pat + && snapshot + .parse_paren_comma_seq(|p| { + p.parse_pat_allow_top_alt( + None, + RecoverComma::No, + RecoverColon::No, + CommaRecoveryMode::LikelyTuple, + ) + }) + .is_ok())) + && snapshot.token.kind != token::ModSep + && snapshot.token.kind != token::RArrow + { + { + error.span_suggestion_verbose( + prev_token_before_parsing.span, + "consider removing `::`", + "", + Applicability::Unspecified, + ); + } + } + } + + return Err(error); + } + Err(error) => return Err(error), + }; let inputs_span = lo.to(self.prev_token.span); let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?; diff --git a/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-1.rs b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-1.rs new file mode 100644 index 0000000000000..40d1c3dd9939d --- /dev/null +++ b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-1.rs @@ -0,0 +1,14 @@ +fn main() { + foo::( //~ HELP: consider removing `::` + //~^ NOTE: while parsing this list of parenthesized type arguments starting here + bar(x, y, z), + bar(x, y, z), + bar(x, y, z), + bar(x, y, z), + bar(x, y, z), + bar(x, y, z), + bar(x, y, z), + baz("test"), //~ ERROR: expected type, found `"test"` + //~^ NOTE: expected type + ) +} diff --git a/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-1.stderr b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-1.stderr new file mode 100644 index 0000000000000..434e198417bd7 --- /dev/null +++ b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-1.stderr @@ -0,0 +1,17 @@ +error: expected type, found `"test"` + --> $DIR/issue-120892-1.rs:11:9 + | +LL | foo::( + | --- while parsing this list of parenthesized type arguments starting here +... +LL | baz("test"), + | ^^^^^^ expected type + | +help: consider removing `::` + | +LL - foo::( +LL + foo( + | + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-2.rs b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-2.rs new file mode 100644 index 0000000000000..281cf10699629 --- /dev/null +++ b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-2.rs @@ -0,0 +1,5 @@ +fn main() { + foo::(123, "foo") -> (u32); //~ ERROR: expected type, found `123` + //~^ NOTE: while parsing this list of parenthesized type arguments starting here + //~^^ NOTE: expected type +} diff --git a/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-2.stderr b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-2.stderr new file mode 100644 index 0000000000000..1d66ae6074960 --- /dev/null +++ b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-2.stderr @@ -0,0 +1,10 @@ +error: expected type, found `123` + --> $DIR/issue-120892-2.rs:2:9 + | +LL | foo::(123, "foo") -> (u32); + | ---^^^ expected type + | | + | while parsing this list of parenthesized type arguments starting here + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-3.rs b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-3.rs new file mode 100644 index 0000000000000..7a87a3aafc25c --- /dev/null +++ b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-3.rs @@ -0,0 +1,14 @@ +struct Foo(u32, u32); +impl Foo { + fn foo(&self) { + match *self { + Foo::(1, 2) => {}, //~ HELP: consider removing `::` + //~^ NOTE: while parsing this list of parenthesized type arguments starting here + //~^^ ERROR: expected type, found `1` + //~^^^ NOTE: expected type + _ => {}, + } + } +} + +fn main() {} diff --git a/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-3.stderr b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-3.stderr new file mode 100644 index 0000000000000..75cd8d9efbdd6 --- /dev/null +++ b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-3.stderr @@ -0,0 +1,16 @@ +error: expected type, found `1` + --> $DIR/issue-120892-3.rs:5:19 + | +LL | Foo::(1, 2) => {}, + | ---^ expected type + | | + | while parsing this list of parenthesized type arguments starting here + | +help: consider removing `::` + | +LL - Foo::(1, 2) => {}, +LL + Foo(1, 2) => {}, + | + +error: aborting due to 1 previous error +