diff options
Diffstat (limited to 'compiler/rustc_parse/src')
| -rw-r--r-- | compiler/rustc_parse/src/errors.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/diagnostics.rs | 52 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 33 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/pat.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/ty.rs | 67 |
5 files changed, 134 insertions, 32 deletions
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 06b970ad979..40763da0bb5 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -337,7 +337,9 @@ pub(crate) struct IfExpressionMissingThenBlock { #[primary_span] pub if_span: Span, #[subdiagnostic] - pub sub: IfExpressionMissingThenBlockSub, + pub missing_then_block_sub: IfExpressionMissingThenBlockSub, + #[subdiagnostic] + pub let_else_sub: Option<IfExpressionLetSomeSub>, } #[derive(Subdiagnostic)] @@ -348,6 +350,13 @@ pub(crate) enum IfExpressionMissingThenBlockSub { AddThenBlock(#[primary_span] Span), } +#[derive(Subdiagnostic)] +#[help(parse_extra_if_in_let_else)] +pub(crate) struct IfExpressionLetSomeSub { + #[primary_span] + pub if_span: Span, +} + #[derive(Diagnostic)] #[diag(parse_if_expression_missing_condition)] pub(crate) struct IfExpressionMissingCondition { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 4c918c6702e..eda7046c748 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2372,7 +2372,7 @@ impl<'a> Parser<'a> { /// Some special error handling for the "top-level" patterns in a match arm, /// `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_or_anon_enum( &mut self, mut first_pat: P<Pat>, expected: Expected, @@ -2383,26 +2383,41 @@ impl<'a> Parser<'a> { if !matches!(first_pat.kind, PatKind::Ident(_, _, None) | PatKind::Path(..)) || !self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident()) { + let mut snapshot_type = self.create_snapshot_for_diagnostic(); + snapshot_type.bump(); // `:` + match snapshot_type.parse_ty() { + Err(inner_err) => { + inner_err.cancel(); + } + Ok(ty) => { + let Err(mut err) = self.expected_one_of_not_found(&[], &[]) else { + return first_pat; + }; + err.span_label(ty.span, "specifying the type of a pattern isn't supported"); + self.restore_snapshot(snapshot_type); + let span = first_pat.span.to(ty.span); + first_pat = self.mk_pat(span, PatKind::Wild); + err.emit(); + } + } return first_pat; } // The pattern looks like it might be a path with a `::` -> `:` typo: // `match foo { bar:baz => {} }` - let span = self.token.span; + let colon_span = self.token.span; // We only emit "unexpected `:`" error here if we can successfully parse the // whole pattern correctly in that case. - let snapshot = self.create_snapshot_for_diagnostic(); + let mut snapshot_pat = self.create_snapshot_for_diagnostic(); + let mut snapshot_type = self.create_snapshot_for_diagnostic(); // Create error for "unexpected `:`". match self.expected_one_of_not_found(&[], &[]) { Err(mut err) => { - self.bump(); // Skip the `:`. - match self.parse_pat_no_top_alt(expected) { + snapshot_pat.bump(); // Skip the `:`. + snapshot_type.bump(); // Skip the `:`. + match snapshot_pat.parse_pat_no_top_alt(expected) { Err(inner_err) => { - // Carry on as if we had not done anything, callers will emit a - // reasonable error. inner_err.cancel(); - err.cancel(); - self.restore_snapshot(snapshot); } Ok(mut pat) => { // We've parsed the rest of the pattern. @@ -2466,8 +2481,8 @@ impl<'a> Parser<'a> { _ => {} } if show_sugg { - err.span_suggestion( - span, + err.span_suggestion_verbose( + colon_span.until(self.look_ahead(1, |t| t.span)), "maybe write a path separator here", "::", Applicability::MaybeIncorrect, @@ -2475,13 +2490,24 @@ impl<'a> Parser<'a> { } else { first_pat = self.mk_pat(new_span, PatKind::Wild); } - err.emit(); + self.restore_snapshot(snapshot_pat); } } + match snapshot_type.parse_ty() { + Err(inner_err) => { + inner_err.cancel(); + } + Ok(ty) => { + err.span_label(ty.span, "specifying the type of a pattern isn't supported"); + self.restore_snapshot(snapshot_type); + let new_span = first_pat.span.to(ty.span); + first_pat = self.mk_pat(new_span, PatKind::Wild); + } + } + err.emit(); } _ => { // Carry on as if we had not done anything. This should be unreachable. - self.restore_snapshot(snapshot); } }; first_pat diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index bf93a89f065..3225a309a31 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -11,15 +11,15 @@ use crate::errors::{ ComparisonOrShiftInterpretedAsGenericSugg, DoCatchSyntaxRemoved, DotDotDot, EqFieldInit, ExpectedElseBlock, ExpectedEqForLetExpr, ExpectedExpressionFoundLet, FieldExpressionWithGeneric, FloatLiteralRequiresIntegerPart, FoundExprWouldBeStmt, - IfExpressionMissingCondition, IfExpressionMissingThenBlock, IfExpressionMissingThenBlockSub, - InvalidBlockMacroSegment, InvalidComparisonOperator, InvalidComparisonOperatorSub, - InvalidInterpolatedExpression, InvalidLiteralSuffixOnTupleIndex, InvalidLogicalOperator, - InvalidLogicalOperatorSub, LabeledLoopInBreak, LeadingPlusNotSupported, LeftArrowOperator, - LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath, MalformedLoopLabel, - MatchArmBodyWithoutBraces, MatchArmBodyWithoutBracesSugg, MissingCommaAfterMatchArm, - MissingDotDot, MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray, - NoFieldsForFnCall, NotAsNegationOperator, NotAsNegationOperatorSub, - OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields, + IfExpressionLetSomeSub, IfExpressionMissingCondition, IfExpressionMissingThenBlock, + IfExpressionMissingThenBlockSub, InvalidBlockMacroSegment, InvalidComparisonOperator, + InvalidComparisonOperatorSub, InvalidInterpolatedExpression, InvalidLiteralSuffixOnTupleIndex, + InvalidLogicalOperator, InvalidLogicalOperatorSub, LabeledLoopInBreak, LeadingPlusNotSupported, + LeftArrowOperator, LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath, + MalformedLoopLabel, MatchArmBodyWithoutBraces, MatchArmBodyWithoutBracesSugg, + MissingCommaAfterMatchArm, MissingDotDot, MissingInInForLoop, MissingInInForLoopSub, + MissingSemicolonBeforeArray, NoFieldsForFnCall, NotAsNegationOperator, + NotAsNegationOperatorSub, OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields, RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, StructLiteralNotAllowedHere, StructLiteralNotAllowedHereSugg, TildeAsUnaryOperator, UnexpectedIfWithIf, UnexpectedTokenAfterLabel, UnexpectedTokenAfterLabelSugg, WrapExpressionInParentheses, @@ -2251,9 +2251,10 @@ impl<'a> Parser<'a> { if let ExprKind::Block(_, None) = right.kind => { self.sess.emit_err(IfExpressionMissingThenBlock { if_span: lo, - sub: IfExpressionMissingThenBlockSub::UnfinishedCondition( - cond_span.shrink_to_lo().to(*binop_span) - ), + missing_then_block_sub: + IfExpressionMissingThenBlockSub::UnfinishedCondition(cond_span.shrink_to_lo().to(*binop_span)), + let_else_sub: None, + }); std::mem::replace(right, this.mk_expr_err(binop_span.shrink_to_hi())) }, @@ -2279,9 +2280,15 @@ impl<'a> Parser<'a> { if let Some(block) = recover_block_from_condition(self) { block } else { + let let_else_sub = matches!(cond.kind, ExprKind::Let(..)) + .then(|| IfExpressionLetSomeSub { if_span: lo }); + self.sess.emit_err(IfExpressionMissingThenBlock { if_span: lo, - sub: IfExpressionMissingThenBlockSub::AddThenBlock(cond_span.shrink_to_hi()), + missing_then_block_sub: IfExpressionMissingThenBlockSub::AddThenBlock( + cond_span.shrink_to_hi(), + ), + let_else_sub, }); self.mk_block_err(cond_span.shrink_to_hi()) } diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index e73a17ced7d..e5411538eea 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -116,7 +116,8 @@ impl<'a> Parser<'a> { // Check if the user wrote `foo:bar` instead of `foo::bar`. if ra == RecoverColon::Yes { - first_pat = self.maybe_recover_colon_colon_in_pat_typo(first_pat, expected); + first_pat = + self.maybe_recover_colon_colon_in_pat_typo_or_anon_enum(first_pat, expected); } if let Some(leading_vert_span) = leading_vert_span { diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 1766b0293de..25de0a9e750 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -11,6 +11,7 @@ use rustc_ast::{ self as ast, BareFnTy, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax, Ty, TyKind, }; +use rustc_ast_pretty::pprust; use rustc_errors::{pluralize, struct_span_err, Applicability, PResult}; use rustc_span::source_map::Span; use rustc_span::symbol::{kw, sym, Ident}; @@ -43,17 +44,24 @@ pub(super) enum AllowPlus { No, } -#[derive(PartialEq)] +#[derive(PartialEq, Clone, Copy)] pub(super) enum RecoverQPath { Yes, No, } +#[derive(PartialEq, Clone, Copy)] pub(super) enum RecoverQuestionMark { Yes, No, } +#[derive(PartialEq, Clone, Copy)] +pub(super) enum RecoverAnonEnum { + Yes, + No, +} + /// Signals whether parsing a type should recover `->`. /// /// More specifically, when parsing a function like: @@ -86,7 +94,7 @@ impl RecoverReturnSign { } // Is `...` (`CVarArgs`) legal at this level of type parsing? -#[derive(PartialEq)] +#[derive(PartialEq, Clone, Copy)] enum AllowCVariadic { Yes, No, @@ -111,6 +119,7 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::Yes, + RecoverAnonEnum::No, ) } @@ -125,6 +134,7 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, Some(ty_params), RecoverQuestionMark::Yes, + RecoverAnonEnum::No, ) } @@ -139,6 +149,7 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::Yes, + RecoverAnonEnum::Yes, ) } @@ -156,6 +167,7 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::Yes, + RecoverAnonEnum::No, ) } @@ -169,6 +181,7 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::No, + RecoverAnonEnum::No, ) } @@ -180,6 +193,7 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::No, + RecoverAnonEnum::No, ) } @@ -192,6 +206,7 @@ impl<'a> Parser<'a> { RecoverReturnSign::OnlyFatArrow, None, RecoverQuestionMark::Yes, + RecoverAnonEnum::No, ) } @@ -211,6 +226,7 @@ impl<'a> Parser<'a> { recover_return_sign, None, RecoverQuestionMark::Yes, + RecoverAnonEnum::Yes, )?; FnRetTy::Ty(ty) } else if recover_return_sign.can_recover(&self.token.kind) { @@ -232,6 +248,7 @@ impl<'a> Parser<'a> { recover_return_sign, None, RecoverQuestionMark::Yes, + RecoverAnonEnum::Yes, )?; FnRetTy::Ty(ty) } else { @@ -247,6 +264,7 @@ impl<'a> Parser<'a> { recover_return_sign: RecoverReturnSign, ty_generics: Option<&Generics>, recover_question_mark: RecoverQuestionMark, + recover_anon_enum: RecoverAnonEnum, ) -> PResult<'a, P<Ty>> { let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes; maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery); @@ -325,14 +343,55 @@ impl<'a> Parser<'a> { let mut ty = self.mk_ty(span, kind); // Try to recover from use of `+` with incorrect priority. - if matches!(allow_plus, AllowPlus::Yes) { + if allow_plus == AllowPlus::Yes { self.maybe_recover_from_bad_type_plus(&ty)?; } else { self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty); } - if let RecoverQuestionMark::Yes = recover_question_mark { + if RecoverQuestionMark::Yes == recover_question_mark { ty = self.maybe_recover_from_question_mark(ty); } + if recover_anon_enum == RecoverAnonEnum::Yes + && self.check_noexpect(&token::BinOp(token::Or)) + && self.look_ahead(1, |t| t.can_begin_type()) + { + let mut pipes = vec![self.token.span]; + let mut types = vec![ty]; + loop { + if !self.eat(&token::BinOp(token::Or)) { + break; + } + pipes.push(self.prev_token.span); + types.push(self.parse_ty_common( + allow_plus, + allow_c_variadic, + recover_qpath, + recover_return_sign, + ty_generics, + recover_question_mark, + RecoverAnonEnum::No, + )?); + } + let mut err = self.struct_span_err(pipes, "anonymous enums are not supported"); + for ty in &types { + err.span_label(ty.span, ""); + } + err.help(&format!( + "create a named `enum` and use it here instead:\nenum Name {{\n{}\n}}", + types + .iter() + .enumerate() + .map(|(i, t)| format!( + " Variant{}({}),", + i + 1, // Lets not confuse people with zero-indexing :) + pprust::to_string(|s| s.print_type(&t)), + )) + .collect::<Vec<_>>() + .join("\n"), + )); + err.emit(); + return Ok(self.mk_ty(lo.to(self.prev_token.span), TyKind::Err)); + } if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) } } |
