about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSantiago Pastorino <spastorino@gmail.com>2020-09-21 17:55:58 -0300
committerSantiago Pastorino <spastorino@gmail.com>2020-10-16 15:15:30 -0300
commitc3e8d7965ccef7fe47db591ae0064af0034e3f25 (patch)
tree922d26cccff89f11700bd96e7ca4f6289924f48e
parent3c4ad5508242bd560d095f1380bb8d739a0cbba2 (diff)
Parse inline const expressions
-rw-r--r--compiler/rustc_ast/src/ast.rs3
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs3
-rw-r--r--compiler/rustc_ast/src/token.rs1
-rw-r--r--compiler/rustc_ast/src/util/parser.rs2
-rw-r--r--compiler/rustc_ast/src/visit.rs1
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs3
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs11
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs2
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs27
-rw-r--r--src/test/ui/parser/inline_const/const_expr_parses.rs10
10 files changed, 60 insertions, 3 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 8f156aea2ff..ea84fc0095f 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1152,6 +1152,7 @@ impl Expr {
         match self.kind {
             ExprKind::Box(_) => ExprPrecedence::Box,
             ExprKind::Array(_) => ExprPrecedence::Array,
+            ExprKind::ConstBlock(_) => ExprPrecedence::ConstBlock,
             ExprKind::Call(..) => ExprPrecedence::Call,
             ExprKind::MethodCall(..) => ExprPrecedence::MethodCall,
             ExprKind::Tup(_) => ExprPrecedence::Tup,
@@ -1207,6 +1208,8 @@ pub enum ExprKind {
     Box(P<Expr>),
     /// An array (`[a, b, c, d]`)
     Array(Vec<P<Expr>>),
+    /// Allow anonymous constants from an inline `const` block
+    ConstBlock(AnonConst),
     /// A function call
     ///
     /// The first field resolves to the function itself,
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 425ef83b57a..382003c834e 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1106,6 +1106,9 @@ pub fn noop_visit_expr<T: MutVisitor>(
     match kind {
         ExprKind::Box(expr) => vis.visit_expr(expr),
         ExprKind::Array(exprs) => visit_exprs(exprs, vis),
+        ExprKind::ConstBlock(anon_const) => {
+            vis.visit_anon_const(anon_const);
+        }
         ExprKind::Repeat(expr, count) => {
             vis.visit_expr(expr);
             vis.visit_anon_const(count);
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index ad9c7391939..d991027cb45 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -153,6 +153,7 @@ pub fn ident_can_begin_expr(name: Symbol, span: Span, is_raw: bool) -> bool {
             kw::Do,
             kw::Box,
             kw::Break,
+            kw::Const,
             kw::Continue,
             kw::False,
             kw::For,
diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs
index be5516ef471..078dd4bd6e6 100644
--- a/compiler/rustc_ast/src/util/parser.rs
+++ b/compiler/rustc_ast/src/util/parser.rs
@@ -282,6 +282,7 @@ pub enum ExprPrecedence {
     ForLoop,
     Loop,
     Match,
+    ConstBlock,
     Block,
     TryBlock,
     Struct,
@@ -346,6 +347,7 @@ impl ExprPrecedence {
             ExprPrecedence::ForLoop |
             ExprPrecedence::Loop |
             ExprPrecedence::Match |
+            ExprPrecedence::ConstBlock |
             ExprPrecedence::Block |
             ExprPrecedence::TryBlock |
             ExprPrecedence::Async |
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 86fd87f6c42..3da078b760b 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -717,6 +717,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
         ExprKind::Array(ref subexpressions) => {
             walk_list!(visitor, visit_expr, subexpressions);
         }
+        ExprKind::ConstBlock(ref anon_const) => visitor.visit_anon_const(anon_const),
         ExprKind::Repeat(ref element, ref count) => {
             visitor.visit_expr(element);
             visitor.visit_anon_const(count)
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 2d2caa7a808..1841a06eb89 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -30,6 +30,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let kind = match e.kind {
                 ExprKind::Box(ref inner) => hir::ExprKind::Box(self.lower_expr(inner)),
                 ExprKind::Array(ref exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
+                ExprKind::ConstBlock(_) => {
+                    unimplemented!();
+                }
                 ExprKind::Repeat(ref expr, ref count) => {
                     let expr = self.lower_expr(expr);
                     let count = self.lower_anon_const(count);
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 9aa066370bb..af8f8132780 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -1714,6 +1714,14 @@ impl<'a> State<'a> {
         self.end();
     }
 
+    fn print_expr_anon_const(&mut self, expr: &ast::AnonConst, attrs: &[ast::Attribute]) {
+        self.ibox(INDENT_UNIT);
+        self.s.word("const");
+        self.print_inner_attributes_inline(attrs);
+        self.print_expr(&expr.value);
+        self.end();
+    }
+
     fn print_expr_repeat(
         &mut self,
         element: &ast::Expr,
@@ -1890,6 +1898,9 @@ impl<'a> State<'a> {
             ast::ExprKind::Array(ref exprs) => {
                 self.print_expr_vec(&exprs[..], attrs);
             }
+            ast::ExprKind::ConstBlock(ref anon_const) => {
+                self.print_expr_anon_const(anon_const, attrs);
+            }
             ast::ExprKind::Repeat(ref element, ref count) => {
                 self.print_expr_repeat(element, count, attrs);
             }
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 17cbaf65420..fb05f8791a5 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1060,6 +1060,8 @@ impl<'a> Parser<'a> {
             })
         } else if self.eat_keyword(kw::Unsafe) {
             self.parse_block_expr(None, lo, BlockCheckMode::Unsafe(ast::UserProvided), attrs)
+        } else if self.check_inline_const() {
+            self.parse_const_expr(lo.to(self.token.span))
         } else if self.is_do_catch_block() {
             self.recover_do_catch(attrs)
         } else if self.is_try_block() {
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index c1094681221..7970ad36456 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -18,8 +18,9 @@ use rustc_ast::ptr::P;
 use rustc_ast::token::{self, DelimToken, Token, TokenKind};
 use rustc_ast::tokenstream::{self, DelimSpan, TokenStream, TokenTree, TreeAndSpacing};
 use rustc_ast::DUMMY_NODE_ID;
-use rustc_ast::{self as ast, AttrStyle, AttrVec, Const, CrateSugar, Extern, Unsafe};
-use rustc_ast::{Async, MacArgs, MacDelimiter, Mutability, StrLit, Visibility, VisibilityKind};
+use rustc_ast::{self as ast, AnonConst, AttrStyle, AttrVec, Const, CrateSugar, Extern, Unsafe};
+use rustc_ast::{Async, Expr, ExprKind, MacArgs, MacDelimiter, Mutability, StrLit};
+use rustc_ast::{Visibility, VisibilityKind};
 use rustc_ast_pretty::pprust;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, FatalError, PResult};
 use rustc_session::parse::ParseSess;
@@ -545,6 +546,11 @@ impl<'a> Parser<'a> {
         self.check_or_expected(self.token.can_begin_const_arg(), TokenType::Const)
     }
 
+    fn check_inline_const(&mut self) -> bool {
+        self.check_keyword(kw::Const)
+            && self.look_ahead(1, |t| t == &token::OpenDelim(DelimToken::Brace))
+    }
+
     /// Checks to see if the next token is either `+` or `+=`.
     /// Otherwise returns `false`.
     fn check_plus(&mut self) -> bool {
@@ -864,13 +870,28 @@ impl<'a> Parser<'a> {
 
     /// Parses constness: `const` or nothing.
     fn parse_constness(&mut self) -> Const {
-        if self.eat_keyword(kw::Const) {
+        // Avoid const blocks to be parsed as const items
+        if self.look_ahead(1, |t| t != &token::OpenDelim(DelimToken::Brace))
+            && self.eat_keyword(kw::Const)
+        {
             Const::Yes(self.prev_token.uninterpolated_span())
         } else {
             Const::No
         }
     }
 
+    /// Parses inline const expressions.
+    fn parse_const_expr(&mut self, span: Span) -> PResult<'a, P<Expr>> {
+        self.sess.gated_spans.gate(sym::inline_const, span);
+        self.eat_keyword(kw::Const);
+        let blk = self.parse_block()?;
+        let anon_const = AnonConst {
+            id: DUMMY_NODE_ID,
+            value: self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new()),
+        };
+        Ok(self.mk_expr(span, ExprKind::ConstBlock(anon_const), AttrVec::new()))
+    }
+
     /// Parses mutability (`mut` or nothing).
     fn parse_mutability(&mut self) -> Mutability {
         if self.eat_keyword(kw::Mut) { Mutability::Mut } else { Mutability::Not }
diff --git a/src/test/ui/parser/inline_const/const_expr_parses.rs b/src/test/ui/parser/inline_const/const_expr_parses.rs
new file mode 100644
index 00000000000..5319db3482d
--- /dev/null
+++ b/src/test/ui/parser/inline_const/const_expr_parses.rs
@@ -0,0 +1,10 @@
+// check-pass
+// compile-flags: -Z parse-only
+
+#![feature(inline_const)]
+fn foo() -> i32 {
+    const {
+        let x = 5 + 10;
+        x / 3
+    }
+}