Migrate even more diagnostics in rustc_parse to diagnostic structs
This commit is contained in:
parent
760c4352d6
commit
00f95468c4
4 changed files with 395 additions and 213 deletions
|
@ -316,3 +316,56 @@ parser_expected_semi_found_str = expected `;`, found `{$token_str}`
|
||||||
parser_sugg_change_this_to_semi = change this to `;`
|
parser_sugg_change_this_to_semi = change this to `;`
|
||||||
parser_sugg_add_semi = add `;` here
|
parser_sugg_add_semi = add `;` here
|
||||||
parser_label_unexpected_token = unexpected token
|
parser_label_unexpected_token = unexpected token
|
||||||
|
|
||||||
|
parser_unmatched_angle_brackets = {$num_extra_brackets ->
|
||||||
|
[one] unmatched angle bracket
|
||||||
|
*[other] unmatched angle brackets
|
||||||
|
}
|
||||||
|
.suggestion = {$num_extra_brackets ->
|
||||||
|
[one] remove extra angle bracket
|
||||||
|
*[other] remove extra angle brackets
|
||||||
|
}
|
||||||
|
|
||||||
|
parser_generic_parameters_without_angle_brackets = generic parameters without surrounding angle brackets
|
||||||
|
.suggestion = surround the type parameters with angle brackets
|
||||||
|
|
||||||
|
parser_comparison_operators_cannot_be_chained = comparison operators cannot be chained
|
||||||
|
.sugg_parentheses_for_function_args = or use `(...)` if you meant to specify fn arguments
|
||||||
|
.sugg_split_comparison = split the comparison into two
|
||||||
|
.sugg_parenthesize = parenthesize the comparison
|
||||||
|
parser_sugg_turbofish_syntax = use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
||||||
|
|
||||||
|
parser_question_mark_in_type = invalid `?` in type
|
||||||
|
.label = `?` is only allowed on expressions, not types
|
||||||
|
.suggestion = if you meant to express that the type might not contain a value, use the `Option` wrapper type
|
||||||
|
|
||||||
|
parser_unexpected_parentheses_in_for_head = unexpected parentheses surrounding `for` loop head
|
||||||
|
.suggestion = remove parentheses in `for` loop
|
||||||
|
|
||||||
|
parser_doc_comment_on_param_type = documentation comments cannot be applied to a function parameter's type
|
||||||
|
.label = doc comments are not allowed here
|
||||||
|
|
||||||
|
parser_attribute_on_param_type = attributes cannot be applied to a function parameter's type
|
||||||
|
.label = attributes are not allowed here
|
||||||
|
|
||||||
|
parser_pattern_method_param_without_body = patterns aren't allowed in methods without bodies
|
||||||
|
.suggestion = give this argument a name or use an underscore to ignore it
|
||||||
|
|
||||||
|
parser_self_param_not_first = unexpected `self` parameter in function
|
||||||
|
.label = must be the first parameter of an associated function
|
||||||
|
|
||||||
|
parser_const_generic_without_braces = expressions must be enclosed in braces to be used as const generic arguments
|
||||||
|
.suggestion = enclose the `const` expression in braces
|
||||||
|
|
||||||
|
parser_unexpected_const_param_declaration = unexpected `const` parameter declaration
|
||||||
|
.label = expected a `const` expression, not a parameter declaration
|
||||||
|
.suggestion = `const` parameters must be declared for the `impl`
|
||||||
|
|
||||||
|
parser_unexpected_const_in_generic_param = expected lifetime, type, or constant, found keyword `const`
|
||||||
|
.suggestion = the `const` keyword is only needed in the definition of the type
|
||||||
|
|
||||||
|
parser_async_move_order_incorrect = the order of `move` and `async` is incorrect
|
||||||
|
.suggestion = try switching the order
|
||||||
|
|
||||||
|
parser_double_colon_in_bound = expected `:` followed by trait or lifetime
|
||||||
|
.suggestion = use single colon
|
||||||
|
|
|
@ -1032,3 +1032,214 @@ pub(crate) struct StructLiteralBodyWithoutPathSugg {
|
||||||
#[suggestion_part(code = " }}")]
|
#[suggestion_part(code = " }}")]
|
||||||
pub after: Span,
|
pub after: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::unmatched_angle_brackets)]
|
||||||
|
pub(crate) struct UnmatchedAngleBrackets {
|
||||||
|
#[primary_span]
|
||||||
|
#[suggestion(code = "", applicability = "machine-applicable")]
|
||||||
|
pub span: Span,
|
||||||
|
pub num_extra_brackets: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::generic_parameters_without_angle_brackets)]
|
||||||
|
pub(crate) struct GenericParamsWithoutAngleBrackets {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub sugg: GenericParamsWithoutAngleBracketsSugg,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")]
|
||||||
|
pub(crate) struct GenericParamsWithoutAngleBracketsSugg {
|
||||||
|
#[suggestion_part(code = "<")]
|
||||||
|
pub left: Span,
|
||||||
|
#[suggestion_part(code = ">")]
|
||||||
|
pub right: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::comparison_operators_cannot_be_chained)]
|
||||||
|
pub(crate) struct ComparisonOperatorsCannotBeChained {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Vec<Span>,
|
||||||
|
#[suggestion_verbose(
|
||||||
|
parser::sugg_turbofish_syntax,
|
||||||
|
code = "::",
|
||||||
|
applicability = "maybe-incorrect"
|
||||||
|
)]
|
||||||
|
pub suggest_turbofish: Option<Span>,
|
||||||
|
#[help(parser::sugg_turbofish_syntax)]
|
||||||
|
#[help(parser::sugg_parentheses_for_function_args)]
|
||||||
|
pub help_turbofish: Option<()>,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub chaining_sugg: Option<ComparisonOperatorsCannotBeChainedSugg>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
pub(crate) enum ComparisonOperatorsCannotBeChainedSugg {
|
||||||
|
#[suggestion_verbose(
|
||||||
|
parser::sugg_split_comparison,
|
||||||
|
code = " && {middle_term}",
|
||||||
|
applicability = "maybe-incorrect"
|
||||||
|
)]
|
||||||
|
SplitComparison {
|
||||||
|
#[primary_span]
|
||||||
|
span: Span,
|
||||||
|
middle_term: String,
|
||||||
|
},
|
||||||
|
#[multipart_suggestion(parser::sugg_parenthesize, applicability = "maybe-incorrect")]
|
||||||
|
Parenthesize {
|
||||||
|
#[suggestion_part(code = "(")]
|
||||||
|
left: Span,
|
||||||
|
#[suggestion_part(code = ")")]
|
||||||
|
right: Span,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::question_mark_in_type)]
|
||||||
|
pub(crate) struct QuestionMarkInType {
|
||||||
|
#[primary_span]
|
||||||
|
#[label]
|
||||||
|
pub span: Span,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub sugg: QuestionMarkInTypeSugg,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")]
|
||||||
|
pub(crate) struct QuestionMarkInTypeSugg {
|
||||||
|
#[suggestion_part(code = "Option<")]
|
||||||
|
pub left: Span,
|
||||||
|
#[suggestion_part(code = ">")]
|
||||||
|
pub right: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::unexpected_parentheses_in_for_head)]
|
||||||
|
pub(crate) struct ParenthesesInForHead {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Vec<Span>,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub sugg: ParenthesesInForHeadSugg,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")]
|
||||||
|
pub(crate) struct ParenthesesInForHeadSugg {
|
||||||
|
#[suggestion_part(code = "")]
|
||||||
|
pub left: Span,
|
||||||
|
#[suggestion_part(code = "")]
|
||||||
|
pub right: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::doc_comment_on_param_type)]
|
||||||
|
pub(crate) struct DocCommentOnParamType {
|
||||||
|
#[primary_span]
|
||||||
|
#[label]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::attribute_on_param_type)]
|
||||||
|
pub(crate) struct AttributeOnParamType {
|
||||||
|
#[primary_span]
|
||||||
|
#[label]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::pattern_method_param_without_body, code = "E0642")]
|
||||||
|
pub(crate) struct PatternMethodParamWithoutBody {
|
||||||
|
#[primary_span]
|
||||||
|
#[suggestion(code = "_", applicability = "machine-applicable")]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::self_param_not_first)]
|
||||||
|
pub(crate) struct SelfParamNotFirst {
|
||||||
|
#[primary_span]
|
||||||
|
#[label]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::const_generic_without_braces)]
|
||||||
|
pub(crate) struct ConstGenericWithoutBraces {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub sugg: ConstGenericWithoutBracesSugg,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")]
|
||||||
|
pub(crate) struct ConstGenericWithoutBracesSugg {
|
||||||
|
#[suggestion_part(code = "{{ ")]
|
||||||
|
pub left: Span,
|
||||||
|
#[suggestion_part(code = " }}")]
|
||||||
|
pub right: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::unexpected_const_param_declaration)]
|
||||||
|
pub(crate) struct UnexpectedConstParamDeclaration {
|
||||||
|
#[primary_span]
|
||||||
|
#[label]
|
||||||
|
pub span: Span,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub sugg: Option<UnexpectedConstParamDeclarationSugg>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
pub(crate) enum UnexpectedConstParamDeclarationSugg {
|
||||||
|
#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")]
|
||||||
|
AddParam {
|
||||||
|
#[suggestion_part(code = "<{snippet}>")]
|
||||||
|
impl_generics: Span,
|
||||||
|
#[suggestion_part(code = "{ident}")]
|
||||||
|
incorrect_decl: Span,
|
||||||
|
snippet: String,
|
||||||
|
ident: String,
|
||||||
|
},
|
||||||
|
#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")]
|
||||||
|
AppendParam {
|
||||||
|
#[suggestion_part(code = ", {snippet}")]
|
||||||
|
impl_generics_end: Span,
|
||||||
|
#[suggestion_part(code = "{ident}")]
|
||||||
|
incorrect_decl: Span,
|
||||||
|
snippet: String,
|
||||||
|
ident: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::unexpected_const_in_generic_param)]
|
||||||
|
pub(crate) struct UnexpectedConstInGenericParam {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
#[suggestion_verbose(code = "", applicability = "maybe-incorrect")]
|
||||||
|
pub to_remove: Option<Span>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::async_move_order_incorrect)]
|
||||||
|
pub(crate) struct AsyncMoveOrderIncorrect {
|
||||||
|
#[primary_span]
|
||||||
|
#[suggestion_verbose(code = "async move", applicability = "maybe-incorrect")]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::double_colon_in_bound)]
|
||||||
|
pub(crate) struct DoubleColonInBound {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
#[suggestion(code = ": ", applicability = "machine-applicable")]
|
||||||
|
pub between: Span,
|
||||||
|
}
|
||||||
|
|
|
@ -4,10 +4,17 @@ use super::{
|
||||||
TokenExpectType, TokenType,
|
TokenExpectType, TokenType,
|
||||||
};
|
};
|
||||||
use crate::errors::{
|
use crate::errors::{
|
||||||
AmbiguousPlus, BadQPathStage2, BadTypePlus, BadTypePlusSub, ExpectedIdentifier, ExpectedSemi,
|
AmbiguousPlus, AttributeOnParamType, BadQPathStage2, BadTypePlus, BadTypePlusSub,
|
||||||
ExpectedSemiSugg, InInTypo, IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait,
|
ComparisonOperatorsCannotBeChained, ComparisonOperatorsCannotBeChainedSugg,
|
||||||
StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, SuggEscapeToUseAsIdentifier,
|
ConstGenericWithoutBraces, ConstGenericWithoutBracesSugg, DocCommentOnParamType,
|
||||||
SuggRemoveComma, UseEqInstead,
|
DoubleColonInBound, ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg,
|
||||||
|
GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg, InInTypo,
|
||||||
|
IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, ParenthesesInForHead,
|
||||||
|
ParenthesesInForHeadSugg, PatternMethodParamWithoutBody, QuestionMarkInType,
|
||||||
|
QuestionMarkInTypeSugg, SelfParamNotFirst, StructLiteralBodyWithoutPath,
|
||||||
|
StructLiteralBodyWithoutPathSugg, SuggEscapeToUseAsIdentifier, SuggRemoveComma,
|
||||||
|
UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration,
|
||||||
|
UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::lexer::UnmatchedBrace;
|
use crate::lexer::UnmatchedBrace;
|
||||||
|
@ -22,10 +29,10 @@ use rustc_ast::{
|
||||||
};
|
};
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnostic};
|
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
Applicability, DiagnosticBuilder, DiagnosticMessage, Handler, MultiSpan, PResult,
|
fluent, Applicability, DiagnosticBuilder, DiagnosticMessage, Handler, MultiSpan, PResult,
|
||||||
};
|
};
|
||||||
|
use rustc_errors::{pluralize, Diagnostic, ErrorGuaranteed, IntoDiagnostic};
|
||||||
use rustc_span::source_map::Spanned;
|
use rustc_span::source_map::Spanned;
|
||||||
use rustc_span::symbol::{kw, sym, Ident};
|
use rustc_span::symbol::{kw, sym, Ident};
|
||||||
use rustc_span::{Span, SpanSnippetError, DUMMY_SP};
|
use rustc_span::{Span, SpanSnippetError, DUMMY_SP};
|
||||||
|
@ -35,9 +42,6 @@ use std::mem::take;
|
||||||
|
|
||||||
use crate::parser;
|
use crate::parser;
|
||||||
|
|
||||||
const TURBOFISH_SUGGESTION_STR: &str =
|
|
||||||
"use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments";
|
|
||||||
|
|
||||||
/// Creates a placeholder argument.
|
/// Creates a placeholder argument.
|
||||||
pub(super) fn dummy_arg(ident: Ident) -> Param {
|
pub(super) fn dummy_arg(ident: Ident) -> Param {
|
||||||
let pat = P(Pat {
|
let pat = P(Pat {
|
||||||
|
@ -846,18 +850,8 @@ impl<'a> Parser<'a> {
|
||||||
self.eat_to_tokens(end);
|
self.eat_to_tokens(end);
|
||||||
let span = lo.until(self.token.span);
|
let span = lo.until(self.token.span);
|
||||||
|
|
||||||
let total_num_of_gt = number_of_gt + number_of_shr * 2;
|
let num_extra_brackets = number_of_gt + number_of_shr * 2;
|
||||||
self.struct_span_err(
|
self.sess.emit_err(UnmatchedAngleBrackets { span, num_extra_brackets });
|
||||||
span,
|
|
||||||
&format!("unmatched angle bracket{}", pluralize!(total_num_of_gt)),
|
|
||||||
)
|
|
||||||
.span_suggestion(
|
|
||||||
span,
|
|
||||||
&format!("remove extra angle bracket{}", pluralize!(total_num_of_gt)),
|
|
||||||
"",
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
|
@ -886,19 +880,13 @@ impl<'a> Parser<'a> {
|
||||||
let args = AngleBracketedArgs { args, span }.into();
|
let args = AngleBracketedArgs { args, span }.into();
|
||||||
segment.args = args;
|
segment.args = args;
|
||||||
|
|
||||||
self.struct_span_err(
|
self.sess.emit_err(GenericParamsWithoutAngleBrackets {
|
||||||
span,
|
span,
|
||||||
"generic parameters without surrounding angle brackets",
|
sugg: GenericParamsWithoutAngleBracketsSugg {
|
||||||
)
|
left: span.shrink_to_lo(),
|
||||||
.multipart_suggestion(
|
right: trailing_span,
|
||||||
"surround the type parameters with angle brackets",
|
},
|
||||||
vec![
|
});
|
||||||
(span.shrink_to_lo(), "<".to_string()),
|
|
||||||
(trailing_span, ">".to_string()),
|
|
||||||
],
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
} else {
|
} else {
|
||||||
// This doesn't look like an invalid turbofish, can't recover parse state.
|
// This doesn't look like an invalid turbofish, can't recover parse state.
|
||||||
self.restore_snapshot(snapshot);
|
self.restore_snapshot(snapshot);
|
||||||
|
@ -935,7 +923,7 @@ impl<'a> Parser<'a> {
|
||||||
if self.eat(&token::Gt) {
|
if self.eat(&token::Gt) {
|
||||||
e.span_suggestion_verbose(
|
e.span_suggestion_verbose(
|
||||||
binop.span.shrink_to_lo(),
|
binop.span.shrink_to_lo(),
|
||||||
TURBOFISH_SUGGESTION_STR,
|
fluent::parser::sugg_turbofish_syntax,
|
||||||
"::",
|
"::",
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
)
|
)
|
||||||
|
@ -967,7 +955,7 @@ impl<'a> Parser<'a> {
|
||||||
/// parenthesising the leftmost comparison.
|
/// parenthesising the leftmost comparison.
|
||||||
fn attempt_chained_comparison_suggestion(
|
fn attempt_chained_comparison_suggestion(
|
||||||
&mut self,
|
&mut self,
|
||||||
err: &mut Diagnostic,
|
err: &mut ComparisonOperatorsCannotBeChained,
|
||||||
inner_op: &Expr,
|
inner_op: &Expr,
|
||||||
outer_op: &Spanned<AssocOp>,
|
outer_op: &Spanned<AssocOp>,
|
||||||
) -> bool /* advanced the cursor */ {
|
) -> bool /* advanced the cursor */ {
|
||||||
|
@ -980,16 +968,6 @@ impl<'a> Parser<'a> {
|
||||||
// suggestion being the only one to apply is high.
|
// suggestion being the only one to apply is high.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let mut enclose = |left: Span, right: Span| {
|
|
||||||
err.multipart_suggestion(
|
|
||||||
"parenthesize the comparison",
|
|
||||||
vec![
|
|
||||||
(left.shrink_to_lo(), "(".to_string()),
|
|
||||||
(right.shrink_to_hi(), ")".to_string()),
|
|
||||||
],
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
return match (op.node, &outer_op.node) {
|
return match (op.node, &outer_op.node) {
|
||||||
// `x == y == z`
|
// `x == y == z`
|
||||||
(BinOpKind::Eq, AssocOp::Equal) |
|
(BinOpKind::Eq, AssocOp::Equal) |
|
||||||
|
@ -1003,12 +981,10 @@ impl<'a> Parser<'a> {
|
||||||
self.span_to_snippet(e.span)
|
self.span_to_snippet(e.span)
|
||||||
.unwrap_or_else(|_| pprust::expr_to_string(&e))
|
.unwrap_or_else(|_| pprust::expr_to_string(&e))
|
||||||
};
|
};
|
||||||
err.span_suggestion_verbose(
|
err.chaining_sugg = Some(ComparisonOperatorsCannotBeChainedSugg::SplitComparison {
|
||||||
inner_op.span.shrink_to_hi(),
|
span: inner_op.span.shrink_to_hi(),
|
||||||
"split the comparison into two",
|
middle_term: expr_to_str(&r1),
|
||||||
format!(" && {}", expr_to_str(&r1)),
|
});
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
|
||||||
false // Keep the current parse behavior, where the AST is `(x < y) < z`.
|
false // Keep the current parse behavior, where the AST is `(x < y) < z`.
|
||||||
}
|
}
|
||||||
// `x == y < z`
|
// `x == y < z`
|
||||||
|
@ -1019,7 +995,10 @@ impl<'a> Parser<'a> {
|
||||||
Ok(r2) => {
|
Ok(r2) => {
|
||||||
// We are sure that outer-op-rhs could be consumed, the suggestion is
|
// We are sure that outer-op-rhs could be consumed, the suggestion is
|
||||||
// likely correct.
|
// likely correct.
|
||||||
enclose(r1.span, r2.span);
|
err.chaining_sugg = Some(ComparisonOperatorsCannotBeChainedSugg::Parenthesize {
|
||||||
|
left: r1.span.shrink_to_lo(),
|
||||||
|
right: r2.span.shrink_to_hi(),
|
||||||
|
});
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
Err(expr_err) => {
|
Err(expr_err) => {
|
||||||
|
@ -1036,7 +1015,10 @@ impl<'a> Parser<'a> {
|
||||||
// further checks are necessary.
|
// further checks are necessary.
|
||||||
match self.parse_expr() {
|
match self.parse_expr() {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
enclose(l1.span, r1.span);
|
err.chaining_sugg = Some(ComparisonOperatorsCannotBeChainedSugg::Parenthesize {
|
||||||
|
left: l1.span.shrink_to_lo(),
|
||||||
|
right: r1.span.shrink_to_hi(),
|
||||||
|
});
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
Err(expr_err) => {
|
Err(expr_err) => {
|
||||||
|
@ -1085,18 +1067,11 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
match inner_op.kind {
|
match inner_op.kind {
|
||||||
ExprKind::Binary(op, ref l1, ref r1) if op.node.is_comparison() => {
|
ExprKind::Binary(op, ref l1, ref r1) if op.node.is_comparison() => {
|
||||||
let mut err = self.struct_span_err(
|
let mut err = ComparisonOperatorsCannotBeChained {
|
||||||
vec![op.span, self.prev_token.span],
|
span: vec![op.span, self.prev_token.span],
|
||||||
"comparison operators cannot be chained",
|
suggest_turbofish: None,
|
||||||
);
|
help_turbofish: None,
|
||||||
|
chaining_sugg: None,
|
||||||
let suggest = |err: &mut Diagnostic| {
|
|
||||||
err.span_suggestion_verbose(
|
|
||||||
op.span.shrink_to_lo(),
|
|
||||||
TURBOFISH_SUGGESTION_STR,
|
|
||||||
"::",
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Include `<` to provide this recommendation even in a case like
|
// Include `<` to provide this recommendation even in a case like
|
||||||
|
@ -1123,7 +1098,7 @@ impl<'a> Parser<'a> {
|
||||||
return if token::ModSep == self.token.kind {
|
return if token::ModSep == self.token.kind {
|
||||||
// We have some certainty that this was a bad turbofish at this point.
|
// We have some certainty that this was a bad turbofish at this point.
|
||||||
// `foo< bar >::`
|
// `foo< bar >::`
|
||||||
suggest(&mut err);
|
err.suggest_turbofish = Some(op.span.shrink_to_lo());
|
||||||
|
|
||||||
let snapshot = self.create_snapshot_for_diagnostic();
|
let snapshot = self.create_snapshot_for_diagnostic();
|
||||||
self.bump(); // `::`
|
self.bump(); // `::`
|
||||||
|
@ -1132,7 +1107,7 @@ impl<'a> Parser<'a> {
|
||||||
match self.parse_expr() {
|
match self.parse_expr() {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
// 99% certain that the suggestion is correct, continue parsing.
|
// 99% certain that the suggestion is correct, continue parsing.
|
||||||
err.emit();
|
self.sess.emit_err(err);
|
||||||
// FIXME: actually check that the two expressions in the binop are
|
// FIXME: actually check that the two expressions in the binop are
|
||||||
// paths and resynthesize new fn call expression instead of using
|
// paths and resynthesize new fn call expression instead of using
|
||||||
// `ExprKind::Err` placeholder.
|
// `ExprKind::Err` placeholder.
|
||||||
|
@ -1143,18 +1118,18 @@ impl<'a> Parser<'a> {
|
||||||
// Not entirely sure now, but we bubble the error up with the
|
// Not entirely sure now, but we bubble the error up with the
|
||||||
// suggestion.
|
// suggestion.
|
||||||
self.restore_snapshot(snapshot);
|
self.restore_snapshot(snapshot);
|
||||||
Err(err)
|
Err(err.into_diagnostic(&self.sess.span_diagnostic))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if token::OpenDelim(Delimiter::Parenthesis) == self.token.kind {
|
} else if token::OpenDelim(Delimiter::Parenthesis) == self.token.kind {
|
||||||
// We have high certainty that this was a bad turbofish at this point.
|
// We have high certainty that this was a bad turbofish at this point.
|
||||||
// `foo< bar >(`
|
// `foo< bar >(`
|
||||||
suggest(&mut err);
|
err.suggest_turbofish = Some(op.span.shrink_to_lo());
|
||||||
// Consume the fn call arguments.
|
// Consume the fn call arguments.
|
||||||
match self.consume_fn_args() {
|
match self.consume_fn_args() {
|
||||||
Err(()) => Err(err),
|
Err(()) => Err(err.into_diagnostic(&self.sess.span_diagnostic)),
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
err.emit();
|
self.sess.emit_err(err);
|
||||||
// FIXME: actually check that the two expressions in the binop are
|
// FIXME: actually check that the two expressions in the binop are
|
||||||
// paths and resynthesize new fn call expression instead of using
|
// paths and resynthesize new fn call expression instead of using
|
||||||
// `ExprKind::Err` placeholder.
|
// `ExprKind::Err` placeholder.
|
||||||
|
@ -1167,25 +1142,24 @@ impl<'a> Parser<'a> {
|
||||||
{
|
{
|
||||||
// All we know is that this is `foo < bar >` and *nothing* else. Try to
|
// All we know is that this is `foo < bar >` and *nothing* else. Try to
|
||||||
// be helpful, but don't attempt to recover.
|
// be helpful, but don't attempt to recover.
|
||||||
err.help(TURBOFISH_SUGGESTION_STR);
|
err.help_turbofish = Some(());
|
||||||
err.help("or use `(...)` if you meant to specify fn arguments");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it looks like a genuine attempt to chain operators (as opposed to a
|
// If it looks like a genuine attempt to chain operators (as opposed to a
|
||||||
// misformatted turbofish, for instance), suggest a correct form.
|
// misformatted turbofish, for instance), suggest a correct form.
|
||||||
if self.attempt_chained_comparison_suggestion(&mut err, inner_op, outer_op)
|
if self.attempt_chained_comparison_suggestion(&mut err, inner_op, outer_op)
|
||||||
{
|
{
|
||||||
err.emit();
|
self.sess.emit_err(err);
|
||||||
mk_err_expr(self, inner_op.span.to(self.prev_token.span))
|
mk_err_expr(self, inner_op.span.to(self.prev_token.span))
|
||||||
} else {
|
} else {
|
||||||
// These cases cause too many knock-down errors, bail out (#61329).
|
// These cases cause too many knock-down errors, bail out (#61329).
|
||||||
Err(err)
|
Err(err.into_diagnostic(&self.sess.span_diagnostic))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
let recover =
|
let recover =
|
||||||
self.attempt_chained_comparison_suggestion(&mut err, inner_op, outer_op);
|
self.attempt_chained_comparison_suggestion(&mut err, inner_op, outer_op);
|
||||||
err.emit();
|
self.sess.emit_err(err);
|
||||||
if recover {
|
if recover {
|
||||||
return mk_err_expr(self, inner_op.span.to(self.prev_token.span));
|
return mk_err_expr(self, inner_op.span.to(self.prev_token.span));
|
||||||
}
|
}
|
||||||
|
@ -1226,17 +1200,13 @@ impl<'a> Parser<'a> {
|
||||||
pub(super) fn maybe_recover_from_question_mark(&mut self, ty: P<Ty>) -> P<Ty> {
|
pub(super) fn maybe_recover_from_question_mark(&mut self, ty: P<Ty>) -> P<Ty> {
|
||||||
if self.token == token::Question {
|
if self.token == token::Question {
|
||||||
self.bump();
|
self.bump();
|
||||||
self.struct_span_err(self.prev_token.span, "invalid `?` in type")
|
self.sess.emit_err(QuestionMarkInType {
|
||||||
.span_label(self.prev_token.span, "`?` is only allowed on expressions, not types")
|
span: self.prev_token.span,
|
||||||
.multipart_suggestion(
|
sugg: QuestionMarkInTypeSugg {
|
||||||
"if you meant to express that the type might not contain a value, use the `Option` wrapper type",
|
left: ty.span.shrink_to_lo(),
|
||||||
vec![
|
right: self.prev_token.span,
|
||||||
(ty.span.shrink_to_lo(), "Option<".to_string()),
|
},
|
||||||
(self.prev_token.span, ">".to_string()),
|
});
|
||||||
],
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
self.mk_ty(ty.span.to(self.prev_token.span), TyKind::Err)
|
self.mk_ty(ty.span.to(self.prev_token.span), TyKind::Err)
|
||||||
} else {
|
} else {
|
||||||
ty
|
ty
|
||||||
|
@ -1660,19 +1630,16 @@ impl<'a> Parser<'a> {
|
||||||
(token::CloseDelim(Delimiter::Parenthesis), Some(begin_par_sp)) => {
|
(token::CloseDelim(Delimiter::Parenthesis), Some(begin_par_sp)) => {
|
||||||
self.bump();
|
self.bump();
|
||||||
|
|
||||||
self.struct_span_err(
|
self.sess.emit_err(ParenthesesInForHead {
|
||||||
MultiSpan::from_spans(vec![begin_par_sp, self.prev_token.span]),
|
span: vec![begin_par_sp, self.prev_token.span],
|
||||||
"unexpected parentheses surrounding `for` loop head",
|
|
||||||
)
|
|
||||||
.multipart_suggestion(
|
|
||||||
"remove parentheses in `for` loop",
|
|
||||||
vec![(begin_par_sp, String::new()), (self.prev_token.span, String::new())],
|
|
||||||
// With e.g. `for (x) in y)` this would replace `(x) in y)`
|
// With e.g. `for (x) in y)` this would replace `(x) in y)`
|
||||||
// with `x) in y)` which is syntactically invalid.
|
// with `x) in y)` which is syntactically invalid.
|
||||||
// However, this is prevented before we get here.
|
// However, this is prevented before we get here.
|
||||||
Applicability::MachineApplicable,
|
sugg: ParenthesesInForHeadSugg {
|
||||||
)
|
left: begin_par_sp,
|
||||||
.emit();
|
right: self.prev_token.span,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
// Unwrap `(pat)` into `pat` to avoid the `unused_parens` lint.
|
// Unwrap `(pat)` into `pat` to avoid the `unused_parens` lint.
|
||||||
pat.and_then(|pat| match pat.kind {
|
pat.and_then(|pat| match pat.kind {
|
||||||
|
@ -1891,12 +1858,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
pub(super) fn eat_incorrect_doc_comment_for_param_type(&mut self) {
|
pub(super) fn eat_incorrect_doc_comment_for_param_type(&mut self) {
|
||||||
if let token::DocComment(..) = self.token.kind {
|
if let token::DocComment(..) = self.token.kind {
|
||||||
self.struct_span_err(
|
self.sess.emit_err(DocCommentOnParamType { span: self.token.span });
|
||||||
self.token.span,
|
|
||||||
"documentation comments cannot be applied to a function parameter's type",
|
|
||||||
)
|
|
||||||
.span_label(self.token.span, "doc comments are not allowed here")
|
|
||||||
.emit();
|
|
||||||
self.bump();
|
self.bump();
|
||||||
} else if self.token == token::Pound
|
} else if self.token == token::Pound
|
||||||
&& self.look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Bracket))
|
&& self.look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Bracket))
|
||||||
|
@ -1908,9 +1870,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
let sp = lo.to(self.token.span);
|
let sp = lo.to(self.token.span);
|
||||||
self.bump();
|
self.bump();
|
||||||
self.struct_span_err(sp, "attributes cannot be applied to a function parameter's type")
|
self.sess.emit_err(AttributeOnParamType { span: sp });
|
||||||
.span_label(sp, "attributes are not allowed here")
|
|
||||||
.emit();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2031,19 +1991,7 @@ impl<'a> Parser<'a> {
|
||||||
self.expect(&token::Colon)?;
|
self.expect(&token::Colon)?;
|
||||||
let ty = self.parse_ty()?;
|
let ty = self.parse_ty()?;
|
||||||
|
|
||||||
struct_span_err!(
|
self.sess.emit_err(PatternMethodParamWithoutBody { span: pat.span });
|
||||||
self.diagnostic(),
|
|
||||||
pat.span,
|
|
||||||
E0642,
|
|
||||||
"patterns aren't allowed in methods without bodies",
|
|
||||||
)
|
|
||||||
.span_suggestion_short(
|
|
||||||
pat.span,
|
|
||||||
"give this argument a name or use an underscore to ignore it",
|
|
||||||
"_",
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
|
|
||||||
// Pretend the pattern is `_`, to avoid duplicate errors from AST validation.
|
// Pretend the pattern is `_`, to avoid duplicate errors from AST validation.
|
||||||
let pat =
|
let pat =
|
||||||
|
@ -2052,11 +2000,9 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn recover_bad_self_param(&mut self, mut param: Param) -> PResult<'a, Param> {
|
pub(super) fn recover_bad_self_param(&mut self, mut param: Param) -> PResult<'a, Param> {
|
||||||
let sp = param.pat.span;
|
let span = param.pat.span;
|
||||||
param.ty.kind = TyKind::Err;
|
param.ty.kind = TyKind::Err;
|
||||||
self.struct_span_err(sp, "unexpected `self` parameter in function")
|
self.sess.emit_err(SelfParamNotFirst { span });
|
||||||
.span_label(sp, "must be the first parameter of an associated function")
|
|
||||||
.emit();
|
|
||||||
Ok(param)
|
Ok(param)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2205,20 +2151,13 @@ impl<'a> Parser<'a> {
|
||||||
err
|
err
|
||||||
})?;
|
})?;
|
||||||
if !self.expr_is_valid_const_arg(&expr) {
|
if !self.expr_is_valid_const_arg(&expr) {
|
||||||
self.struct_span_err(
|
self.sess.emit_err(ConstGenericWithoutBraces {
|
||||||
expr.span,
|
span: expr.span,
|
||||||
"expressions must be enclosed in braces to be used as const generic \
|
sugg: ConstGenericWithoutBracesSugg {
|
||||||
arguments",
|
left: expr.span.shrink_to_lo(),
|
||||||
)
|
right: expr.span.shrink_to_hi(),
|
||||||
.multipart_suggestion(
|
},
|
||||||
"enclose the `const` expression in braces",
|
});
|
||||||
vec![
|
|
||||||
(expr.span.shrink_to_lo(), "{ ".to_string()),
|
|
||||||
(expr.span.shrink_to_hi(), " }".to_string()),
|
|
||||||
],
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
}
|
}
|
||||||
Ok(expr)
|
Ok(expr)
|
||||||
}
|
}
|
||||||
|
@ -2233,24 +2172,30 @@ impl<'a> Parser<'a> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut err =
|
|
||||||
self.struct_span_err(param.span(), "unexpected `const` parameter declaration");
|
let ident = param.ident.to_string();
|
||||||
err.span_label(param.span(), "expected a `const` expression, not a parameter declaration");
|
let sugg = match (ty_generics, self.sess.source_map().span_to_snippet(param.span())) {
|
||||||
if let (Some(generics), Ok(snippet)) =
|
(Some(Generics { params, span: impl_generics, .. }), Ok(snippet)) => {
|
||||||
(ty_generics, self.sess.source_map().span_to_snippet(param.span()))
|
Some(match ¶ms[..] {
|
||||||
{
|
[] => UnexpectedConstParamDeclarationSugg::AddParam {
|
||||||
let (span, sugg) = match &generics.params[..] {
|
impl_generics: *impl_generics,
|
||||||
[] => (generics.span, format!("<{snippet}>")),
|
incorrect_decl: param.span(),
|
||||||
[.., generic] => (generic.span().shrink_to_hi(), format!(", {snippet}")),
|
snippet,
|
||||||
};
|
ident,
|
||||||
err.multipart_suggestion(
|
},
|
||||||
"`const` parameters must be declared for the `impl`",
|
[.., generic] => UnexpectedConstParamDeclarationSugg::AppendParam {
|
||||||
vec![(span, sugg), (param.span(), param.ident.to_string())],
|
impl_generics_end: generic.span().shrink_to_hi(),
|
||||||
Applicability::MachineApplicable,
|
incorrect_decl: param.span(),
|
||||||
);
|
snippet,
|
||||||
}
|
ident,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
self.sess.emit_err(UnexpectedConstParamDeclaration { span: param.span(), sugg });
|
||||||
|
|
||||||
let value = self.mk_expr_err(param.span());
|
let value = self.mk_expr_err(param.span());
|
||||||
err.emit();
|
|
||||||
Some(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value }))
|
Some(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2268,20 +2213,15 @@ impl<'a> Parser<'a> {
|
||||||
self.bump(); // `const`
|
self.bump(); // `const`
|
||||||
|
|
||||||
// Detect and recover from the old, pre-RFC2000 syntax for const generics.
|
// Detect and recover from the old, pre-RFC2000 syntax for const generics.
|
||||||
let mut err = self
|
let mut err = UnexpectedConstInGenericParam { span: start, to_remove: None };
|
||||||
.struct_span_err(start, "expected lifetime, type, or constant, found keyword `const`");
|
|
||||||
if self.check_const_arg() {
|
if self.check_const_arg() {
|
||||||
err.span_suggestion_verbose(
|
err.to_remove = Some(start.until(self.token.span));
|
||||||
start.until(self.token.span),
|
self.sess.emit_err(err);
|
||||||
"the `const` keyword is only needed in the definition of the type",
|
|
||||||
"",
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
|
||||||
err.emit();
|
|
||||||
Ok(Some(GenericArg::Const(self.parse_const_arg()?)))
|
Ok(Some(GenericArg::Const(self.parse_const_arg()?)))
|
||||||
} else {
|
} else {
|
||||||
let after_kw_const = self.token.span;
|
let after_kw_const = self.token.span;
|
||||||
self.recover_const_arg(after_kw_const, err).map(Some)
|
self.recover_const_arg(after_kw_const, err.into_diagnostic(&self.sess.span_diagnostic))
|
||||||
|
.map(Some)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2387,24 +2327,6 @@ impl<'a> Parser<'a> {
|
||||||
GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })
|
GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the diagnostics for the cases where `move async` is found.
|
|
||||||
///
|
|
||||||
/// `move_async_span` starts at the 'm' of the move keyword and ends with the 'c' of the async keyword
|
|
||||||
pub(super) fn incorrect_move_async_order_found(
|
|
||||||
&self,
|
|
||||||
move_async_span: Span,
|
|
||||||
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
|
||||||
let mut err =
|
|
||||||
self.struct_span_err(move_async_span, "the order of `move` and `async` is incorrect");
|
|
||||||
err.span_suggestion_verbose(
|
|
||||||
move_async_span,
|
|
||||||
"try switching the order",
|
|
||||||
"async move",
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
|
||||||
err
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Some special error handling for the "top-level" patterns in a match arm,
|
/// Some special error handling for the "top-level" patterns in a match arm,
|
||||||
/// `for` loop, `let`, &c. (in contrast to subpatterns within such).
|
/// `for` loop, `let`, &c. (in contrast to subpatterns within such).
|
||||||
pub(crate) fn maybe_recover_colon_colon_in_pat_typo(
|
pub(crate) fn maybe_recover_colon_colon_in_pat_typo(
|
||||||
|
@ -2600,17 +2522,11 @@ impl<'a> Parser<'a> {
|
||||||
let (a_span, b_span) = (a.span(), b.span());
|
let (a_span, b_span) = (a.span(), b.span());
|
||||||
let between_span = a_span.shrink_to_hi().to(b_span.shrink_to_lo());
|
let between_span = a_span.shrink_to_hi().to(b_span.shrink_to_lo());
|
||||||
if self.span_to_snippet(between_span).as_ref().map(|a| &a[..]) == Ok(":: ") {
|
if self.span_to_snippet(between_span).as_ref().map(|a| &a[..]) == Ok(":: ") {
|
||||||
let mut err = self.struct_span_err(
|
return Err(DoubleColonInBound {
|
||||||
path.span.shrink_to_hi(),
|
span: path.span.shrink_to_hi(),
|
||||||
"expected `:` followed by trait or lifetime",
|
between: between_span,
|
||||||
);
|
}
|
||||||
err.span_suggestion(
|
.into_diagnostic(&self.sess.span_diagnostic));
|
||||||
between_span,
|
|
||||||
"use single colon",
|
|
||||||
": ",
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
return Err(err);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,25 +6,26 @@ use super::{
|
||||||
SemiColonMode, SeqSep, TokenExpectType, TokenType, TrailingToken,
|
SemiColonMode, SeqSep, TokenExpectType, TokenType, TrailingToken,
|
||||||
};
|
};
|
||||||
use crate::errors::{
|
use crate::errors::{
|
||||||
ArrayBracketsInsteadOfSpaces, ArrayBracketsInsteadOfSpacesSugg, BinaryFloatLiteralNotSupported,
|
ArrayBracketsInsteadOfSpaces, ArrayBracketsInsteadOfSpacesSugg, AsyncMoveOrderIncorrect,
|
||||||
BracesForStructLiteral, CatchAfterTry, CommaAfterBaseStruct, ComparisonInterpretedAsGeneric,
|
BinaryFloatLiteralNotSupported, BracesForStructLiteral, CatchAfterTry, CommaAfterBaseStruct,
|
||||||
ComparisonOrShiftInterpretedAsGenericSugg, DoCatchSyntaxRemoved, DotDotDot, EqFieldInit,
|
ComparisonInterpretedAsGeneric, ComparisonOrShiftInterpretedAsGenericSugg,
|
||||||
ExpectedElseBlock, ExpectedExpressionFoundLet, FieldExpressionWithGeneric,
|
DoCatchSyntaxRemoved, DotDotDot, EqFieldInit, ExpectedElseBlock, ExpectedExpressionFoundLet,
|
||||||
FloatLiteralRequiresIntegerPart, FoundExprWouldBeStmt, HexadecimalFloatLiteralNotSupported,
|
FieldExpressionWithGeneric, FloatLiteralRequiresIntegerPart, FoundExprWouldBeStmt,
|
||||||
IfExpressionMissingCondition, IfExpressionMissingThenBlock, IfExpressionMissingThenBlockSub,
|
HexadecimalFloatLiteralNotSupported, IfExpressionMissingCondition,
|
||||||
IntLiteralTooLarge, InvalidBlockMacroSegment, InvalidComparisonOperator,
|
IfExpressionMissingThenBlock, IfExpressionMissingThenBlockSub, IntLiteralTooLarge,
|
||||||
InvalidComparisonOperatorSub, InvalidFloatLiteralSuffix, InvalidFloatLiteralWidth,
|
InvalidBlockMacroSegment, InvalidComparisonOperator, InvalidComparisonOperatorSub,
|
||||||
InvalidIntLiteralWidth, InvalidInterpolatedExpression, InvalidLiteralSuffix,
|
InvalidFloatLiteralSuffix, InvalidFloatLiteralWidth, InvalidIntLiteralWidth,
|
||||||
InvalidLiteralSuffixOnTupleIndex, InvalidLogicalOperator, InvalidLogicalOperatorSub,
|
InvalidInterpolatedExpression, InvalidLiteralSuffix, InvalidLiteralSuffixOnTupleIndex,
|
||||||
InvalidNumLiteralBasePrefix, InvalidNumLiteralSuffix, LabeledLoopInBreak,
|
InvalidLogicalOperator, InvalidLogicalOperatorSub, InvalidNumLiteralBasePrefix,
|
||||||
LeadingPlusNotSupported, LeftArrowOperator, LifetimeInBorrowExpression,
|
InvalidNumLiteralSuffix, LabeledLoopInBreak, LeadingPlusNotSupported, LeftArrowOperator,
|
||||||
MacroInvocationWithQualifiedPath, MalformedLoopLabel, MatchArmBodyWithoutBraces,
|
LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath, MalformedLoopLabel,
|
||||||
MatchArmBodyWithoutBracesSugg, MissingCommaAfterMatchArm, MissingInInForLoop,
|
MatchArmBodyWithoutBraces, MatchArmBodyWithoutBracesSugg, MissingCommaAfterMatchArm,
|
||||||
MissingInInForLoopSub, MissingSemicolonBeforeArray, NoFieldsForFnCall, NotAsNegationOperator,
|
MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray, NoFieldsForFnCall,
|
||||||
NotAsNegationOperatorSub, OctalFloatLiteralNotSupported, OuterAttributeNotAllowedOnIfElse,
|
NotAsNegationOperator, NotAsNegationOperatorSub, OctalFloatLiteralNotSupported,
|
||||||
ParenthesesWithStructFields, RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric,
|
OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields,
|
||||||
StructLiteralNotAllowedHere, StructLiteralNotAllowedHereSugg, TildeAsUnaryOperator,
|
RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, StructLiteralNotAllowedHere,
|
||||||
UnexpectedTokenAfterLabel, UnexpectedTokenAfterLabelSugg, WrapExpressionInParentheses,
|
StructLiteralNotAllowedHereSugg, TildeAsUnaryOperator, UnexpectedTokenAfterLabel,
|
||||||
|
UnexpectedTokenAfterLabelSugg, WrapExpressionInParentheses,
|
||||||
};
|
};
|
||||||
use crate::maybe_recover_from_interpolated_ty_qpath;
|
use crate::maybe_recover_from_interpolated_ty_qpath;
|
||||||
|
|
||||||
|
@ -2087,7 +2088,8 @@ impl<'a> Parser<'a> {
|
||||||
// Check for `move async` and recover
|
// Check for `move async` and recover
|
||||||
if self.check_keyword(kw::Async) {
|
if self.check_keyword(kw::Async) {
|
||||||
let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo);
|
let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo);
|
||||||
Err(self.incorrect_move_async_order_found(move_async_span))
|
Err(AsyncMoveOrderIncorrect { span: move_async_span }
|
||||||
|
.into_diagnostic(&self.sess.span_diagnostic))
|
||||||
} else {
|
} else {
|
||||||
Ok(CaptureBy::Value)
|
Ok(CaptureBy::Value)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue