mirror of https://github.com/rust-lang/rust.git
Parse inline const expressions
This commit is contained in:
parent
3c4ad55082
commit
c3e8d7965c
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 |
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
// check-pass
|
||||
// compile-flags: -Z parse-only
|
||||
|
||||
#![feature(inline_const)]
|
||||
fn foo() -> i32 {
|
||||
const {
|
||||
let x = 5 + 10;
|
||||
x / 3
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue