mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-29 02:03:53 +00:00
Migrate more diagnostics in rustc_parse to diagnostic structs
This commit is contained in:
parent
4d02892acf
commit
ab7c7dc7ce
@ -71,6 +71,8 @@ parser_field_expression_with_generic = field expressions cannot have generic arg
|
|||||||
parser_macro_invocation_with_qualified_path = macros cannot use qualified paths
|
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_unexpected_token_after_label = expected `while`, `for`, `loop` or `{"{"}` after a label
|
||||||
|
.suggestion_remove_label = consider removing the label
|
||||||
|
.suggestion_enclose_in_block = consider enclosing expression in a block
|
||||||
|
|
||||||
parser_require_colon_after_labeled_expression = labeled expression must be followed by `:`
|
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
|
.note = labels are used before loops and blocks, allowing e.g., `break 'label` to them
|
||||||
@ -161,3 +163,62 @@ parser_use_eq_instead = unexpected `==`
|
|||||||
|
|
||||||
parser_use_empty_block_not_semi = expected { "`{}`" }, found `;`
|
parser_use_empty_block_not_semi = expected { "`{}`" }, found `;`
|
||||||
.suggestion = try using { "`{}`" } instead
|
.suggestion = try using { "`{}`" } instead
|
||||||
|
|
||||||
|
parser_comparison_interpreted_as_generic =
|
||||||
|
`<` is interpreted as a start of generic arguments for `{$typename}`, not a comparison
|
||||||
|
.label_args = interpreted as generic arguments
|
||||||
|
.label_comparison = not interpreted as comparison
|
||||||
|
.suggestion = try comparing the cast value
|
||||||
|
|
||||||
|
parser_shift_interpreted_as_generic =
|
||||||
|
`<<` is interpreted as a start of generic arguments for `{$typename}`, not a shift
|
||||||
|
.label_args = interpreted as generic arguments
|
||||||
|
.label_comparison = not interpreted as shift
|
||||||
|
.suggestion = try shifting the cast value
|
||||||
|
|
||||||
|
parser_found_expr_would_be_stmt = expected expression, found `{$token}`
|
||||||
|
.label = expected expression
|
||||||
|
|
||||||
|
parser_leading_plus_not_supported = leading `+` is not supported
|
||||||
|
.label = unexpected `+`
|
||||||
|
.suggestion_remove_plus = try removing the `+`
|
||||||
|
|
||||||
|
parser_parentheses_with_struct_fields = invalid `struct` delimiters or `fn` call arguments
|
||||||
|
.suggestion_braces_for_struct = if `{$name}` is a struct, use braces as delimiters
|
||||||
|
.suggestion_no_fields_for_fn = if `{$name}` is a function, use the arguments directly
|
||||||
|
|
||||||
|
parser_labeled_loop_in_break = parentheses are required around this expression to avoid confusion with a labeled break expression
|
||||||
|
.suggestion = wrap the expression in parentheses
|
||||||
|
|
||||||
|
parser_array_brackets_instead_of_braces = this is a block expression, not an array
|
||||||
|
.suggestion = to make an array, use square brackets instead of curly braces
|
||||||
|
|
||||||
|
parser_match_arm_body_without_braces = `match` arm body without braces
|
||||||
|
.label_statements = {$num_statements ->
|
||||||
|
[one] this statement is not surrounded by a body
|
||||||
|
*[other] these statements are not surrounded by a body
|
||||||
|
}
|
||||||
|
.label_arrow = while parsing the `match` arm starting here
|
||||||
|
.suggestion_add_braces = surround the {$num_statements ->
|
||||||
|
[one] statement
|
||||||
|
*[other] statements
|
||||||
|
} with a body
|
||||||
|
.suggestion_use_comma_not_semicolon = use a comma to end a `match` arm expression
|
||||||
|
|
||||||
|
parser_struct_literal_not_allowed_here = struct literals are not allowed here
|
||||||
|
.suggestion = surround the struct literal with parentheses
|
||||||
|
|
||||||
|
parser_invalid_interpolated_expression = invalid interpolated expression
|
||||||
|
|
||||||
|
parser_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported
|
||||||
|
parser_octal_float_literal_not_supported = octal float literal is not supported
|
||||||
|
parser_binary_float_literal_not_supported = binary float literal is not supported
|
||||||
|
parser_not_supported = not supported
|
||||||
|
|
||||||
|
parser_non_string_abi_literal = non-string ABI literal
|
||||||
|
.suggestion = specify the ABI with a string literal
|
||||||
|
|
||||||
|
parser_mismatched_closing_delimiter = mismatched closing delimiter: `{$delimiter}`
|
||||||
|
.label_unmatched = mismatched closing delimiter
|
||||||
|
.label_opening_candidate = closing delimiter possibly meant for this
|
||||||
|
.label_unclosed = unclosed delimiter
|
||||||
|
@ -21,6 +21,7 @@ use rustc_errors::{
|
|||||||
};
|
};
|
||||||
use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed};
|
use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed};
|
||||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||||
|
use rustc_session::errors::ExprParenthesesNeeded;
|
||||||
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};
|
||||||
@ -487,11 +488,24 @@ pub(crate) struct MacroInvocationWithQualifiedPath(#[primary_span] pub Span);
|
|||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(parser::unexpected_token_after_label)]
|
#[diag(parser::unexpected_token_after_label)]
|
||||||
pub(crate) struct UnexpectedTokenAfterLabel(
|
pub(crate) struct UnexpectedTokenAfterLabel {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label(parser::unexpected_token_after_label)]
|
#[label(parser::unexpected_token_after_label)]
|
||||||
pub Span,
|
pub span: Span,
|
||||||
);
|
#[suggestion_verbose(parser::suggestion_remove_label, code = "")]
|
||||||
|
pub remove_label: Option<Span>,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub enclose_in_block: Option<UnexpectedTokenAfterLabelSugg>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[multipart_suggestion(parser::suggestion_enclose_in_block, applicability = "machine-applicable")]
|
||||||
|
pub(crate) struct UnexpectedTokenAfterLabelSugg {
|
||||||
|
#[suggestion_part(code = "{{ ")]
|
||||||
|
pub left: Span,
|
||||||
|
#[suggestion_part(code = " }}")]
|
||||||
|
pub right: Span,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(parser::require_colon_after_labeled_expression)]
|
#[diag(parser::require_colon_after_labeled_expression)]
|
||||||
@ -753,6 +767,236 @@ pub(crate) struct UseEmptyBlockNotSemi {
|
|||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::comparison_interpreted_as_generic)]
|
||||||
|
pub(crate) struct ComparisonInterpretedAsGeneric {
|
||||||
|
#[primary_span]
|
||||||
|
#[label(parser::label_comparison)]
|
||||||
|
pub comparison: Span,
|
||||||
|
pub typename: String,
|
||||||
|
#[label(parser::label_args)]
|
||||||
|
pub args: Span,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub suggestion: ComparisonOrShiftInterpretedAsGenericSugg,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::shift_interpreted_as_generic)]
|
||||||
|
pub(crate) struct ShiftInterpretedAsGeneric {
|
||||||
|
#[primary_span]
|
||||||
|
#[label(parser::label_comparison)]
|
||||||
|
pub shift: Span,
|
||||||
|
pub typename: String,
|
||||||
|
#[label(parser::label_args)]
|
||||||
|
pub args: Span,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub suggestion: ComparisonOrShiftInterpretedAsGenericSugg,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")]
|
||||||
|
pub(crate) struct ComparisonOrShiftInterpretedAsGenericSugg {
|
||||||
|
#[suggestion_part(code = "(")]
|
||||||
|
pub left: Span,
|
||||||
|
#[suggestion_part(code = ")")]
|
||||||
|
pub right: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::found_expr_would_be_stmt)]
|
||||||
|
pub(crate) struct FoundExprWouldBeStmt {
|
||||||
|
#[primary_span]
|
||||||
|
#[label]
|
||||||
|
pub span: Span,
|
||||||
|
pub token: String,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub suggestion: ExprParenthesesNeeded,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::leading_plus_not_supported)]
|
||||||
|
pub(crate) struct LeadingPlusNotSupported {
|
||||||
|
#[primary_span]
|
||||||
|
#[label]
|
||||||
|
pub span: Span,
|
||||||
|
#[suggestion_verbose(
|
||||||
|
parser::suggestion_remove_plus,
|
||||||
|
code = "",
|
||||||
|
applicability = "machine-applicable"
|
||||||
|
)]
|
||||||
|
pub remove_plus: Option<Span>,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub add_parentheses: Option<ExprParenthesesNeeded>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::parentheses_with_struct_fields)]
|
||||||
|
pub(crate) struct ParenthesesWithStructFields {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub name: String,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub braces_for_struct: BracesForStructLiteral,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub no_fields_for_fn: NoFieldsForFnCall,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[multipart_suggestion(parser::suggestion_braces_for_struct, applicability = "maybe-incorrect")]
|
||||||
|
pub(crate) struct BracesForStructLiteral {
|
||||||
|
#[suggestion_part(code = " {{ ")]
|
||||||
|
pub first: Span,
|
||||||
|
#[suggestion_part(code = " }}")]
|
||||||
|
pub second: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[multipart_suggestion(parser::suggestion_no_fields_for_fn, applicability = "maybe-incorrect")]
|
||||||
|
pub(crate) struct NoFieldsForFnCall {
|
||||||
|
#[suggestion_part(code = "")]
|
||||||
|
pub fields: Vec<Span>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::labeled_loop_in_break)]
|
||||||
|
pub(crate) struct LabeledLoopInBreak {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub sub: LabeledLoopInBreakSub,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")]
|
||||||
|
pub(crate) struct LabeledLoopInBreakSub {
|
||||||
|
#[suggestion_part(code = "(")]
|
||||||
|
pub first: Span,
|
||||||
|
#[suggestion_part(code = ")")]
|
||||||
|
pub second: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::array_brackets_instead_of_braces)]
|
||||||
|
pub(crate) struct ArrayBracketsInsteadOfSpaces {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub sub: ArrayBracketsInsteadOfSpacesSugg,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[multipart_suggestion(parser::suggestion, applicability = "maybe-incorrect")]
|
||||||
|
pub(crate) struct ArrayBracketsInsteadOfSpacesSugg {
|
||||||
|
#[suggestion_part(code = "[")]
|
||||||
|
pub left: Span,
|
||||||
|
#[suggestion_part(code = "]")]
|
||||||
|
pub right: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::match_arm_body_without_braces)]
|
||||||
|
pub(crate) struct MatchArmBodyWithoutBraces {
|
||||||
|
#[primary_span]
|
||||||
|
#[label(parser::label_statements)]
|
||||||
|
pub statements: Span,
|
||||||
|
#[label(parser::label_arrow)]
|
||||||
|
pub arrow: Span,
|
||||||
|
pub num_statements: usize,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub sub: MatchArmBodyWithoutBracesSugg,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
pub(crate) enum MatchArmBodyWithoutBracesSugg {
|
||||||
|
#[multipart_suggestion(parser::suggestion_add_braces, applicability = "machine-applicable")]
|
||||||
|
AddBraces {
|
||||||
|
#[suggestion_part(code = "{{ ")]
|
||||||
|
left: Span,
|
||||||
|
#[suggestion_part(code = " }}")]
|
||||||
|
right: Span,
|
||||||
|
},
|
||||||
|
#[suggestion(
|
||||||
|
parser::suggestion_use_comma_not_semicolon,
|
||||||
|
code = ",",
|
||||||
|
applicability = "machine-applicable"
|
||||||
|
)]
|
||||||
|
UseComma {
|
||||||
|
#[primary_span]
|
||||||
|
semicolon: Span,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::struct_literal_not_allowed_here)]
|
||||||
|
pub(crate) struct StructLiteralNotAllowedHere {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub sub: StructLiteralNotAllowedHereSugg,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")]
|
||||||
|
pub(crate) struct StructLiteralNotAllowedHereSugg {
|
||||||
|
#[suggestion_part(code = "(")]
|
||||||
|
pub left: Span,
|
||||||
|
#[suggestion_part(code = ")")]
|
||||||
|
pub right: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::invalid_interpolated_expression)]
|
||||||
|
pub(crate) struct InvalidInterpolatedExpression {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::hexadecimal_float_literal_not_supported)]
|
||||||
|
pub(crate) struct HexadecimalFloatLiteralNotSupported {
|
||||||
|
#[primary_span]
|
||||||
|
#[label(parser::not_supported)]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::octal_float_literal_not_supported)]
|
||||||
|
pub(crate) struct OctalFloatLiteralNotSupported {
|
||||||
|
#[primary_span]
|
||||||
|
#[label(parser::not_supported)]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::binary_float_literal_not_supported)]
|
||||||
|
pub(crate) struct BinaryFloatLiteralNotSupported {
|
||||||
|
#[primary_span]
|
||||||
|
#[label(parser::not_supported)]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::non_string_abi_literal)]
|
||||||
|
pub(crate) struct NonStringAbiLiteral {
|
||||||
|
#[primary_span]
|
||||||
|
#[suggestion(code = "\"C\"", applicability = "maybe-incorrect")]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parser::mismatched_closing_delimiter)]
|
||||||
|
pub(crate) struct MismatchedClosingDelimiter {
|
||||||
|
#[primary_span]
|
||||||
|
pub spans: Vec<Span>,
|
||||||
|
pub delimiter: String,
|
||||||
|
#[label(parser::label_unmatched)]
|
||||||
|
pub unmatched: Span,
|
||||||
|
#[label(parser::label_opening_candidate)]
|
||||||
|
pub opening_candidate: Option<Span>,
|
||||||
|
#[label(parser::label_unclosed)]
|
||||||
|
pub unclosed: Option<Span>,
|
||||||
|
}
|
||||||
|
|
||||||
// SnapshotParser is used to create a snapshot of the parser
|
// SnapshotParser is used to create a snapshot of the parser
|
||||||
// without causing duplicate errors being emitted when the `Parser`
|
// without causing duplicate errors being emitted when the `Parser`
|
||||||
// is dropped.
|
// is dropped.
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
use super::diagnostics::{
|
use super::diagnostics::{
|
||||||
CatchAfterTry, CommaAfterBaseStruct, DoCatchSyntaxRemoved, DotDotDot, EqFieldInit,
|
ArrayBracketsInsteadOfSpaces, ArrayBracketsInsteadOfSpacesSugg, BracesForStructLiteral,
|
||||||
|
CatchAfterTry, CommaAfterBaseStruct, ComparisonInterpretedAsGeneric,
|
||||||
|
ComparisonOrShiftInterpretedAsGenericSugg, DoCatchSyntaxRemoved, DotDotDot, EqFieldInit,
|
||||||
ExpectedElseBlock, ExpectedExpressionFoundLet, FieldExpressionWithGeneric,
|
ExpectedElseBlock, ExpectedExpressionFoundLet, FieldExpressionWithGeneric,
|
||||||
FloatLiteralRequiresIntegerPart, IfExpressionMissingCondition, IfExpressionMissingThenBlock,
|
FloatLiteralRequiresIntegerPart, FoundExprWouldBeStmt, IfExpressionMissingCondition,
|
||||||
IfExpressionMissingThenBlockSub, InvalidBlockMacroSegment, InvalidComparisonOperator,
|
IfExpressionMissingThenBlock, IfExpressionMissingThenBlockSub, InvalidBlockMacroSegment,
|
||||||
InvalidComparisonOperatorSub, InvalidLogicalOperator, InvalidLogicalOperatorSub,
|
InvalidComparisonOperator, InvalidComparisonOperatorSub, InvalidInterpolatedExpression,
|
||||||
LeftArrowOperator, LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath,
|
InvalidLogicalOperator, InvalidLogicalOperatorSub, LabeledLoopInBreak, LeftArrowOperator,
|
||||||
MalformedLoopLabel, MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray,
|
LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath, MalformedLoopLabel,
|
||||||
NotAsNegationOperator, NotAsNegationOperatorSub, OuterAttributeNotAllowedOnIfElse,
|
MatchArmBodyWithoutBraces, MissingInInForLoop, MissingInInForLoopSub,
|
||||||
RequireColonAfterLabeledExpression, SnapshotParser, TildeAsUnaryOperator,
|
MissingSemicolonBeforeArray, NoFieldsForFnCall, NotAsNegationOperator,
|
||||||
UnexpectedTokenAfterLabel,
|
NotAsNegationOperatorSub, OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields,
|
||||||
|
RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, SnapshotParser,
|
||||||
|
StructLiteralNotAllowedHere, TildeAsUnaryOperator, UnexpectedTokenAfterLabel,
|
||||||
|
UnexpectedTokenAfterLabelSugg,
|
||||||
};
|
};
|
||||||
use super::pat::{CommaRecoveryMode, RecoverColon, RecoverComma, PARAM_EXPECTED};
|
use super::pat::{CommaRecoveryMode, RecoverColon, RecoverComma, PARAM_EXPECTED};
|
||||||
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
|
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
|
||||||
@ -18,9 +23,11 @@ use super::{
|
|||||||
};
|
};
|
||||||
use crate::maybe_recover_from_interpolated_ty_qpath;
|
use crate::maybe_recover_from_interpolated_ty_qpath;
|
||||||
use crate::parser::diagnostics::{
|
use crate::parser::diagnostics::{
|
||||||
IntLiteralTooLarge, InvalidFloatLiteralSuffix, InvalidFloatLiteralWidth,
|
BinaryFloatLiteralNotSupported, HexadecimalFloatLiteralNotSupported, IntLiteralTooLarge,
|
||||||
InvalidIntLiteralWidth, InvalidNumLiteralBasePrefix, InvalidNumLiteralSuffix,
|
InvalidFloatLiteralSuffix, InvalidFloatLiteralWidth, InvalidIntLiteralWidth,
|
||||||
MissingCommaAfterMatchArm,
|
InvalidNumLiteralBasePrefix, InvalidNumLiteralSuffix, LabeledLoopInBreakSub,
|
||||||
|
LeadingPlusNotSupported, MatchArmBodyWithoutBracesSugg, MissingCommaAfterMatchArm,
|
||||||
|
OctalFloatLiteralNotSupported, StructLiteralNotAllowedHereSugg,
|
||||||
};
|
};
|
||||||
|
|
||||||
use core::mem;
|
use core::mem;
|
||||||
@ -38,6 +45,7 @@ use rustc_ast::{ClosureBinder, StmtKind};
|
|||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_errors::IntoDiagnostic;
|
use rustc_errors::IntoDiagnostic;
|
||||||
use rustc_errors::{Applicability, Diagnostic, PResult};
|
use rustc_errors::{Applicability, Diagnostic, PResult};
|
||||||
|
use rustc_session::errors::ExprParenthesesNeeded;
|
||||||
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
|
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
|
||||||
use rustc_session::lint::BuiltinLintDiagnostics;
|
use rustc_session::lint::BuiltinLintDiagnostics;
|
||||||
use rustc_span::source_map::{self, Span, Spanned};
|
use rustc_span::source_map::{self, Span, Spanned};
|
||||||
@ -421,13 +429,12 @@ impl<'a> Parser<'a> {
|
|||||||
/// but the next token implies this should be parsed as an expression.
|
/// but the next token implies this should be parsed as an expression.
|
||||||
/// For example: `if let Some(x) = x { x } else { 0 } / 2`.
|
/// For example: `if let Some(x) = x { x } else { 0 } / 2`.
|
||||||
fn error_found_expr_would_be_stmt(&self, lhs: &Expr) {
|
fn error_found_expr_would_be_stmt(&self, lhs: &Expr) {
|
||||||
let mut err = self.struct_span_err(
|
self.sess.emit_err(FoundExprWouldBeStmt {
|
||||||
self.token.span,
|
span: self.token.span,
|
||||||
&format!("expected expression, found `{}`", pprust::token_to_string(&self.token),),
|
// FIXME(#100717)
|
||||||
);
|
token: pprust::token_to_string(&self.token).to_string(),
|
||||||
err.span_label(self.token.span, "expected expression");
|
suggestion: ExprParenthesesNeeded::surrounding(lhs.span),
|
||||||
self.sess.expr_parentheses_needed(&mut err, lhs.span);
|
});
|
||||||
err.emit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Possibly translate the current token to an associative operator.
|
/// Possibly translate the current token to an associative operator.
|
||||||
@ -578,21 +585,16 @@ impl<'a> Parser<'a> {
|
|||||||
make_it!(this, attrs, |this, _| this.parse_borrow_expr(lo))
|
make_it!(this, attrs, |this, _| this.parse_borrow_expr(lo))
|
||||||
}
|
}
|
||||||
token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => {
|
token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => {
|
||||||
let mut err = this.struct_span_err(lo, "leading `+` is not supported");
|
let mut err =
|
||||||
err.span_label(lo, "unexpected `+`");
|
LeadingPlusNotSupported { span: lo, remove_plus: None, add_parentheses: None };
|
||||||
|
|
||||||
// a block on the LHS might have been intended to be an expression instead
|
// a block on the LHS might have been intended to be an expression instead
|
||||||
if let Some(sp) = this.sess.ambiguous_block_expr_parse.borrow().get(&lo) {
|
if let Some(sp) = this.sess.ambiguous_block_expr_parse.borrow().get(&lo) {
|
||||||
this.sess.expr_parentheses_needed(&mut err, *sp);
|
err.add_parentheses = Some(ExprParenthesesNeeded::surrounding(*sp));
|
||||||
} else {
|
} else {
|
||||||
err.span_suggestion_verbose(
|
err.remove_plus = Some(lo);
|
||||||
lo,
|
|
||||||
"try removing the `+`",
|
|
||||||
"",
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
err.emit();
|
this.sess.emit_err(err);
|
||||||
|
|
||||||
this.bump();
|
this.bump();
|
||||||
this.parse_prefix_expr(None)
|
this.parse_prefix_expr(None)
|
||||||
@ -755,9 +757,33 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
match self.parse_path(PathStyle::Expr) {
|
match self.parse_path(PathStyle::Expr) {
|
||||||
Ok(path) => {
|
Ok(path) => {
|
||||||
let (op_noun, op_verb) = match self.token.kind {
|
let typename = pprust::path_to_string(&path);
|
||||||
token::Lt => ("comparison", "comparing"),
|
|
||||||
token::BinOp(token::Shl) => ("shift", "shifting"),
|
let span_after_type = parser_snapshot_after_type.token.span;
|
||||||
|
let expr =
|
||||||
|
mk_expr(self, lhs, self.mk_ty(path.span, TyKind::Path(None, path)));
|
||||||
|
|
||||||
|
let args_span = self.look_ahead(1, |t| t.span).to(span_after_type);
|
||||||
|
let suggestion = ComparisonOrShiftInterpretedAsGenericSugg {
|
||||||
|
left: expr.span.shrink_to_lo(),
|
||||||
|
right: expr.span.shrink_to_hi(),
|
||||||
|
};
|
||||||
|
|
||||||
|
match self.token.kind {
|
||||||
|
token::Lt => self.sess.emit_err(ComparisonInterpretedAsGeneric {
|
||||||
|
comparison: self.token.span,
|
||||||
|
typename,
|
||||||
|
args: args_span,
|
||||||
|
suggestion,
|
||||||
|
}),
|
||||||
|
token::BinOp(token::Shl) => {
|
||||||
|
self.sess.emit_err(ShiftInterpretedAsGeneric {
|
||||||
|
shift: self.token.span,
|
||||||
|
typename,
|
||||||
|
args: args_span,
|
||||||
|
suggestion,
|
||||||
|
})
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// We can end up here even without `<` being the next token, for
|
// We can end up here even without `<` being the next token, for
|
||||||
// example because `parse_ty_no_plus` returns `Err` on keywords,
|
// example because `parse_ty_no_plus` returns `Err` on keywords,
|
||||||
@ -771,33 +797,7 @@ impl<'a> Parser<'a> {
|
|||||||
// Successfully parsed the type path leaving a `<` yet to parse.
|
// Successfully parsed the type path leaving a `<` yet to parse.
|
||||||
type_err.cancel();
|
type_err.cancel();
|
||||||
|
|
||||||
// Report non-fatal diagnostics, keep `x as usize` as an expression
|
// Keep `x as usize` as an expression in AST and continue parsing.
|
||||||
// in AST and continue parsing.
|
|
||||||
let msg = format!(
|
|
||||||
"`<` is interpreted as a start of generic arguments for `{}`, not a {}",
|
|
||||||
pprust::path_to_string(&path),
|
|
||||||
op_noun,
|
|
||||||
);
|
|
||||||
let span_after_type = parser_snapshot_after_type.token.span;
|
|
||||||
let expr =
|
|
||||||
mk_expr(self, lhs, self.mk_ty(path.span, TyKind::Path(None, path)));
|
|
||||||
|
|
||||||
self.struct_span_err(self.token.span, &msg)
|
|
||||||
.span_label(
|
|
||||||
self.look_ahead(1, |t| t.span).to(span_after_type),
|
|
||||||
"interpreted as generic arguments",
|
|
||||||
)
|
|
||||||
.span_label(self.token.span, format!("not interpreted as {op_noun}"))
|
|
||||||
.multipart_suggestion(
|
|
||||||
&format!("try {op_verb} the cast value"),
|
|
||||||
vec![
|
|
||||||
(expr.span.shrink_to_lo(), "(".to_string()),
|
|
||||||
(expr.span.shrink_to_hi(), ")".to_string()),
|
|
||||||
],
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
|
|
||||||
expr
|
expr
|
||||||
}
|
}
|
||||||
Err(path_err) => {
|
Err(path_err) => {
|
||||||
@ -1208,29 +1208,25 @@ impl<'a> Parser<'a> {
|
|||||||
let close_paren = self.prev_token.span;
|
let close_paren = self.prev_token.span;
|
||||||
let span = lo.to(self.prev_token.span);
|
let span = lo.to(self.prev_token.span);
|
||||||
if !fields.is_empty() {
|
if !fields.is_empty() {
|
||||||
let replacement_err = self.struct_span_err(
|
let mut replacement_err = ParenthesesWithStructFields {
|
||||||
span,
|
span,
|
||||||
"invalid `struct` delimiters or `fn` call arguments",
|
name,
|
||||||
);
|
braces_for_struct: BracesForStructLiteral {
|
||||||
mem::replace(err, replacement_err).cancel();
|
first: open_paren,
|
||||||
|
second: close_paren,
|
||||||
|
},
|
||||||
|
no_fields_for_fn: NoFieldsForFnCall {
|
||||||
|
fields: fields
|
||||||
|
.into_iter()
|
||||||
|
.map(|field| field.span.until(field.expr.span))
|
||||||
|
.collect(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
.into_diagnostic(&self.sess.span_diagnostic);
|
||||||
|
replacement_err.emit();
|
||||||
|
|
||||||
err.multipart_suggestion(
|
let old_err = mem::replace(err, replacement_err);
|
||||||
&format!("if `{name}` is a struct, use braces as delimiters"),
|
old_err.cancel();
|
||||||
vec![
|
|
||||||
(open_paren, " { ".to_string()),
|
|
||||||
(close_paren, " }".to_string()),
|
|
||||||
],
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
|
||||||
err.multipart_suggestion(
|
|
||||||
&format!("if `{name}` is a function, use the arguments directly"),
|
|
||||||
fields
|
|
||||||
.into_iter()
|
|
||||||
.map(|field| (field.span.until(field.expr.span), String::new()))
|
|
||||||
.collect(),
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
|
||||||
err.emit();
|
|
||||||
} else {
|
} else {
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
@ -1537,15 +1533,19 @@ impl<'a> Parser<'a> {
|
|||||||
&& (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt))
|
&& (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt))
|
||||||
{
|
{
|
||||||
// We're probably inside of a `Path<'a>` that needs a turbofish
|
// We're probably inside of a `Path<'a>` that needs a turbofish
|
||||||
self.sess.emit_err(UnexpectedTokenAfterLabel(self.token.span));
|
self.sess.emit_err(UnexpectedTokenAfterLabel {
|
||||||
|
span: self.token.span,
|
||||||
|
remove_label: None,
|
||||||
|
enclose_in_block: None,
|
||||||
|
});
|
||||||
consume_colon = false;
|
consume_colon = false;
|
||||||
Ok(self.mk_expr_err(lo))
|
Ok(self.mk_expr_err(lo))
|
||||||
} else {
|
} else {
|
||||||
// FIXME: use UnexpectedTokenAfterLabel, needs multipart suggestions
|
let mut err = UnexpectedTokenAfterLabel {
|
||||||
let msg = "expected `while`, `for`, `loop` or `{` after a label";
|
span: self.token.span,
|
||||||
|
remove_label: None,
|
||||||
let mut err = self.struct_span_err(self.token.span, msg);
|
enclose_in_block: None,
|
||||||
err.span_label(self.token.span, msg);
|
};
|
||||||
|
|
||||||
// Continue as an expression in an effort to recover on `'label: non_block_expr`.
|
// Continue as an expression in an effort to recover on `'label: non_block_expr`.
|
||||||
let expr = self.parse_expr().map(|expr| {
|
let expr = self.parse_expr().map(|expr| {
|
||||||
@ -1572,28 +1572,15 @@ impl<'a> Parser<'a> {
|
|||||||
// If there are no breaks that may use this label, suggest removing the label and
|
// If there are no breaks that may use this label, suggest removing the label and
|
||||||
// recover to the unmodified expression.
|
// recover to the unmodified expression.
|
||||||
if !found_labeled_breaks {
|
if !found_labeled_breaks {
|
||||||
let msg = "consider removing the label";
|
err.remove_label = Some(lo.until(span));
|
||||||
err.span_suggestion_verbose(
|
|
||||||
lo.until(span),
|
|
||||||
msg,
|
|
||||||
"",
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
|
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
let sugg_msg = "consider enclosing expression in a block";
|
err.enclose_in_block = Some(UnexpectedTokenAfterLabelSugg {
|
||||||
let suggestions = vec![
|
left: span.shrink_to_lo(),
|
||||||
(span.shrink_to_lo(), "{ ".to_owned()),
|
right: span.shrink_to_hi(),
|
||||||
(span.shrink_to_hi(), " }".to_owned()),
|
});
|
||||||
];
|
|
||||||
|
|
||||||
err.multipart_suggestion_verbose(
|
|
||||||
sugg_msg,
|
|
||||||
suggestions,
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Replace `'label: non_block_expr` with `'label: {non_block_expr}` in order to suppress future errors about `break 'label`.
|
// Replace `'label: non_block_expr` with `'label: {non_block_expr}` in order to suppress future errors about `break 'label`.
|
||||||
let stmt = self.mk_stmt(span, StmtKind::Expr(expr));
|
let stmt = self.mk_stmt(span, StmtKind::Expr(expr));
|
||||||
@ -1601,7 +1588,7 @@ impl<'a> Parser<'a> {
|
|||||||
self.mk_expr(span, ExprKind::Block(blk, label))
|
self.mk_expr(span, ExprKind::Block(blk, label))
|
||||||
});
|
});
|
||||||
|
|
||||||
err.emit();
|
self.sess.emit_err(err);
|
||||||
expr
|
expr
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
@ -1672,19 +1659,13 @@ impl<'a> Parser<'a> {
|
|||||||
// The value expression can be a labeled loop, see issue #86948, e.g.:
|
// The value expression can be a labeled loop, see issue #86948, e.g.:
|
||||||
// `loop { break 'label: loop { break 'label 42; }; }`
|
// `loop { break 'label: loop { break 'label 42; }; }`
|
||||||
let lexpr = self.parse_labeled_expr(label.take().unwrap(), true)?;
|
let lexpr = self.parse_labeled_expr(label.take().unwrap(), true)?;
|
||||||
self.struct_span_err(
|
self.sess.emit_err(LabeledLoopInBreak {
|
||||||
lexpr.span,
|
span: lexpr.span,
|
||||||
"parentheses are required around this expression to avoid confusion with a labeled break expression",
|
sub: LabeledLoopInBreakSub {
|
||||||
)
|
first: lexpr.span.shrink_to_lo(),
|
||||||
.multipart_suggestion(
|
second: lexpr.span.shrink_to_hi(),
|
||||||
"wrap the expression in parentheses",
|
},
|
||||||
vec![
|
});
|
||||||
(lexpr.span.shrink_to_lo(), "(".to_string()),
|
|
||||||
(lexpr.span.shrink_to_hi(), ")".to_string()),
|
|
||||||
],
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
Some(lexpr)
|
Some(lexpr)
|
||||||
} else if self.token != token::OpenDelim(Delimiter::Brace)
|
} else if self.token != token::OpenDelim(Delimiter::Brace)
|
||||||
|| !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
|
|| !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
|
||||||
@ -1756,9 +1737,8 @@ impl<'a> Parser<'a> {
|
|||||||
};
|
};
|
||||||
if let Some(expr) = expr {
|
if let Some(expr) = expr {
|
||||||
if matches!(expr.kind, ExprKind::Err) {
|
if matches!(expr.kind, ExprKind::Err) {
|
||||||
let mut err = self
|
let mut err = InvalidInterpolatedExpression { span: self.token.span }
|
||||||
.diagnostic()
|
.into_diagnostic(&self.sess.span_diagnostic);
|
||||||
.struct_span_err(self.token.span, "invalid interpolated expression");
|
|
||||||
err.downgrade_to_delayed_bug();
|
err.downgrade_to_delayed_bug();
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -1790,7 +1770,10 @@ impl<'a> Parser<'a> {
|
|||||||
});
|
});
|
||||||
if let Some(token) = &recovered {
|
if let Some(token) = &recovered {
|
||||||
self.bump();
|
self.bump();
|
||||||
self.error_float_lits_must_have_int_part(&token);
|
self.sess.emit_err(FloatLiteralRequiresIntegerPart {
|
||||||
|
span: token.span,
|
||||||
|
correct: pprust::token_to_string(token).into_owned(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1818,13 +1801,6 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error_float_lits_must_have_int_part(&self, token: &Token) {
|
|
||||||
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) {
|
fn report_lit_error(&self, err: LitError, lit: token::Lit, span: Span) {
|
||||||
// Checks if `s` looks like i32 or u1234 etc.
|
// Checks if `s` looks like i32 or u1234 etc.
|
||||||
fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
|
fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
|
||||||
@ -1883,15 +1859,12 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
LitError::NonDecimalFloat(base) => {
|
LitError::NonDecimalFloat(base) => {
|
||||||
let descr = match base {
|
match base {
|
||||||
16 => "hexadecimal",
|
16 => self.sess.emit_err(HexadecimalFloatLiteralNotSupported { span }),
|
||||||
8 => "octal",
|
8 => self.sess.emit_err(OctalFloatLiteralNotSupported { span }),
|
||||||
2 => "binary",
|
2 => self.sess.emit_err(BinaryFloatLiteralNotSupported { span }),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
self.struct_span_err(span, &format!("{descr} float literal is not supported"))
|
|
||||||
.span_label(span, "not supported")
|
|
||||||
.emit();
|
|
||||||
}
|
}
|
||||||
LitError::IntTooLarge => {
|
LitError::IntTooLarge => {
|
||||||
self.sess.emit_err(IntLiteralTooLarge { span });
|
self.sess.emit_err(IntLiteralTooLarge { span });
|
||||||
@ -1964,14 +1937,13 @@ impl<'a> Parser<'a> {
|
|||||||
let mut snapshot = self.create_snapshot_for_diagnostic();
|
let mut snapshot = self.create_snapshot_for_diagnostic();
|
||||||
match snapshot.parse_array_or_repeat_expr(Delimiter::Brace) {
|
match snapshot.parse_array_or_repeat_expr(Delimiter::Brace) {
|
||||||
Ok(arr) => {
|
Ok(arr) => {
|
||||||
let hi = snapshot.prev_token.span;
|
self.sess.emit_err(ArrayBracketsInsteadOfSpaces {
|
||||||
self.struct_span_err(arr.span, "this is a block expression, not an array")
|
span: arr.span,
|
||||||
.multipart_suggestion(
|
sub: ArrayBracketsInsteadOfSpacesSugg {
|
||||||
"to make an array, use square brackets instead of curly braces",
|
left: lo,
|
||||||
vec![(lo, "[".to_owned()), (hi, "]".to_owned())],
|
right: snapshot.prev_token.span,
|
||||||
Applicability::MaybeIncorrect,
|
},
|
||||||
)
|
});
|
||||||
.emit();
|
|
||||||
|
|
||||||
self.restore_snapshot(snapshot);
|
self.restore_snapshot(snapshot);
|
||||||
Some(self.mk_expr_err(arr.span))
|
Some(self.mk_expr_err(arr.span))
|
||||||
@ -2515,39 +2487,22 @@ impl<'a> Parser<'a> {
|
|||||||
self.bump(); // `;`
|
self.bump(); // `;`
|
||||||
let mut stmts =
|
let mut stmts =
|
||||||
vec![self.mk_stmt(first_expr.span, ast::StmtKind::Expr(first_expr.clone()))];
|
vec![self.mk_stmt(first_expr.span, ast::StmtKind::Expr(first_expr.clone()))];
|
||||||
let err = |this: &mut Parser<'_>, stmts: Vec<ast::Stmt>| {
|
let err = |this: &Parser<'_>, stmts: Vec<ast::Stmt>| {
|
||||||
let span = stmts[0].span.to(stmts[stmts.len() - 1].span);
|
let span = stmts[0].span.to(stmts[stmts.len() - 1].span);
|
||||||
let mut err = this.struct_span_err(span, "`match` arm body without braces");
|
|
||||||
let (these, s, are) =
|
this.sess.emit_err(MatchArmBodyWithoutBraces {
|
||||||
if stmts.len() > 1 { ("these", "s", "are") } else { ("this", "", "is") };
|
statements: span,
|
||||||
err.span_label(
|
arrow: arrow_span,
|
||||||
span,
|
num_statements: stmts.len(),
|
||||||
&format!(
|
sub: if stmts.len() > 1 {
|
||||||
"{these} statement{s} {are} not surrounded by a body",
|
MatchArmBodyWithoutBracesSugg::AddBraces {
|
||||||
these = these,
|
left: span.shrink_to_lo(),
|
||||||
s = s,
|
right: span.shrink_to_hi(),
|
||||||
are = are
|
}
|
||||||
),
|
} else {
|
||||||
);
|
MatchArmBodyWithoutBracesSugg::UseComma { semicolon: semi_sp }
|
||||||
err.span_label(arrow_span, "while parsing the `match` arm starting here");
|
},
|
||||||
if stmts.len() > 1 {
|
});
|
||||||
err.multipart_suggestion(
|
|
||||||
&format!("surround the statement{s} with a body"),
|
|
||||||
vec![
|
|
||||||
(span.shrink_to_lo(), "{ ".to_string()),
|
|
||||||
(span.shrink_to_hi(), " }".to_string()),
|
|
||||||
],
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
err.span_suggestion(
|
|
||||||
semi_sp,
|
|
||||||
"use a comma to end a `match` arm expression",
|
|
||||||
",",
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
err.emit();
|
|
||||||
this.mk_expr_err(span)
|
this.mk_expr_err(span)
|
||||||
};
|
};
|
||||||
// We might have either a `,` -> `;` typo, or a block without braces. We need
|
// We might have either a `,` -> `;` typo, or a block without braces. We need
|
||||||
@ -2836,23 +2791,19 @@ impl<'a> Parser<'a> {
|
|||||||
let expr = self.parse_struct_expr(qself.cloned(), path.clone(), true);
|
let expr = self.parse_struct_expr(qself.cloned(), path.clone(), true);
|
||||||
if let (Ok(expr), false) = (&expr, struct_allowed) {
|
if let (Ok(expr), false) = (&expr, struct_allowed) {
|
||||||
// This is a struct literal, but we don't can't accept them here.
|
// This is a struct literal, but we don't can't accept them here.
|
||||||
self.error_struct_lit_not_allowed_here(path.span, expr.span);
|
self.sess.emit_err(StructLiteralNotAllowedHere {
|
||||||
|
span: expr.span,
|
||||||
|
sub: StructLiteralNotAllowedHereSugg {
|
||||||
|
left: path.span.shrink_to_lo(),
|
||||||
|
right: expr.span.shrink_to_hi(),
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return Some(expr);
|
return Some(expr);
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error_struct_lit_not_allowed_here(&self, lo: Span, sp: Span) {
|
|
||||||
self.struct_span_err(sp, "struct literals are not allowed here")
|
|
||||||
.multipart_suggestion(
|
|
||||||
"surround the struct literal with parentheses",
|
|
||||||
vec![(lo.shrink_to_lo(), "(".to_string()), (sp.shrink_to_hi(), ")".to_string())],
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn parse_struct_fields(
|
pub(super) fn parse_struct_fields(
|
||||||
&mut self,
|
&mut self,
|
||||||
pth: ast::Path,
|
pth: ast::Path,
|
||||||
|
@ -32,7 +32,8 @@ use rustc_ast_pretty::pprust;
|
|||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::PResult;
|
use rustc_errors::PResult;
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, MultiSpan,
|
struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, IntoDiagnostic,
|
||||||
|
MultiSpan,
|
||||||
};
|
};
|
||||||
use rustc_session::parse::ParseSess;
|
use rustc_session::parse::ParseSess;
|
||||||
use rustc_span::source_map::{Span, DUMMY_SP};
|
use rustc_span::source_map::{Span, DUMMY_SP};
|
||||||
@ -41,6 +42,8 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
|||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::{cmp, mem, slice};
|
use std::{cmp, mem, slice};
|
||||||
|
|
||||||
|
use self::diagnostics::{MismatchedClosingDelimiter, NonStringAbiLiteral};
|
||||||
|
|
||||||
bitflags::bitflags! {
|
bitflags::bitflags! {
|
||||||
struct Restrictions: u8 {
|
struct Restrictions: u8 {
|
||||||
const STMT_EXPR = 1 << 0;
|
const STMT_EXPR = 1 << 0;
|
||||||
@ -1384,14 +1387,7 @@ impl<'a> Parser<'a> {
|
|||||||
Err(Some(lit)) => match lit.kind {
|
Err(Some(lit)) => match lit.kind {
|
||||||
ast::LitKind::Err => None,
|
ast::LitKind::Err => None,
|
||||||
_ => {
|
_ => {
|
||||||
self.struct_span_err(lit.span, "non-string ABI literal")
|
self.sess.emit_err(NonStringAbiLiteral { span: lit.span });
|
||||||
.span_suggestion(
|
|
||||||
lit.span,
|
|
||||||
"specify the ABI with a string literal",
|
|
||||||
"\"C\"",
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1432,25 +1428,18 @@ pub(crate) fn make_unclosed_delims_error(
|
|||||||
// `None` here means an `Eof` was found. We already emit those errors elsewhere, we add them to
|
// `None` here means an `Eof` was found. We already emit those errors elsewhere, we add them to
|
||||||
// `unmatched_braces` only for error recovery in the `Parser`.
|
// `unmatched_braces` only for error recovery in the `Parser`.
|
||||||
let found_delim = unmatched.found_delim?;
|
let found_delim = unmatched.found_delim?;
|
||||||
let span: MultiSpan = if let Some(sp) = unmatched.unclosed_span {
|
let mut spans = vec![unmatched.found_span];
|
||||||
vec![unmatched.found_span, sp].into()
|
|
||||||
} else {
|
|
||||||
unmatched.found_span.into()
|
|
||||||
};
|
|
||||||
let mut err = sess.span_diagnostic.struct_span_err(
|
|
||||||
span,
|
|
||||||
&format!(
|
|
||||||
"mismatched closing delimiter: `{}`",
|
|
||||||
pprust::token_kind_to_string(&token::CloseDelim(found_delim)),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
err.span_label(unmatched.found_span, "mismatched closing delimiter");
|
|
||||||
if let Some(sp) = unmatched.candidate_span {
|
|
||||||
err.span_label(sp, "closing delimiter possibly meant for this");
|
|
||||||
}
|
|
||||||
if let Some(sp) = unmatched.unclosed_span {
|
if let Some(sp) = unmatched.unclosed_span {
|
||||||
err.span_label(sp, "unclosed delimiter");
|
spans.push(sp);
|
||||||
|
};
|
||||||
|
let err = MismatchedClosingDelimiter {
|
||||||
|
spans,
|
||||||
|
delimiter: pprust::token_kind_to_string(&token::CloseDelim(found_delim)).to_string(),
|
||||||
|
unmatched: unmatched.found_span,
|
||||||
|
opening_candidate: unmatched.candidate_span,
|
||||||
|
unclosed: unmatched.unclosed_span,
|
||||||
}
|
}
|
||||||
|
.into_diagnostic(&sess.span_diagnostic);
|
||||||
Some(err)
|
Some(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ fn main() {
|
|||||||
< //~ ERROR `<` is interpreted as a start of generic
|
< //~ ERROR `<` is interpreted as a start of generic
|
||||||
5);
|
5);
|
||||||
|
|
||||||
println!("{}", a as usize << long_name); //~ ERROR `<` is interpreted as a start of generic
|
println!("{}", a as usize << long_name); //~ ERROR `<<` is interpreted as a start of generic
|
||||||
|
|
||||||
println!("{}", a: &mut 4); //~ ERROR expected type, found `4`
|
println!("{}", a: &mut 4); //~ ERROR expected type, found `4`
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ LL |
|
|||||||
LL ~ usize)
|
LL ~ usize)
|
||||||
|
|
|
|
||||||
|
|
||||||
error: `<` is interpreted as a start of generic arguments for `usize`, not a shift
|
error: `<<` is interpreted as a start of generic arguments for `usize`, not a shift
|
||||||
--> $DIR/issue-22644.rs:32:31
|
--> $DIR/issue-22644.rs:32:31
|
||||||
|
|
|
|
||||||
LL | println!("{}", a as usize << long_name);
|
LL | println!("{}", a as usize << long_name);
|
||||||
|
Loading…
Reference in New Issue
Block a user