Improve diagnostics for parenthesized type arguments
This commit is contained in:
parent
1c580bcb70
commit
58f6aaa710
@ -1,6 +1,7 @@
|
|||||||
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
|
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
|
||||||
use super::{Parser, Restrictions, TokenType};
|
use super::{Parser, Restrictions, TokenType};
|
||||||
use crate::errors::PathSingleColon;
|
use crate::errors::PathSingleColon;
|
||||||
|
use crate::parser::{CommaRecoveryMode, RecoverColon, RecoverComma};
|
||||||
use crate::{errors, maybe_whole};
|
use crate::{errors, maybe_whole};
|
||||||
use ast::token::IdentIsRaw;
|
use ast::token::IdentIsRaw;
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
@ -10,7 +11,7 @@ use rustc_ast::{
|
|||||||
AssocConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs,
|
AssocConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs,
|
||||||
Path, PathSegment, QSelf,
|
Path, PathSegment, QSelf,
|
||||||
};
|
};
|
||||||
use rustc_errors::{Applicability, PResult};
|
use rustc_errors::{Applicability, Diag, PResult};
|
||||||
use rustc_span::symbol::{kw, sym, Ident};
|
use rustc_span::symbol::{kw, sym, Ident};
|
||||||
use rustc_span::{BytePos, Span};
|
use rustc_span::{BytePos, Span};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
@ -373,7 +374,38 @@ impl<'a> Parser<'a> {
|
|||||||
.into()
|
.into()
|
||||||
} else {
|
} else {
|
||||||
// `(T, U) -> R`
|
// `(T, U) -> R`
|
||||||
let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?;
|
|
||||||
|
let prev_token_before_parsing = self.prev_token.clone();
|
||||||
|
let token_before_parsing = self.token.clone();
|
||||||
|
let mut snapshot = None;
|
||||||
|
if self.may_recover()
|
||||||
|
&& prev_token_before_parsing.kind == token::ModSep
|
||||||
|
&& (style == PathStyle::Expr && self.token.can_begin_expr()
|
||||||
|
|| style == PathStyle::Pat && 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.to(token_before_parsing.span),
|
||||||
|
"while parsing this parenthesized list of type arguments starting here",
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(mut snapshot) = snapshot {
|
||||||
|
snapshot.recover_fn_call_leading_path_sep(
|
||||||
|
style,
|
||||||
|
prev_token_before_parsing,
|
||||||
|
&mut error,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(error);
|
||||||
|
}
|
||||||
|
Err(error) => return Err(error),
|
||||||
|
};
|
||||||
let inputs_span = lo.to(self.prev_token.span);
|
let inputs_span = lo.to(self.prev_token.span);
|
||||||
let output =
|
let output =
|
||||||
self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
|
self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
|
||||||
@ -399,6 +431,56 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Recover `$path::(...)` as `$path(...)`.
|
||||||
|
///
|
||||||
|
/// ```ignore (diagnostics)
|
||||||
|
/// foo::(420, "bar")
|
||||||
|
/// ^^ remove extra separator to make the function call
|
||||||
|
/// // or
|
||||||
|
/// match x {
|
||||||
|
/// Foo::(420, "bar") => { ... },
|
||||||
|
/// ^^ remove extra separator to turn this into tuple struct pattern
|
||||||
|
/// _ => { ... },
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
fn recover_fn_call_leading_path_sep(
|
||||||
|
&mut self,
|
||||||
|
style: PathStyle,
|
||||||
|
prev_token_before_parsing: Token,
|
||||||
|
error: &mut Diag<'_>,
|
||||||
|
) {
|
||||||
|
if ((style == PathStyle::Expr && self.parse_paren_comma_seq(|p| p.parse_expr()).is_ok())
|
||||||
|
|| (style == PathStyle::Pat
|
||||||
|
&& self
|
||||||
|
.parse_paren_comma_seq(|p| {
|
||||||
|
p.parse_pat_allow_top_alt(
|
||||||
|
None,
|
||||||
|
RecoverComma::No,
|
||||||
|
RecoverColon::No,
|
||||||
|
CommaRecoveryMode::LikelyTuple,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.is_ok()))
|
||||||
|
&& !matches!(self.token.kind, token::ModSep | token::RArrow)
|
||||||
|
{
|
||||||
|
error.span_suggestion_verbose(
|
||||||
|
prev_token_before_parsing.span,
|
||||||
|
format!(
|
||||||
|
"consider removing the `::` here to {}",
|
||||||
|
match style {
|
||||||
|
PathStyle::Expr => "call the expression",
|
||||||
|
PathStyle::Pat => "turn this into a tuple struct pattern",
|
||||||
|
_ => {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
"",
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Parses generic args (within a path segment) with recovery for extra leading angle brackets.
|
/// Parses generic args (within a path segment) with recovery for extra leading angle brackets.
|
||||||
/// For the purposes of understanding the parsing logic of generic arguments, this function
|
/// For the purposes of understanding the parsing logic of generic arguments, this function
|
||||||
/// can be thought of being the same as just calling `self.parse_angle_args()` if the source
|
/// can be thought of being the same as just calling `self.parse_angle_args()` if the source
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
fn main() {
|
||||||
|
foo::( //~ HELP: consider removing the `::` here to call the expression
|
||||||
|
//~^ NOTE: while parsing this parenthesized list of type arguments starting
|
||||||
|
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
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
error: expected type, found `"test"`
|
||||||
|
--> $DIR/diagnostics-parenthesized-type-arguments-issue-120892-1.rs:11:9
|
||||||
|
|
|
||||||
|
LL | foo::(
|
||||||
|
| --- while parsing this parenthesized list of type arguments starting here
|
||||||
|
...
|
||||||
|
LL | baz("test"),
|
||||||
|
| ^^^^^^ expected type
|
||||||
|
|
|
||||||
|
help: consider removing the `::` here to call the expression
|
||||||
|
|
|
||||||
|
LL - foo::(
|
||||||
|
LL + foo(
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
@ -0,0 +1,5 @@
|
|||||||
|
fn main() {
|
||||||
|
foo::/* definitely not harmful comment */(123, "foo") -> (u32); //~ ERROR: expected type, found `123`
|
||||||
|
//~^ NOTE: while parsing this parenthesized list of type arguments starting
|
||||||
|
//~^^ NOTE: expected type
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
error: expected type, found `123`
|
||||||
|
--> $DIR/diagnostics-parenthesized-type-arguments-issue-120892-2.rs:2:45
|
||||||
|
|
|
||||||
|
LL | foo::/* definitely not harmful comment */(123, "foo") -> (u32);
|
||||||
|
| ---------------------------------------^^^ expected type
|
||||||
|
| |
|
||||||
|
| while parsing this parenthesized list of type arguments starting here
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
@ -0,0 +1,14 @@
|
|||||||
|
struct Foo(u32, u32);
|
||||||
|
impl Foo {
|
||||||
|
fn foo(&self) {
|
||||||
|
match *self {
|
||||||
|
Foo::(1, 2) => {}, //~ HELP: consider removing the `::` here to turn this into a tuple struct pattern
|
||||||
|
//~^ NOTE: while parsing this parenthesized list of type arguments starting
|
||||||
|
//~^^ ERROR: expected type, found `1`
|
||||||
|
//~^^^ NOTE: expected type
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,16 @@
|
|||||||
|
error: expected type, found `1`
|
||||||
|
--> $DIR/diagnostics-parenthesized-type-arguments-issue-120892-3.rs:5:19
|
||||||
|
|
|
||||||
|
LL | Foo::(1, 2) => {},
|
||||||
|
| ---^ expected type
|
||||||
|
| |
|
||||||
|
| while parsing this parenthesized list of type arguments starting here
|
||||||
|
|
|
||||||
|
help: consider removing the `::` here to turn this into a tuple struct pattern
|
||||||
|
|
|
||||||
|
LL - Foo::(1, 2) => {},
|
||||||
|
LL + Foo(1, 2) => {},
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user