diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2020-03-07 17:16:29 +0100 |
|---|---|---|
| committer | Mazdak Farrokhzad <twingoow@gmail.com> | 2020-03-10 08:55:18 +0100 |
| commit | 458383dd337f276d091fa2de81bb7c1d31dde5fa (patch) | |
| tree | 064c57b7be465e8364441365612d52d8bcc084ea /src/librustc_parse/parser | |
| parent | ba3ae46de972f3e70319c25a5da69378454cb88d (diff) | |
| download | rust-458383dd337f276d091fa2de81bb7c1d31dde5fa.tar.gz rust-458383dd337f276d091fa2de81bb7c1d31dde5fa.zip | |
parse_if_expr: recover on attributes
Diffstat (limited to 'src/librustc_parse/parser')
| -rw-r--r-- | src/librustc_parse/parser/expr.rs | 43 | ||||
| -rw-r--r-- | src/librustc_parse/parser/item.rs | 3 |
2 files changed, 38 insertions, 8 deletions
diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index a41beb77119..7f6f90431fc 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -1514,13 +1514,16 @@ impl<'a> Parser<'a> { let thn = if self.eat_keyword(kw::Else) || !cond.returns() { self.error_missing_if_cond(lo, cond.span) } else { + let attrs = self.parse_outer_attributes()?; // For recovery. let not_block = self.token != token::OpenDelim(token::Brace); - self.parse_block().map_err(|mut err| { + let block = self.parse_block().map_err(|mut err| { if not_block { err.span_label(lo, "this `if` expression has a condition, but no block"); } err - })? + })?; + self.error_on_if_block_attrs(lo, false, block.span, &attrs); + block }; let els = if self.eat_keyword(kw::Else) { Some(self.parse_else_expr()?) } else { None }; Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els), attrs)) @@ -1562,12 +1565,40 @@ impl<'a> Parser<'a> { /// Parses an `else { ... }` expression (`else` token already eaten). fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> { - if self.eat_keyword(kw::If) { - self.parse_if_expr(AttrVec::new()) + let ctx_span = self.prev_token.span; // `else` + let attrs = self.parse_outer_attributes()?; // For recovery. + let expr = if self.eat_keyword(kw::If) { + self.parse_if_expr(AttrVec::new())? } else { let blk = self.parse_block()?; - Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new())) - } + self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new()) + }; + self.error_on_if_block_attrs(ctx_span, true, expr.span, &attrs); + Ok(expr) + } + + fn error_on_if_block_attrs( + &self, + ctx_span: Span, + is_ctx_else: bool, + branch_span: Span, + attrs: &[ast::Attribute], + ) { + let (span, 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", + String::new(), + Applicability::MachineApplicable, + ) + .emit(); } /// Parses `for <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten). diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 5add3fcc802..15cafef97fb 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -352,8 +352,7 @@ impl<'a> Parser<'a> { fn recover_attrs_no_item(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> { let (start, end) = match attrs { [] => return Ok(()), - [x0] => (x0, x0), - [x0, .., xn] => (x0, xn), + [x0 @ xn] | [x0, .., xn] => (x0, xn), }; let msg = if end.is_doc_comment() { "expected item after doc comment" |
