diff options
| author | bors <bors@rust-lang.org> | 2018-05-16 14:22:17 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-05-16 14:22:17 +0000 |
| commit | 0e325d0141ce8d86524f55c2df53835aab895096 (patch) | |
| tree | b99c4a1c01f88267db584a9768b92c6a82370e85 /src/libsyntax | |
| parent | 2a3f5367a23a769a068c37460db336de427c4b48 (diff) | |
| parent | ae1553aa027c395a93426dc0fe0abd4ec6af2291 (diff) | |
| download | rust-0e325d0141ce8d86524f55c2df53835aab895096.tar.gz rust-0e325d0141ce8d86524f55c2df53835aab895096.zip | |
Auto merge of #50045 - est31:label_break_value, r=eddyb
Implement label break value (RFC 2046) Implement label-break-value (#48594).
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 6 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 9 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 5 | ||||
| -rw-r--r-- | src/libsyntax/parse/classify.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 22 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 15 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 5 |
8 files changed, 49 insertions, 17 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index f8cd6103bdf..2b6635ec783 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -934,7 +934,7 @@ impl Expr { /// Whether this expression would be valid somewhere that expects a value, for example, an `if` /// condition. pub fn returns(&self) -> bool { - if let ExprKind::Block(ref block) = self.node { + if let ExprKind::Block(ref block, _) = self.node { match block.stmts.last().map(|last_stmt| &last_stmt.node) { // implicit return Some(&StmtKind::Expr(_)) => true, @@ -1121,8 +1121,8 @@ pub enum ExprKind { /// /// The final span is the span of the argument block `|...|` Closure(CaptureBy, Movability, P<FnDecl>, P<Expr>, Span), - /// A block (`{ ... }`) - Block(P<Block>), + /// A block (`'label: { ... }`) + Block(P<Block>, Option<Label>), /// A catch block (`catch { ... }`) Catch(P<Block>), diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 0b64189b2bc..a4f9ebcf418 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -668,7 +668,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.expr(span, ast::ExprKind::MethodCall(segment, args)) } fn expr_block(&self, b: P<ast::Block>) -> P<ast::Expr> { - self.expr(b.span, ast::ExprKind::Block(b)) + self.expr(b.span, ast::ExprKind::Block(b, None)) } fn field_imm(&self, span: Span, ident: Ident, e: P<ast::Expr>) -> ast::Field { ast::Field { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index bf78723e413..f1229520c77 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -466,6 +466,9 @@ declare_features! ( // inconsistent bounds in where clauses (active, trivial_bounds, "1.28.0", Some(48214), None), + + // 'a: { break 'a; } + (active, label_break_value, "1.28.0", Some(48594), None), ); declare_features! ( @@ -1696,6 +1699,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { "multiple patterns in `if let` and `while let` are unstable"); } } + ast::ExprKind::Block(_, opt_label) => { + if let Some(label) = opt_label { + gate_feature_post!(&self, label_break_value, label.ident.span, + "labels on blocks are unstable"); + } + } _ => {} } visit::walk_expr(self, e); diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index d67995761f6..29cc208c06b 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1256,7 +1256,10 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu folder.fold_expr(body), folder.new_span(span)) } - ExprKind::Block(blk) => ExprKind::Block(folder.fold_block(blk)), + ExprKind::Block(blk, opt_label) => { + ExprKind::Block(folder.fold_block(blk), + opt_label.map(|label| folder.fold_label(label))) + } ExprKind::Assign(el, er) => { ExprKind::Assign(folder.fold_expr(el), folder.fold_expr(er)) } diff --git a/src/libsyntax/parse/classify.rs b/src/libsyntax/parse/classify.rs index b8e02556625..531483e7de1 100644 --- a/src/libsyntax/parse/classify.rs +++ b/src/libsyntax/parse/classify.rs @@ -26,7 +26,7 @@ pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool { ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) | ast::ExprKind::Match(..) | - ast::ExprKind::Block(_) | + ast::ExprKind::Block(..) | ast::ExprKind::While(..) | ast::ExprKind::WhileLet(..) | ast::ExprKind::Loop(..) | diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 3f0df6d055b..7b91c491700 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -128,7 +128,7 @@ macro_rules! maybe_whole_expr { token::NtBlock(ref block) => { $p.bump(); let span = $p.span; - let kind = ExprKind::Block((*block).clone()); + let kind = ExprKind::Block((*block).clone(), None); return Ok($p.mk_expr(span, kind, ThinVec::new())); } _ => {}, @@ -2244,7 +2244,7 @@ impl<'a> Parser<'a> { }; } token::OpenDelim(token::Brace) => { - return self.parse_block_expr(lo, BlockCheckMode::Default, attrs); + return self.parse_block_expr(None, lo, BlockCheckMode::Default, attrs); } token::BinOp(token::Or) | token::OrOr => { return self.parse_lambda_expr(attrs); @@ -2318,7 +2318,13 @@ impl<'a> Parser<'a> { if self.eat_keyword(keywords::Loop) { return self.parse_loop_expr(Some(label), lo, attrs) } - let msg = "expected `while`, `for`, or `loop` after a label"; + if self.token == token::OpenDelim(token::Brace) { + return self.parse_block_expr(Some(label), + lo, + BlockCheckMode::Default, + attrs); + } + let msg = "expected `while`, `for`, `loop` or `{` after a label"; let mut err = self.fatal(msg); err.span_label(self.span, msg); return Err(err); @@ -2338,6 +2344,7 @@ impl<'a> Parser<'a> { } if self.eat_keyword(keywords::Unsafe) { return self.parse_block_expr( + None, lo, BlockCheckMode::Unsafe(ast::UserProvided), attrs); @@ -2502,7 +2509,8 @@ impl<'a> Parser<'a> { } /// Parse a block or unsafe block - pub fn parse_block_expr(&mut self, lo: Span, blk_mode: BlockCheckMode, + pub fn parse_block_expr(&mut self, opt_label: Option<Label>, + lo: Span, blk_mode: BlockCheckMode, outer_attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { self.expect(&token::OpenDelim(token::Brace))?; @@ -2511,7 +2519,7 @@ impl<'a> Parser<'a> { attrs.extend(self.parse_inner_attributes()?); let blk = self.parse_block_tail(lo, blk_mode)?; - return Ok(self.mk_expr(blk.span, ExprKind::Block(blk), attrs)); + return Ok(self.mk_expr(blk.span, ExprKind::Block(blk, opt_label), attrs)); } /// parse a.b or a(13) or a[4] or just a @@ -3261,7 +3269,7 @@ impl<'a> Parser<'a> { // If an explicit return type is given, require a // block to appear (RFC 968). let body_lo = self.span; - self.parse_block_expr(body_lo, BlockCheckMode::Default, ThinVec::new())? + self.parse_block_expr(None, body_lo, BlockCheckMode::Default, ThinVec::new())? } }; @@ -3277,7 +3285,7 @@ impl<'a> Parser<'a> { return self.parse_if_expr(ThinVec::new()); } else { let blk = self.parse_block()?; - return Ok(self.mk_expr(blk.span, ExprKind::Block(blk), ThinVec::new())); + return Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None), ThinVec::new())); } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 8e33fa08083..a700799cde5 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1792,7 +1792,7 @@ impl<'a> State<'a> { self.print_else(e.as_ref().map(|e| &**e)) } // "final else" - ast::ExprKind::Block(ref b) => { + ast::ExprKind::Block(ref b, _) => { self.cbox(INDENT_UNIT - 1)?; self.ibox(0)?; self.s.word(" else ")?; @@ -2182,7 +2182,11 @@ impl<'a> State<'a> { // empty box to satisfy the close. self.ibox(0)?; } - ast::ExprKind::Block(ref blk) => { + ast::ExprKind::Block(ref blk, opt_label) => { + if let Some(label) = opt_label { + self.print_ident(label.ident)?; + self.word_space(":")?; + } // containing cbox, will be closed by print-block at } self.cbox(INDENT_UNIT)?; // head-box, will be closed by print-block after { @@ -2695,7 +2699,12 @@ impl<'a> State<'a> { self.word_space("=>")?; match arm.body.node { - ast::ExprKind::Block(ref blk) => { + ast::ExprKind::Block(ref blk, opt_label) => { + if let Some(label) = opt_label { + self.print_ident(label.ident)?; + self.word_space(":")?; + } + // the block will close the pattern's ibox self.print_block_unclosed_indent(blk, INDENT_UNIT)?; diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 40d59d3ff8b..2013e838c05 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -736,7 +736,10 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { expression.span, expression.id) } - ExprKind::Block(ref block) => visitor.visit_block(block), + ExprKind::Block(ref block, ref opt_label) => { + walk_list!(visitor, visit_label, opt_label); + visitor.visit_block(block); + } ExprKind::Assign(ref left_hand_expression, ref right_hand_expression) => { visitor.visit_expr(left_hand_expression); visitor.visit_expr(right_hand_expression); |
