diff options
Diffstat (limited to 'compiler/rustc_parse/src')
| -rw-r--r-- | compiler/rustc_parse/src/lib.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/diagnostics.rs | 31 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 30 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/item.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/mod.rs | 28 |
5 files changed, 66 insertions, 27 deletions
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index f3bdd63ee6d..113af328a91 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -6,6 +6,7 @@ #![feature(let_chains)] #![feature(let_else)] #![feature(never_type)] +#![feature(rustc_attrs)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index acf892cec53..63055c56c5c 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -244,7 +244,7 @@ impl MultiSugg { } #[derive(SessionDiagnostic)] -#[error(slug = "parser-maybe-report-ambiguous-plus")] +#[error(parser::maybe_report_ambiguous_plus)] struct AmbiguousPlus { pub sum_ty: String, #[primary_span] @@ -253,7 +253,7 @@ struct AmbiguousPlus { } #[derive(SessionDiagnostic)] -#[error(code = "E0178", slug = "parser-maybe-recover-from-bad-type-plus")] +#[error(parser::maybe_recover_from_bad_type_plus, code = "E0178")] struct BadTypePlus { pub ty: String, #[primary_span] @@ -265,7 +265,7 @@ struct BadTypePlus { #[derive(SessionSubdiagnostic)] pub enum BadTypePlusSub { #[suggestion( - slug = "parser-add-paren", + parser::add_paren, code = "{sum_with_parens}", applicability = "machine-applicable" )] @@ -274,12 +274,12 @@ pub enum BadTypePlusSub { #[primary_span] span: Span, }, - #[label(slug = "parser-forgot-paren")] + #[label(parser::forgot_paren)] ForgotParen { #[primary_span] span: Span, }, - #[label(slug = "parser-expect-path")] + #[label(parser::expect_path)] ExpectPath { #[primary_span] span: Span, @@ -287,7 +287,7 @@ pub enum BadTypePlusSub { } #[derive(SessionDiagnostic)] -#[error(slug = "parser-maybe-recover-from-bad-qpath-stage-2")] +#[error(parser::maybe_recover_from_bad_qpath_stage_2)] struct BadQPathStage2 { #[primary_span] #[suggestion(applicability = "maybe-incorrect")] @@ -296,7 +296,7 @@ struct BadQPathStage2 { } #[derive(SessionDiagnostic)] -#[error(slug = "parser-incorrect-semicolon")] +#[error(parser::incorrect_semicolon)] struct IncorrectSemicolon<'a> { #[primary_span] #[suggestion_short(applicability = "machine-applicable")] @@ -307,26 +307,26 @@ struct IncorrectSemicolon<'a> { } #[derive(SessionDiagnostic)] -#[error(slug = "parser-incorrect-use-of-await")] +#[error(parser::incorrect_use_of_await)] struct IncorrectUseOfAwait { #[primary_span] - #[suggestion(message = "parentheses-suggestion", applicability = "machine-applicable")] + #[suggestion(parser::parentheses_suggestion, applicability = "machine-applicable")] span: Span, } #[derive(SessionDiagnostic)] -#[error(slug = "parser-incorrect-use-of-await")] +#[error(parser::incorrect_use_of_await)] struct IncorrectAwait { #[primary_span] span: Span, - #[suggestion(message = "postfix-suggestion", code = "{expr}.await{question_mark}")] + #[suggestion(parser::postfix_suggestion, code = "{expr}.await{question_mark}")] sugg_span: (Span, Applicability), expr: String, question_mark: &'static str, } #[derive(SessionDiagnostic)] -#[error(slug = "parser-in-in-typo")] +#[error(parser::in_in_typo)] struct InInTypo { #[primary_span] span: Span, @@ -357,6 +357,7 @@ impl<'a> DerefMut for SnapshotParser<'a> { } impl<'a> Parser<'a> { + #[rustc_lint_diagnostics] pub(super) fn span_err<S: Into<MultiSpan>>( &self, sp: S, @@ -365,6 +366,7 @@ impl<'a> Parser<'a> { err.span_err(sp, self.diagnostic()) } + #[rustc_lint_diagnostics] pub fn struct_span_err<S: Into<MultiSpan>>( &self, sp: S, @@ -1355,7 +1357,10 @@ impl<'a> Parser<'a> { s.print_mutability(mut_ty.mutbl, false); s.popen(); s.print_type(&mut_ty.ty); - s.print_type_bounds(" +", &bounds); + if !bounds.is_empty() { + s.word(" + "); + s.print_type_bounds(&bounds); + } s.pclose() }); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 81bab0e3513..2c43563b104 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -7,6 +7,7 @@ use super::{ }; use crate::maybe_recover_from_interpolated_ty_qpath; +use core::mem; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::Spacing; @@ -26,7 +27,6 @@ use rustc_session::lint::BuiltinLintDiagnostics; use rustc_span::source_map::{self, Span, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, Pos}; -use std::mem; /// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression /// dropped into the token stream, which happens while parsing the result of @@ -2343,7 +2343,9 @@ impl<'a> Parser<'a> { /// Parses the condition of a `if` or `while` expression. fn parse_cond_expr(&mut self) -> PResult<'a, P<Expr>> { - let cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; + let cond = self.with_let_management(true, |local_self| { + local_self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None) + })?; if let ExprKind::Let(..) = cond.kind { // Remove the last feature gating of a `let` expression since it's stable. @@ -2356,6 +2358,13 @@ impl<'a> Parser<'a> { /// Parses a `let $pat = $expr` pseudo-expression. /// The `let` token has already been eaten. fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> { + if !self.let_expr_allowed { + self.struct_span_err( + self.prev_token.span, + "expected expression, found `let` statement", + ) + .emit(); + } let lo = self.prev_token.span; let pat = self.parse_pat_allow_top_alt( None, @@ -2672,6 +2681,8 @@ impl<'a> Parser<'a> { } pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> { + // Used to check the `let_chains` and `if_let_guard` features mostly by scaning + // `&&` tokens. fn check_let_expr(expr: &Expr) -> (bool, bool) { match expr.kind { ExprKind::Binary(_, ref lhs, ref rhs) => { @@ -2694,7 +2705,7 @@ impl<'a> Parser<'a> { )?; let guard = if this.eat_keyword(kw::If) { let if_span = this.prev_token.span; - let cond = this.parse_expr()?; + let cond = this.with_let_management(true, |local_this| local_this.parse_expr())?; let (has_let_expr, does_not_have_bin_op) = check_let_expr(&cond); if has_let_expr { if does_not_have_bin_op { @@ -3256,4 +3267,17 @@ impl<'a> Parser<'a> { Ok((res, trailing)) }) } + + // Calls `f` with the internal `let_expr_allowed` set to `let_expr_allowed` and then + // sets the internal `let_expr_allowed` back to its original value. + fn with_let_management<T>( + &mut self, + let_expr_allowed: bool, + f: impl FnOnce(&mut Self) -> T, + ) -> T { + let last_let_expr_allowed = mem::replace(&mut self.let_expr_allowed, let_expr_allowed); + let rslt = f(self); + self.let_expr_allowed = last_let_expr_allowed; + rslt + } } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index bf685aa8cad..87bc0d9762e 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -271,8 +271,7 @@ impl<'a> Parser<'a> { // MACRO_RULES ITEM self.parse_item_macro_rules(vis, has_bang)? } else if self.isnt_macro_invocation() - && (self.token.is_ident_named(Symbol::intern("import")) - || self.token.is_ident_named(Symbol::intern("using"))) + && (self.token.is_ident_named(sym::import) || self.token.is_ident_named(sym::using)) { return self.recover_import_as_use(); } else if self.isnt_macro_invocation() && vis.kind.is_pub() { diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 6d6667717f0..67e6402c0ae 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -147,12 +147,15 @@ pub struct Parser<'a> { /// This allows us to recover when the user forget to add braces around /// multiple statements in the closure body. pub current_closure: Option<ClosureSpans>, + /// Used to track where `let`s are allowed. For example, `if true && let 1 = 1` is valid + /// but `[1, 2, 3][let _ = ()]` is not. + let_expr_allowed: bool, } // This type is used a lot, e.g. it's cloned when matching many declarative macro rules. Make sure // it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Parser<'_>, 328); +rustc_data_structures::static_assert_size!(Parser<'_>, 336); /// Stores span information about a closure. #[derive(Clone)] @@ -455,6 +458,7 @@ impl<'a> Parser<'a> { inner_attr_ranges: Default::default(), }, current_closure: None, + let_expr_allowed: false, }; // Make parser point to the first token. @@ -887,22 +891,19 @@ impl<'a> Parser<'a> { let mut first_note = MultiSpan::from(vec![initial_semicolon]); first_note.push_span_label( initial_semicolon, - "this `;` turns the preceding closure into a statement".to_string(), + "this `;` turns the preceding closure into a statement", ); first_note.push_span_label( closure_spans.body, - "this expression is a statement because of the trailing semicolon".to_string(), + "this expression is a statement because of the trailing semicolon", ); expect_err.span_note(first_note, "statement found outside of a block"); let mut second_note = MultiSpan::from(vec![closure_spans.whole_closure]); - second_note.push_span_label( - closure_spans.whole_closure, - "this is the parsed closure...".to_string(), - ); + second_note.push_span_label(closure_spans.whole_closure, "this is the parsed closure..."); second_note.push_span_label( following_token_span, - "...but likely you meant the closure to end here".to_string(), + "...but likely you meant the closure to end here", ); expect_err.span_note(second_note, "the closure body may be incorrectly delimited"); @@ -1352,7 +1353,16 @@ impl<'a> Parser<'a> { /// Parses `extern string_literal?`. fn parse_extern(&mut self) -> Extern { - if self.eat_keyword(kw::Extern) { Extern::from_abi(self.parse_abi()) } else { Extern::None } + if self.eat_keyword(kw::Extern) { + let mut extern_span = self.prev_token.span; + let abi = self.parse_abi(); + if let Some(abi) = abi { + extern_span = extern_span.to(abi.span); + } + Extern::from_abi(abi, extern_span) + } else { + Extern::None + } } /// Parses a string literal as an ABI spec. |
