Migrate diagnostics in parser/expr to SessionDiagnostic
This commit is contained in:
parent
4b695f7c4e
commit
ffcaa0dee2
@ -41,3 +41,112 @@ parser_switch_mut_let_order =
|
||||
parser_missing_let_before_mut = missing keyword
|
||||
parser_use_let_not_auto = write `let` instead of `auto` to introduce a new variable
|
||||
parser_use_let_not_var = write `let` instead of `var` to introduce a new variable
|
||||
|
||||
parser_invalid_comparison_operator = invalid comparison operator `{$invalid}`
|
||||
.use_instead = `{$invalid}` is not a valid comparison operator, use `{$correct}`
|
||||
.spaceship_operator_invalid = `<=>` is not a valid comparison operator, use `std::cmp::Ordering`
|
||||
|
||||
parser_invalid_logical_operator = `{$incorrect}` is not a logical operator
|
||||
.note = unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
.use_amp_amp_for_conjunction = use `&&` to perform logical conjunction
|
||||
.use_pipe_pipe_for_disjunction = use `||` to perform logical disjunction
|
||||
|
||||
parser_tilde_is_not_unary_operator = `~` cannot be used as a unary operator
|
||||
.suggestion = use `!` to perform bitwise not
|
||||
|
||||
parser_unexpected_token_after_not = unexpected {$negated_desc} after identifier
|
||||
.suggestion = use `!` to perform logical negation
|
||||
|
||||
parser_malformed_loop_label = malformed loop label
|
||||
.suggestion = use the correct loop label format
|
||||
|
||||
parser_lifetime_in_borrow_expression = borrow expressions cannot be annotated with lifetimes
|
||||
.suggestion = remove the lifetime annotation
|
||||
.label = annotated with lifetime here
|
||||
|
||||
parser_field_expression_with_generic = field expressions cannot have generic arguments
|
||||
|
||||
parser_macro_invocation_with_qualified_path = macros cannot use qualified paths
|
||||
|
||||
parser_unexpected_token_after_label = expected `while`, `for`, `loop` or `{"{"}` after a label
|
||||
|
||||
parser_require_colon_after_labeled_expression = labeled expression must be followed by `:`
|
||||
.note = labels are used before loops and blocks, allowing e.g., `break 'label` to them
|
||||
.label = the label
|
||||
.suggestion = add `:` after the label
|
||||
|
||||
parser_do_catch_syntax_removed = found removed `do catch` syntax
|
||||
.note = following RFC #2388, the new non-placeholder syntax is `try`
|
||||
.suggestion = replace with the new syntax
|
||||
|
||||
parser_float_literal_requires_integer_part = float literals must have an integer part
|
||||
.suggestion = must have an integer part
|
||||
|
||||
parser_invalid_int_literal_width = invalid width `{$width}` for integer literal
|
||||
.help = valid widths are 8, 16, 32, 64 and 128
|
||||
|
||||
parser_invalid_num_literal_base_prefix = invalid base prefix for number literal
|
||||
.note = base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
|
||||
.suggestion = try making the prefix lowercase
|
||||
|
||||
parser_invalid_num_literal_suffix = invalid suffix `{$suffix}` for number literal
|
||||
.label = invalid suffix `{$suffix}`
|
||||
.help = the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
|
||||
|
||||
parser_invalid_float_literal_width = invalid width `{$width}` for float literal
|
||||
.help = valid widths are 32 and 64
|
||||
|
||||
parser_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal
|
||||
.label = invalid suffix `{$suffix}`
|
||||
.help = valid suffixes are `f32` and `f64`
|
||||
|
||||
parser_int_literal_too_large = integer literal is too large
|
||||
|
||||
parser_missing_semicolon_before_array = expected `;`, found `[`
|
||||
.suggestion = consider adding `;` here
|
||||
|
||||
parser_invalid_block_macro_segment = cannot use a `block` macro fragment here
|
||||
.label = the `block` fragment is within this context
|
||||
|
||||
parser_if_expression_missing_then_block = this `if` expression is missing a block after the condition
|
||||
.add_then_block = add a block here
|
||||
.condition_possibly_unfinished = this binary operation is possibly unfinished
|
||||
|
||||
parser_if_expression_missing_condition = missing condition for `if` expression
|
||||
.condition_label = expected condition here
|
||||
.block_label = if this block is the condition of the `if` expression, then it must be followed by another block
|
||||
|
||||
parser_expected_expression_found_let = expected expression, found `let` statement
|
||||
|
||||
parser_expected_else_block = expected `{"{"}`, found {$first_tok}
|
||||
.label = expected an `if` or a block after this `else`
|
||||
.suggestion = add an `if` if this is the condition of a chained `else if` statement
|
||||
|
||||
parser_outer_attribute_not_allowed_on_if_else = outer attributes are not allowed on `if` and `else` branches
|
||||
.branch_label = the attributes are attached to this branch
|
||||
.ctx_label = the branch belongs to this `{$ctx}`
|
||||
.suggestion = remove the attributes
|
||||
|
||||
parser_missing_in_in_for_loop = missing `in` in `for` loop
|
||||
.use_in_not_of = try using `in` here instead
|
||||
.add_in = try adding `in` here
|
||||
|
||||
parser_missing_comma_after_match_arm = expected `,` following `match` arm
|
||||
.suggestion = missing a comma here to end this `match` arm
|
||||
|
||||
parser_catch_after_try = keyword `catch` cannot follow a `try` block
|
||||
.help = try using `match` on the result of the `try` block instead
|
||||
|
||||
parser_comma_after_base_struct = cannot use a comma after the base struct
|
||||
.note = the base struct must always be the last field
|
||||
.suggestion = remove this comma
|
||||
|
||||
parser_eq_field_init = expected `:`, found `=`
|
||||
.suggestion = replace equals symbol with a colon
|
||||
|
||||
parser_dotdotdot = unexpected token: `...`
|
||||
.suggest_exclusive_range = use `..` for an exclusive range
|
||||
.suggest_inclusive_range = or `..=` for an inclusive range
|
||||
|
||||
parser_left_arrow_operator = unexpected token: `<-`
|
||||
.suggestion = if you meant to write a comparison against a negative value, add a space in between `<` and `-`
|
||||
|
@ -363,6 +363,349 @@ pub enum InvalidVariableDeclarationSub {
|
||||
UseLetNotVar(#[primary_span] Span),
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::invalid_comparison_operator)]
|
||||
pub(crate) struct InvalidComparisonOperator {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub invalid: String,
|
||||
#[subdiagnostic]
|
||||
pub sub: InvalidComparisonOperatorSub,
|
||||
}
|
||||
|
||||
#[derive(SessionSubdiagnostic)]
|
||||
pub(crate) enum InvalidComparisonOperatorSub {
|
||||
#[suggestion_short(
|
||||
parser::use_instead,
|
||||
applicability = "machine-applicable",
|
||||
code = "{correct}"
|
||||
)]
|
||||
Correctable {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
invalid: String,
|
||||
correct: String,
|
||||
},
|
||||
#[label(parser::spaceship_operator_invalid)]
|
||||
Spaceship(#[primary_span] Span),
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::invalid_logical_operator)]
|
||||
#[note]
|
||||
pub(crate) struct InvalidLogicalOperator {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub incorrect: String,
|
||||
#[subdiagnostic]
|
||||
pub sub: InvalidLogicalOperatorSub,
|
||||
}
|
||||
|
||||
#[derive(SessionSubdiagnostic)]
|
||||
pub(crate) enum InvalidLogicalOperatorSub {
|
||||
#[suggestion_short(
|
||||
parser::use_amp_amp_for_conjunction,
|
||||
applicability = "machine-applicable",
|
||||
code = "&&"
|
||||
)]
|
||||
Conjunction(#[primary_span] Span),
|
||||
#[suggestion_short(
|
||||
parser::use_pipe_pipe_for_disjunction,
|
||||
applicability = "machine-applicable",
|
||||
code = "||"
|
||||
)]
|
||||
Disjunction(#[primary_span] Span),
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::tilde_is_not_unary_operator)]
|
||||
pub(crate) struct TildeAsUnaryOperator(
|
||||
#[primary_span]
|
||||
#[suggestion_short(applicability = "machine-applicable", code = "!")]
|
||||
pub Span,
|
||||
);
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::unexpected_token_after_not)]
|
||||
pub(crate) struct NotAsNegationOperator {
|
||||
#[primary_span]
|
||||
pub negated: Span,
|
||||
pub negated_desc: String,
|
||||
#[suggestion_short(applicability = "machine-applicable", code = "!")]
|
||||
pub not: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::malformed_loop_label)]
|
||||
pub(crate) struct MalformedLoopLabel {
|
||||
#[primary_span]
|
||||
#[suggestion(applicability = "machine-applicable", code = "{correct_label}")]
|
||||
pub span: Span,
|
||||
pub correct_label: Ident,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::lifetime_in_borrow_expression)]
|
||||
pub(crate) struct LifetimeInBorrowExpression {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[suggestion(applicability = "machine-applicable", code = "")]
|
||||
#[label]
|
||||
pub lifetime_span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::field_expression_with_generic)]
|
||||
pub(crate) struct FieldExpressionWithGeneric(#[primary_span] pub Span);
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::macro_invocation_with_qualified_path)]
|
||||
pub(crate) struct MacroInvocationWithQualifiedPath(#[primary_span] pub Span);
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::unexpected_token_after_label)]
|
||||
pub(crate) struct UnexpectedTokenAfterLabel(
|
||||
#[primary_span]
|
||||
#[label(parser::unexpected_token_after_label)]
|
||||
pub Span,
|
||||
);
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::require_colon_after_labeled_expression)]
|
||||
#[note]
|
||||
pub(crate) struct RequireColonAfterLabeledExpression {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[label]
|
||||
pub label: Span,
|
||||
#[suggestion_short(applicability = "machine-applicable", code = ": ")]
|
||||
pub label_end: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::do_catch_syntax_removed)]
|
||||
#[note]
|
||||
pub(crate) struct DoCatchSyntaxRemoved {
|
||||
#[primary_span]
|
||||
#[suggestion(applicability = "machine-applicable", code = "try")]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::float_literal_requires_integer_part)]
|
||||
pub(crate) struct FloatLiteralRequiresIntegerPart {
|
||||
#[primary_span]
|
||||
#[suggestion(applicability = "machine-applicable", code = "{correct}")]
|
||||
pub span: Span,
|
||||
pub correct: String,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::invalid_int_literal_width)]
|
||||
#[help]
|
||||
pub(crate) struct InvalidIntLiteralWidth {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub width: String,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::invalid_num_literal_base_prefix)]
|
||||
#[note]
|
||||
pub(crate) struct InvalidNumLiteralBasePrefix {
|
||||
#[primary_span]
|
||||
#[suggestion(applicability = "maybe-incorrect", code = "{fixed}")]
|
||||
pub span: Span,
|
||||
pub fixed: String,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::invalid_num_literal_suffix)]
|
||||
#[help]
|
||||
pub(crate) struct InvalidNumLiteralSuffix {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub suffix: String,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::invalid_float_literal_width)]
|
||||
#[help]
|
||||
pub(crate) struct InvalidFloatLiteralWidth {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub width: String,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::invalid_float_literal_suffix)]
|
||||
#[help]
|
||||
pub(crate) struct InvalidFloatLiteralSuffix {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub suffix: String,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::int_literal_too_large)]
|
||||
pub(crate) struct IntLiteralTooLarge {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::missing_semicolon_before_array)]
|
||||
pub(crate) struct MissingSemicolonBeforeArray {
|
||||
#[primary_span]
|
||||
pub open_delim: Span,
|
||||
#[suggestion_verbose(applicability = "maybe-incorrect", code = ";")]
|
||||
pub semicolon: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::invalid_block_macro_segment)]
|
||||
pub(crate) struct InvalidBlockMacroSegment {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[label]
|
||||
pub context: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::if_expression_missing_then_block)]
|
||||
pub(crate) struct IfExpressionMissingThenBlock {
|
||||
#[primary_span]
|
||||
pub if_span: Span,
|
||||
#[subdiagnostic]
|
||||
pub sub: IfExpressionMissingThenBlockSub,
|
||||
}
|
||||
|
||||
#[derive(SessionSubdiagnostic)]
|
||||
pub(crate) enum IfExpressionMissingThenBlockSub {
|
||||
#[help(parser::condition_possibly_unfinished)]
|
||||
UnfinishedCondition(#[primary_span] Span),
|
||||
#[help(parser::add_then_block)]
|
||||
AddThenBlock(#[primary_span] Span),
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::if_expression_missing_condition)]
|
||||
pub(crate) struct IfExpressionMissingCondition {
|
||||
#[primary_span]
|
||||
#[label(parser::condition_label)]
|
||||
pub if_span: Span,
|
||||
#[label(parser::block_label)]
|
||||
pub block_span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::expected_expression_found_let)]
|
||||
pub(crate) struct ExpectedExpressionFoundLet {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::expected_else_block)]
|
||||
pub(crate) struct ExpectedElseBlock {
|
||||
#[primary_span]
|
||||
pub first_tok_span: Span,
|
||||
pub first_tok: String,
|
||||
#[label]
|
||||
pub else_span: Span,
|
||||
#[suggestion(applicability = "maybe-incorrect", code = "if ")]
|
||||
pub condition_start: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::outer_attribute_not_allowed_on_if_else)]
|
||||
pub(crate) struct OuterAttributeNotAllowedOnIfElse {
|
||||
#[primary_span]
|
||||
pub last: Span,
|
||||
|
||||
#[label(parser::branch_label)]
|
||||
pub branch_span: Span,
|
||||
|
||||
#[label(parser::ctx_label)]
|
||||
pub ctx_span: Span,
|
||||
pub ctx: String,
|
||||
|
||||
#[suggestion(applicability = "machine-applicable", code = "")]
|
||||
pub attributes: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::missing_in_in_for_loop)]
|
||||
pub(crate) struct MissingInInForLoop {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub sub: MissingInInForLoopSub,
|
||||
}
|
||||
|
||||
#[derive(SessionSubdiagnostic)]
|
||||
pub(crate) enum MissingInInForLoopSub {
|
||||
// Has been misleading, at least in the past (closed Issue #48492), thus maybe-incorrect
|
||||
#[suggestion_short(parser::use_in_not_of, applicability = "maybe-incorrect", code = "in")]
|
||||
InNotOf(#[primary_span] Span),
|
||||
#[suggestion_short(parser::add_in, applicability = "maybe-incorrect", code = " in ")]
|
||||
AddIn(#[primary_span] Span),
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::missing_comma_after_match_arm)]
|
||||
pub(crate) struct MissingCommaAfterMatchArm {
|
||||
#[primary_span]
|
||||
#[suggestion(applicability = "machine-applicable", code = ",")]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::catch_after_try)]
|
||||
#[help]
|
||||
pub(crate) struct CatchAfterTry {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::comma_after_base_struct)]
|
||||
#[note]
|
||||
pub(crate) struct CommaAfterBaseStruct {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[suggestion_short(applicability = "machine-applicable", code = "")]
|
||||
pub comma: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::eq_field_init)]
|
||||
pub(crate) struct EqFieldInit {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[suggestion(applicability = "machine-applicable", code = ":")]
|
||||
pub eq: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::dotdotdot)]
|
||||
pub(crate) struct DotDotDot {
|
||||
#[primary_span]
|
||||
#[suggestion(parser::suggest_exclusive_range, applicability = "maybe-incorrect", code = "..")]
|
||||
#[suggestion(parser::suggest_inclusive_range, applicability = "maybe-incorrect", code = "..=")]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::left_arrow_operator)]
|
||||
pub(crate) struct LeftArrowOperator {
|
||||
#[primary_span]
|
||||
#[suggestion(applicability = "maybe-incorrect", code = "< -")]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
// SnapshotParser is used to create a snapshot of the parser
|
||||
// without causing duplicate errors being emitted when the `Parser`
|
||||
// is dropped.
|
||||
|
@ -1,4 +1,14 @@
|
||||
use super::diagnostics::SnapshotParser;
|
||||
use super::diagnostics::{
|
||||
CatchAfterTry, CommaAfterBaseStruct, DoCatchSyntaxRemoved, DotDotDot, EqFieldInit,
|
||||
ExpectedElseBlock, ExpectedExpressionFoundLet, FieldExpressionWithGeneric,
|
||||
FloatLiteralRequiresIntegerPart, IfExpressionMissingCondition, IfExpressionMissingThenBlock,
|
||||
IfExpressionMissingThenBlockSub, InvalidBlockMacroSegment, InvalidComparisonOperator,
|
||||
InvalidComparisonOperatorSub, InvalidLogicalOperator, InvalidLogicalOperatorSub,
|
||||
LeftArrowOperator, LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath,
|
||||
MalformedLoopLabel, MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray,
|
||||
NotAsNegationOperator, OuterAttributeNotAllowedOnIfElse, RequireColonAfterLabeledExpression,
|
||||
SnapshotParser, TildeAsUnaryOperator, UnexpectedTokenAfterLabel,
|
||||
};
|
||||
use super::pat::{CommaRecoveryMode, RecoverColon, RecoverComma, PARAM_EXPECTED};
|
||||
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
|
||||
use super::{
|
||||
@ -6,6 +16,11 @@
|
||||
SemiColonMode, SeqSep, TokenExpectType, TokenType, TrailingToken,
|
||||
};
|
||||
use crate::maybe_recover_from_interpolated_ty_qpath;
|
||||
use crate::parser::diagnostics::{
|
||||
IntLiteralTooLarge, InvalidFloatLiteralSuffix, InvalidFloatLiteralWidth,
|
||||
InvalidIntLiteralWidth, InvalidNumLiteralBasePrefix, InvalidNumLiteralSuffix,
|
||||
MissingCommaAfterMatchArm,
|
||||
};
|
||||
|
||||
use core::mem;
|
||||
use rustc_ast::ptr::P;
|
||||
@ -20,9 +35,10 @@
|
||||
use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
|
||||
use rustc_ast::{ClosureBinder, StmtKind};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, PResult};
|
||||
use rustc_errors::{Applicability, Diagnostic, PResult};
|
||||
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
|
||||
use rustc_session::lint::BuiltinLintDiagnostics;
|
||||
use rustc_session::SessionDiagnostic;
|
||||
use rustc_span::source_map::{self, Span, Spanned};
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{BytePos, Pos};
|
||||
@ -216,15 +232,18 @@ pub(super) fn parse_assoc_expr_with(
|
||||
AssocOp::Equal => "==",
|
||||
AssocOp::NotEqual => "!=",
|
||||
_ => unreachable!(),
|
||||
};
|
||||
self.struct_span_err(sp, &format!("invalid comparison operator `{sugg}=`"))
|
||||
.span_suggestion_short(
|
||||
sp,
|
||||
&format!("`{s}=` is not a valid comparison operator, use `{s}`", s = sugg),
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
.into();
|
||||
let invalid = format!("{}=", &sugg);
|
||||
self.sess.emit_err(InvalidComparisonOperator {
|
||||
span: sp,
|
||||
invalid: invalid.clone(),
|
||||
sub: InvalidComparisonOperatorSub::Correctable {
|
||||
span: sp,
|
||||
invalid,
|
||||
correct: sugg,
|
||||
},
|
||||
});
|
||||
self.bump();
|
||||
}
|
||||
|
||||
@ -234,14 +253,15 @@ pub(super) fn parse_assoc_expr_with(
|
||||
&& self.prev_token.span.hi() == self.token.span.lo()
|
||||
{
|
||||
let sp = op.span.to(self.token.span);
|
||||
self.struct_span_err(sp, "invalid comparison operator `<>`")
|
||||
.span_suggestion_short(
|
||||
sp,
|
||||
"`<>` is not a valid comparison operator, use `!=`",
|
||||
"!=",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(InvalidComparisonOperator {
|
||||
span: sp,
|
||||
invalid: "<>".into(),
|
||||
sub: InvalidComparisonOperatorSub::Correctable {
|
||||
span: sp,
|
||||
invalid: "<>".into(),
|
||||
correct: "!=".into(),
|
||||
},
|
||||
});
|
||||
self.bump();
|
||||
}
|
||||
|
||||
@ -251,12 +271,11 @@ pub(super) fn parse_assoc_expr_with(
|
||||
&& self.prev_token.span.hi() == self.token.span.lo()
|
||||
{
|
||||
let sp = op.span.to(self.token.span);
|
||||
self.struct_span_err(sp, "invalid comparison operator `<=>`")
|
||||
.span_label(
|
||||
sp,
|
||||
"`<=>` is not a valid comparison operator, use `std::cmp::Ordering`",
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(InvalidComparisonOperator {
|
||||
span: sp,
|
||||
invalid: "<=>".into(),
|
||||
sub: InvalidComparisonOperatorSub::Spaceship(sp),
|
||||
});
|
||||
self.bump();
|
||||
}
|
||||
|
||||
@ -430,11 +449,19 @@ fn check_assoc_op(&self) -> Option<Spanned<AssocOp>> {
|
||||
}
|
||||
(Some(op), _) => (op, self.token.span),
|
||||
(None, Some((Ident { name: sym::and, span }, false))) => {
|
||||
self.error_bad_logical_op("and", "&&", "conjunction");
|
||||
self.sess.emit_err(InvalidLogicalOperator {
|
||||
span: self.token.span,
|
||||
incorrect: "and".into(),
|
||||
sub: InvalidLogicalOperatorSub::Conjunction(self.token.span),
|
||||
});
|
||||
(AssocOp::LAnd, span)
|
||||
}
|
||||
(None, Some((Ident { name: sym::or, span }, false))) => {
|
||||
self.error_bad_logical_op("or", "||", "disjunction");
|
||||
self.sess.emit_err(InvalidLogicalOperator {
|
||||
span: self.token.span,
|
||||
incorrect: "or".into(),
|
||||
sub: InvalidLogicalOperatorSub::Disjunction(self.token.span),
|
||||
});
|
||||
(AssocOp::LOr, span)
|
||||
}
|
||||
_ => return None,
|
||||
@ -442,19 +469,6 @@ fn check_assoc_op(&self) -> Option<Spanned<AssocOp>> {
|
||||
Some(source_map::respan(span, op))
|
||||
}
|
||||
|
||||
/// Error on `and` and `or` suggesting `&&` and `||` respectively.
|
||||
fn error_bad_logical_op(&self, bad: &str, good: &str, english: &str) {
|
||||
self.struct_span_err(self.token.span, &format!("`{bad}` is not a logical operator"))
|
||||
.span_suggestion_short(
|
||||
self.token.span,
|
||||
&format!("use `{good}` to perform logical {english}"),
|
||||
good,
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.note("unlike in e.g., python and PHP, `&&` and `||` are used for logical operators")
|
||||
.emit();
|
||||
}
|
||||
|
||||
/// Checks if this expression is a successfully parsed statement.
|
||||
fn expr_is_complete(&self, e: &Expr) -> bool {
|
||||
self.restrictions.contains(Restrictions::STMT_EXPR)
|
||||
@ -619,14 +633,7 @@ fn parse_unary_expr(&mut self, lo: Span, op: UnOp) -> PResult<'a, (Span, ExprKin
|
||||
|
||||
// Recover on `!` suggesting for bitwise negation instead.
|
||||
fn recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
|
||||
self.struct_span_err(lo, "`~` cannot be used as a unary operator")
|
||||
.span_suggestion_short(
|
||||
lo,
|
||||
"use `!` to perform bitwise not",
|
||||
"!",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(TildeAsUnaryOperator(lo));
|
||||
|
||||
self.parse_unary_expr(lo, UnOp::Not)
|
||||
}
|
||||
@ -652,20 +659,14 @@ fn is_mistaken_not_ident_negation(&self) -> bool {
|
||||
/// Recover on `not expr` in favor of `!expr`.
|
||||
fn recover_not_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
|
||||
// Emit the error...
|
||||
let not_token = self.look_ahead(1, |t| t.clone());
|
||||
self.struct_span_err(
|
||||
not_token.span,
|
||||
&format!("unexpected {} after identifier", super::token_descr(¬_token)),
|
||||
)
|
||||
.span_suggestion_short(
|
||||
let negated_token = self.look_ahead(1, |t| t.clone());
|
||||
self.sess.emit_err(NotAsNegationOperator {
|
||||
negated: negated_token.span,
|
||||
negated_desc: super::token_descr(&negated_token),
|
||||
// Span the `not` plus trailing whitespace to avoid
|
||||
// trailing whitespace after the `!` in our suggestion
|
||||
self.sess.source_map().span_until_non_whitespace(lo.to(not_token.span)),
|
||||
"use `!` to perform logical negation",
|
||||
"!",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
not: self.sess.source_map().span_until_non_whitespace(lo.to(negated_token.span)),
|
||||
});
|
||||
|
||||
// ...and recover!
|
||||
self.parse_unary_expr(lo, UnOp::Not)
|
||||
@ -725,14 +726,10 @@ fn parse_assoc_op_cast(
|
||||
match self.parse_labeled_expr(label, false) {
|
||||
Ok(expr) => {
|
||||
type_err.cancel();
|
||||
self.struct_span_err(label.ident.span, "malformed loop label")
|
||||
.span_suggestion(
|
||||
label.ident.span,
|
||||
"use the correct loop label format",
|
||||
label.ident,
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(MalformedLoopLabel {
|
||||
span: label.ident.span,
|
||||
correct_label: label.ident,
|
||||
});
|
||||
return Ok(expr);
|
||||
}
|
||||
Err(err) => {
|
||||
@ -910,15 +907,7 @@ fn parse_borrow_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
|
||||
}
|
||||
|
||||
fn error_remove_borrow_lifetime(&self, span: Span, lt_span: Span) {
|
||||
self.struct_span_err(span, "borrow expressions cannot be annotated with lifetimes")
|
||||
.span_label(lt_span, "annotated with lifetime here")
|
||||
.span_suggestion(
|
||||
lt_span,
|
||||
"remove the lifetime annotation",
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(LifetimeInBorrowExpression { span, lifetime_span: lt_span });
|
||||
}
|
||||
|
||||
/// Parse `mut?` or `raw [ const | mut ]`.
|
||||
@ -1272,11 +1261,7 @@ fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Exp
|
||||
} else {
|
||||
// Field access `expr.f`
|
||||
if let Some(args) = segment.args {
|
||||
self.struct_span_err(
|
||||
args.span(),
|
||||
"field expressions cannot have generic arguments",
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(FieldExpressionWithGeneric(args.span()));
|
||||
}
|
||||
|
||||
let span = lo.to(self.prev_token.span);
|
||||
@ -1489,7 +1474,7 @@ fn parse_path_start_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||
let (span, kind) = if self.eat(&token::Not) {
|
||||
// MACRO INVOCATION expression
|
||||
if qself.is_some() {
|
||||
self.struct_span_err(path.span, "macros cannot use qualified paths").emit();
|
||||
self.sess.emit_err(MacroInvocationWithQualifiedPath(path.span));
|
||||
}
|
||||
let lo = path.span;
|
||||
let mac = P(MacCall {
|
||||
@ -1535,11 +1520,11 @@ fn parse_labeled_expr(
|
||||
&& (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt))
|
||||
{
|
||||
// We're probably inside of a `Path<'a>` that needs a turbofish
|
||||
let msg = "expected `while`, `for`, `loop` or `{` after a label";
|
||||
self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit();
|
||||
self.sess.emit_err(UnexpectedTokenAfterLabel(self.token.span));
|
||||
consume_colon = false;
|
||||
Ok(self.mk_expr_err(lo))
|
||||
} else {
|
||||
// FIXME: use UnexpectedTokenAfterLabel, needs multipart suggestions
|
||||
let msg = "expected `while`, `for`, `loop` or `{` after a label";
|
||||
|
||||
let mut err = self.struct_span_err(self.token.span, msg);
|
||||
@ -1604,25 +1589,16 @@ fn visit_expr_post(&mut self, ex: &'ast Expr) {
|
||||
}?;
|
||||
|
||||
if !ate_colon && consume_colon {
|
||||
self.error_labeled_expr_must_be_followed_by_colon(lo, expr.span);
|
||||
self.sess.emit_err(RequireColonAfterLabeledExpression {
|
||||
span: expr.span,
|
||||
label: lo,
|
||||
label_end: lo.shrink_to_hi(),
|
||||
});
|
||||
}
|
||||
|
||||
Ok(expr)
|
||||
}
|
||||
|
||||
fn error_labeled_expr_must_be_followed_by_colon(&self, lo: Span, span: Span) {
|
||||
self.struct_span_err(span, "labeled expression must be followed by `:`")
|
||||
.span_label(lo, "the label")
|
||||
.span_suggestion_short(
|
||||
lo.shrink_to_hi(),
|
||||
"add `:` after the label",
|
||||
": ",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.note("labels are used before loops and blocks, allowing e.g., `break 'label` to them")
|
||||
.emit();
|
||||
}
|
||||
|
||||
/// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead.
|
||||
fn recover_do_catch(&mut self) -> PResult<'a, P<Expr>> {
|
||||
let lo = self.token.span;
|
||||
@ -1630,16 +1606,8 @@ fn recover_do_catch(&mut self) -> PResult<'a, P<Expr>> {
|
||||
self.bump(); // `do`
|
||||
self.bump(); // `catch`
|
||||
|
||||
let span_dc = lo.to(self.prev_token.span);
|
||||
self.struct_span_err(span_dc, "found removed `do catch` syntax")
|
||||
.span_suggestion(
|
||||
span_dc,
|
||||
"replace with the new syntax",
|
||||
"try",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.note("following RFC #2388, the new non-placeholder syntax is `try`")
|
||||
.emit();
|
||||
let span = lo.to(self.prev_token.span);
|
||||
self.sess.emit_err(DoCatchSyntaxRemoved { span });
|
||||
|
||||
self.parse_try_block(lo)
|
||||
}
|
||||
@ -1834,14 +1802,10 @@ pub(super) fn parse_opt_lit(&mut self) -> Option<Lit> {
|
||||
}
|
||||
|
||||
fn error_float_lits_must_have_int_part(&self, token: &Token) {
|
||||
self.struct_span_err(token.span, "float literals must have an integer part")
|
||||
.span_suggestion(
|
||||
token.span,
|
||||
"must have an integer part",
|
||||
pprust::token_to_string(token),
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(FloatLiteralRequiresIntegerPart {
|
||||
span: token.span,
|
||||
correct: pprust::token_to_string(token).into_owned(),
|
||||
});
|
||||
}
|
||||
|
||||
fn report_lit_error(&self, err: LitError, lit: token::Lit, span: Span) {
|
||||
@ -1883,28 +1847,11 @@ fn fix_base_capitalisation(s: &str) -> Option<String> {
|
||||
let suf = suf.as_str();
|
||||
if looks_like_width_suffix(&['i', 'u'], &suf) {
|
||||
// If it looks like a width, try to be helpful.
|
||||
let msg = format!("invalid width `{}` for integer literal", &suf[1..]);
|
||||
self.struct_span_err(span, &msg)
|
||||
.help("valid widths are 8, 16, 32, 64 and 128")
|
||||
.emit();
|
||||
self.sess.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() });
|
||||
} else if let Some(fixed) = fix_base_capitalisation(suf) {
|
||||
let msg = "invalid base prefix for number literal";
|
||||
|
||||
self.struct_span_err(span, msg)
|
||||
.note("base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase")
|
||||
.span_suggestion(
|
||||
span,
|
||||
"try making the prefix lowercase",
|
||||
fixed,
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(InvalidNumLiteralBasePrefix { span, fixed });
|
||||
} else {
|
||||
let msg = format!("invalid suffix `{suf}` for number literal");
|
||||
self.struct_span_err(span, &msg)
|
||||
.span_label(span, format!("invalid suffix `{suf}`"))
|
||||
.help("the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)")
|
||||
.emit();
|
||||
self.sess.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() });
|
||||
}
|
||||
}
|
||||
LitError::InvalidFloatSuffix => {
|
||||
@ -1912,14 +1859,10 @@ fn fix_base_capitalisation(s: &str) -> Option<String> {
|
||||
let suf = suf.as_str();
|
||||
if looks_like_width_suffix(&['f'], suf) {
|
||||
// If it looks like a width, try to be helpful.
|
||||
let msg = format!("invalid width `{}` for float literal", &suf[1..]);
|
||||
self.struct_span_err(span, &msg).help("valid widths are 32 and 64").emit();
|
||||
self.sess
|
||||
.emit_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() });
|
||||
} else {
|
||||
let msg = format!("invalid suffix `{suf}` for float literal");
|
||||
self.struct_span_err(span, &msg)
|
||||
.span_label(span, format!("invalid suffix `{suf}`"))
|
||||
.help("valid suffixes are `f32` and `f64`")
|
||||
.emit();
|
||||
self.sess.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() });
|
||||
}
|
||||
}
|
||||
LitError::NonDecimalFloat(base) => {
|
||||
@ -1934,7 +1877,7 @@ fn fix_base_capitalisation(s: &str) -> Option<String> {
|
||||
.emit();
|
||||
}
|
||||
LitError::IntTooLarge => {
|
||||
self.struct_span_err(span, "integer literal is too large").emit();
|
||||
self.sess.emit_err(IntLiteralTooLarge { span });
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2046,14 +1989,10 @@ fn suggest_missing_semicolon_before_array(
|
||||
.span_to_snippet(snapshot.token.span)
|
||||
.map_or(false, |snippet| snippet == "]") =>
|
||||
{
|
||||
let mut err = self.struct_span_err(open_delim_span, "expected `;`, found `[`");
|
||||
err.span_suggestion_verbose(
|
||||
prev_span.shrink_to_hi(),
|
||||
"consider adding `;` here",
|
||||
';',
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
return Err(err);
|
||||
return Err(MissingSemicolonBeforeArray {
|
||||
open_delim: open_delim_span,
|
||||
semicolon: prev_span.shrink_to_hi(),
|
||||
}.into_diagnostic(self.sess));
|
||||
}
|
||||
Ok(_) => (),
|
||||
Err(err) => err.cancel(),
|
||||
@ -2080,9 +2019,10 @@ pub(super) fn parse_block_expr(
|
||||
}
|
||||
|
||||
if self.token.is_whole_block() {
|
||||
self.struct_span_err(self.token.span, "cannot use a `block` macro fragment here")
|
||||
.span_label(lo.to(self.token.span), "the `block` fragment is within this context")
|
||||
.emit();
|
||||
self.sess.emit_err(InvalidBlockMacroSegment {
|
||||
span: self.token.span,
|
||||
context: lo.to(self.token.span),
|
||||
});
|
||||
}
|
||||
|
||||
let (attrs, blk) = self.parse_block_common(lo, blk_mode)?;
|
||||
@ -2252,11 +2192,19 @@ fn parse_if_after_cond(&mut self, lo: Span, mut cond: P<Expr>) -> PResult<'a, P<
|
||||
let block = match &mut cond.kind {
|
||||
ExprKind::Binary(Spanned { span: binop_span, .. }, _, right)
|
||||
if let ExprKind::Block(_, None) = right.kind => {
|
||||
this.error_missing_if_then_block(lo, cond_span.shrink_to_lo().to(*binop_span), true).emit();
|
||||
self.sess.emit_err(IfExpressionMissingThenBlock {
|
||||
if_span: lo,
|
||||
sub: IfExpressionMissingThenBlockSub::UnfinishedCondition(
|
||||
cond_span.shrink_to_lo().to(*binop_span)
|
||||
),
|
||||
});
|
||||
std::mem::replace(right, this.mk_expr_err(binop_span.shrink_to_hi()))
|
||||
},
|
||||
ExprKind::Block(_, None) => {
|
||||
this.error_missing_if_cond(lo, cond_span).emit();
|
||||
self.sess.emit_err(IfExpressionMissingCondition {
|
||||
if_span: self.sess.source_map().next_point(lo),
|
||||
block_span: self.sess.source_map().start_point(cond_span),
|
||||
});
|
||||
std::mem::replace(&mut cond, this.mk_expr_err(cond_span.shrink_to_hi()))
|
||||
}
|
||||
_ => {
|
||||
@ -2274,7 +2222,10 @@ fn parse_if_after_cond(&mut self, lo: Span, mut cond: P<Expr>) -> PResult<'a, P<
|
||||
if let Some(block) = recover_block_from_condition(self) {
|
||||
block
|
||||
} else {
|
||||
self.error_missing_if_then_block(lo, cond_span, false).emit();
|
||||
self.sess.emit_err(IfExpressionMissingThenBlock {
|
||||
if_span: lo,
|
||||
sub: IfExpressionMissingThenBlockSub::AddThenBlock(cond_span.shrink_to_hi()),
|
||||
});
|
||||
self.mk_block_err(cond_span.shrink_to_hi())
|
||||
}
|
||||
} else {
|
||||
@ -2302,39 +2253,6 @@ fn parse_if_after_cond(&mut self, lo: Span, mut cond: P<Expr>) -> PResult<'a, P<
|
||||
Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els)))
|
||||
}
|
||||
|
||||
fn error_missing_if_then_block(
|
||||
&self,
|
||||
if_span: Span,
|
||||
cond_span: Span,
|
||||
is_unfinished: bool,
|
||||
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
let mut err = self.struct_span_err(
|
||||
if_span,
|
||||
"this `if` expression is missing a block after the condition",
|
||||
);
|
||||
if is_unfinished {
|
||||
err.span_help(cond_span, "this binary operation is possibly unfinished");
|
||||
} else {
|
||||
err.span_help(cond_span.shrink_to_hi(), "add a block here");
|
||||
}
|
||||
err
|
||||
}
|
||||
|
||||
fn error_missing_if_cond(
|
||||
&self,
|
||||
lo: Span,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
let next_span = self.sess.source_map().next_point(lo);
|
||||
let mut err = self.struct_span_err(next_span, "missing condition for `if` expression");
|
||||
err.span_label(next_span, "expected condition here");
|
||||
err.span_label(
|
||||
self.sess.source_map().start_point(span),
|
||||
"if this block is the condition of the `if` expression, then it must be followed by another block"
|
||||
);
|
||||
err
|
||||
}
|
||||
|
||||
/// Parses the condition of a `if` or `while` expression.
|
||||
fn parse_cond_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||
self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, None)
|
||||
@ -2350,8 +2268,7 @@ fn parse_let_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||
TokenKind::AndAnd | TokenKind::Ident(kw::If, _) | TokenKind::Ident(kw::While, _)
|
||||
);
|
||||
if !self.restrictions.contains(Restrictions::ALLOW_LET) || not_in_chain {
|
||||
self.struct_span_err(self.token.span, "expected expression, found `let` statement")
|
||||
.emit();
|
||||
self.sess.emit_err(ExpectedExpressionFoundLet { span: self.token.span });
|
||||
}
|
||||
|
||||
self.bump(); // Eat `let` token
|
||||
@ -2389,15 +2306,12 @@ fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||
if self.check(&TokenKind::OpenDelim(Delimiter::Brace))
|
||||
&& classify::expr_requires_semi_to_be_stmt(&cond) =>
|
||||
{
|
||||
self.struct_span_err(first_tok_span, format!("expected `{{`, found {first_tok}"))
|
||||
.span_label(else_span, "expected an `if` or a block after this `else`")
|
||||
.span_suggestion(
|
||||
cond.span.shrink_to_lo(),
|
||||
"add an `if` if this is the condition of a chained `else if` statement",
|
||||
"if ",
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(ExpectedElseBlock {
|
||||
first_tok_span,
|
||||
first_tok,
|
||||
else_span,
|
||||
condition_start: cond.span.shrink_to_lo(),
|
||||
});
|
||||
self.parse_if_after_cond(cond.span.shrink_to_lo(), cond)?
|
||||
}
|
||||
Err(e) => {
|
||||
@ -2422,16 +2336,18 @@ fn error_on_if_block_attrs(
|
||||
branch_span: Span,
|
||||
attrs: &[ast::Attribute],
|
||||
) {
|
||||
let (span, last) = match attrs {
|
||||
let (attributes, last) = match attrs {
|
||||
[] => return,
|
||||
[x0 @ xn] | [x0, .., xn] => (x0.span.to(xn.span), xn.span),
|
||||
};
|
||||
let ctx = if is_ctx_else { "else" } else { "if" };
|
||||
self.struct_span_err(last, "outer attributes are not allowed on `if` and `else` branches")
|
||||
.span_label(branch_span, "the attributes are attached to this branch")
|
||||
.span_label(ctx_span, format!("the branch belongs to this `{ctx}`"))
|
||||
.span_suggestion(span, "remove the attributes", "", Applicability::MachineApplicable)
|
||||
.emit();
|
||||
self.sess.emit_err(OuterAttributeNotAllowedOnIfElse {
|
||||
last,
|
||||
branch_span,
|
||||
ctx_span,
|
||||
ctx: ctx.to_string(),
|
||||
attributes,
|
||||
});
|
||||
}
|
||||
|
||||
/// Parses `for <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten).
|
||||
@ -2465,23 +2381,16 @@ fn parse_for_expr(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a,
|
||||
}
|
||||
|
||||
fn error_missing_in_for_loop(&mut self) {
|
||||
let (span, msg, sugg) = if self.token.is_ident_named(sym::of) {
|
||||
let (span, sub): (_, fn(_) -> _) = if self.token.is_ident_named(sym::of) {
|
||||
// Possibly using JS syntax (#75311).
|
||||
let span = self.token.span;
|
||||
self.bump();
|
||||
(span, "try using `in` here instead", "in")
|
||||
(span, MissingInInForLoopSub::InNotOf)
|
||||
} else {
|
||||
(self.prev_token.span.between(self.token.span), "try adding `in` here", " in ")
|
||||
(self.prev_token.span.between(self.token.span), MissingInInForLoopSub::AddIn)
|
||||
};
|
||||
self.struct_span_err(span, "missing `in` in `for` loop")
|
||||
.span_suggestion_short(
|
||||
span,
|
||||
msg,
|
||||
sugg,
|
||||
// Has been misleading, at least in the past (closed Issue #48492).
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
|
||||
self.sess.emit_err(MissingInInForLoop { span, sub: sub(span) });
|
||||
}
|
||||
|
||||
/// Parses a `while` or `while let` expression (`while` token already eaten).
|
||||
@ -2787,17 +2696,9 @@ fn check_let_expr(expr: &Expr) -> bool {
|
||||
.is_ok();
|
||||
if pattern_follows && snapshot.check(&TokenKind::FatArrow) {
|
||||
err.cancel();
|
||||
this.struct_span_err(
|
||||
hi.shrink_to_hi(),
|
||||
"expected `,` following `match` arm",
|
||||
)
|
||||
.span_suggestion(
|
||||
hi.shrink_to_hi(),
|
||||
"missing a comma here to end this `match` arm",
|
||||
",",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
this.sess.emit_err(MissingCommaAfterMatchArm {
|
||||
span: hi.shrink_to_hi(),
|
||||
});
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
@ -2827,13 +2728,7 @@ fn check_let_expr(expr: &Expr) -> bool {
|
||||
fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P<Expr>> {
|
||||
let (attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
if self.eat_keyword(kw::Catch) {
|
||||
let mut error = self.struct_span_err(
|
||||
self.prev_token.span,
|
||||
"keyword `catch` cannot follow a `try` block",
|
||||
);
|
||||
error.help("try using `match` on the result of the `try` block instead");
|
||||
error.emit();
|
||||
Err(error)
|
||||
Err(CatchAfterTry { span: self.prev_token.span }.into_diagnostic(self.sess))
|
||||
} else {
|
||||
let span = span_lo.to(body.span);
|
||||
self.sess.gated_spans.gate(sym::try_blocks, span);
|
||||
@ -3082,18 +2977,10 @@ fn recover_struct_comma_after_dotdot(&mut self, span: Span) {
|
||||
if self.token != token::Comma {
|
||||
return;
|
||||
}
|
||||
self.struct_span_err(
|
||||
span.to(self.prev_token.span),
|
||||
"cannot use a comma after the base struct",
|
||||
)
|
||||
.span_suggestion_short(
|
||||
self.token.span,
|
||||
"remove this comma",
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.note("the base struct must always be the last field")
|
||||
.emit();
|
||||
self.sess.emit_err(CommaAfterBaseStruct {
|
||||
span: span.to(self.prev_token.span),
|
||||
comma: self.token.span,
|
||||
});
|
||||
self.recover_stmt();
|
||||
}
|
||||
|
||||
@ -3139,43 +3026,18 @@ fn error_on_eq_field_init(&self, field_name: Ident) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.struct_span_err(self.token.span, "expected `:`, found `=`")
|
||||
.span_suggestion(
|
||||
field_name.span.shrink_to_hi().to(self.token.span),
|
||||
"replace equals symbol with a colon",
|
||||
":",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(EqFieldInit {
|
||||
span: self.token.span,
|
||||
eq: field_name.span.shrink_to_hi().to(self.token.span),
|
||||
});
|
||||
}
|
||||
|
||||
fn err_dotdotdot_syntax(&self, span: Span) {
|
||||
self.struct_span_err(span, "unexpected token: `...`")
|
||||
.span_suggestion(
|
||||
span,
|
||||
"use `..` for an exclusive range",
|
||||
"..",
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.span_suggestion(
|
||||
span,
|
||||
"or `..=` for an inclusive range",
|
||||
"..=",
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(DotDotDot { span });
|
||||
}
|
||||
|
||||
fn err_larrow_operator(&self, span: Span) {
|
||||
self.struct_span_err(span, "unexpected token: `<-`")
|
||||
.span_suggestion(
|
||||
span,
|
||||
"if you meant to write a comparison against a negative value, add a \
|
||||
space in between `<` and `-`",
|
||||
"< -",
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(LeftArrowOperator { span });
|
||||
}
|
||||
|
||||
fn mk_assign_op(&self, binop: BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ExprKind {
|
||||
|
Loading…
Reference in New Issue
Block a user