From 3c4ad5508242bd560d095f1380bb8d739a0cbba2 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 21 Sep 2020 16:10:31 -0300 Subject: [PATCH 01/11] Add inline_const feature flag --- compiler/rustc_ast_passes/src/feature_gate.rs | 1 + compiler/rustc_feature/src/active.rs | 3 +++ compiler/rustc_span/src/symbol.rs | 1 + src/test/ui/feature-gate-inline_const.rs | 6 ++++++ src/test/ui/feature-gate-inline_const.stderr | 8 ++++++++ 5 files changed, 19 insertions(+) create mode 100644 src/test/ui/feature-gate-inline_const.rs create mode 100644 src/test/ui/feature-gate-inline_const.stderr diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 00d3db73766..f2008449767 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -629,6 +629,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { gate_all!(const_trait_bound_opt_out, "`?const` on trait bounds is experimental"); gate_all!(const_trait_impl, "const trait impls are experimental"); gate_all!(half_open_range_patterns, "half-open range patterns are unstable"); + gate_all!(inline_const, "inline-const is experimental"); // All uses of `gate_all!` below this point were added in #65742, // and subsequently disabled (with the non-early gating readded). diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 7fbd070a609..9a70fa4d589 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -598,6 +598,9 @@ declare_features! ( /// Allows `#[instruction_set(_)]` attribute (active, isa_attribute, "1.48.0", Some(74727), None), + /// Allow anonymous constants from an inline `const` block + (active, inline_const, "1.49.0", Some(76001), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 28fef65da07..9cf530d57c0 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -593,6 +593,7 @@ symbols! { infer_static_outlives_requirements, inlateout, inline, + inline_const, inout, instruction_set, intel, diff --git a/src/test/ui/feature-gate-inline_const.rs b/src/test/ui/feature-gate-inline_const.rs new file mode 100644 index 00000000000..76762489f3a --- /dev/null +++ b/src/test/ui/feature-gate-inline_const.rs @@ -0,0 +1,6 @@ +fn main() { + let _ = const { + //~^ ERROR expected expression, found keyword `const` + true + }; +} diff --git a/src/test/ui/feature-gate-inline_const.stderr b/src/test/ui/feature-gate-inline_const.stderr new file mode 100644 index 00000000000..b9498e22585 --- /dev/null +++ b/src/test/ui/feature-gate-inline_const.stderr @@ -0,0 +1,8 @@ +error: expected expression, found keyword `const` + --> $DIR/feature-gate-inline_const.rs:2:13 + | +LL | let _ = const { + | ^^^^^ expected expression + +error: aborting due to previous error + From c3e8d7965ccef7fe47db591ae0064af0034e3f25 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 21 Sep 2020 17:55:58 -0300 Subject: [PATCH 02/11] Parse inline const expressions --- compiler/rustc_ast/src/ast.rs | 3 +++ compiler/rustc_ast/src/mut_visit.rs | 3 +++ compiler/rustc_ast/src/token.rs | 1 + compiler/rustc_ast/src/util/parser.rs | 2 ++ compiler/rustc_ast/src/visit.rs | 1 + compiler/rustc_ast_lowering/src/expr.rs | 3 +++ compiler/rustc_ast_pretty/src/pprust/state.rs | 11 ++++++++ compiler/rustc_parse/src/parser/expr.rs | 2 ++ compiler/rustc_parse/src/parser/mod.rs | 27 ++++++++++++++++--- .../parser/inline_const/const_expr_parses.rs | 10 +++++++ 10 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/parser/inline_const/const_expr_parses.rs 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), /// An array (`[a, b, c, d]`) Array(Vec>), + /// 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( 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> { + 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 + } +} From 59d07c3ae5a1f53924c7580fa302c397c362f1a2 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 23 Sep 2020 18:34:44 -0300 Subject: [PATCH 03/11] Parse inline const patterns --- compiler/rustc_parse/src/parser/pat.rs | 3 +++ .../inline_const/const_match_pat_parses.rs | 20 +++++++++++++++++++ .../issue-66357-unexpected-unreachable.rs | 2 +- .../issue-66357-unexpected-unreachable.stderr | 2 +- 4 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/parser/inline_const/const_match_pat_parses.rs diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 5aced9dc37c..15db2066a30 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -313,6 +313,9 @@ impl<'a> Parser<'a> { let pat = self.parse_pat_with_range_pat(false, None)?; self.sess.gated_spans.gate(sym::box_patterns, lo.to(self.prev_token.span)); PatKind::Box(pat) + } else if self.check_inline_const() { + // Parse `const pat` + PatKind::Lit(self.parse_const_expr(lo.to(self.token.span))?) } else if self.can_be_ident_pat() { // Parse `ident @ pat` // This can give false positives and parse nullary enums, diff --git a/src/test/ui/parser/inline_const/const_match_pat_parses.rs b/src/test/ui/parser/inline_const/const_match_pat_parses.rs new file mode 100644 index 00000000000..97b05b0a1f2 --- /dev/null +++ b/src/test/ui/parser/inline_const/const_match_pat_parses.rs @@ -0,0 +1,20 @@ +// check-pass +// compile-flags: -Z parse-only + +#![feature(inline_const)] +const MMIO_BIT1: u8 = 4; +const MMIO_BIT2: u8 = 5; + +fn main() { + match read_mmio() { + 0 => {} + const { 1 << MMIO_BIT1 } => println!("FOO"), + const { 1 << MMIO_BIT2 } => println!("BAR"), + + _ => unreachable!(), + } +} + +fn read_mmio() -> u8 { + 1 << 5 +} diff --git a/src/test/ui/parser/issue-66357-unexpected-unreachable.rs b/src/test/ui/parser/issue-66357-unexpected-unreachable.rs index 5ec143fae23..7b95bc775ba 100644 --- a/src/test/ui/parser/issue-66357-unexpected-unreachable.rs +++ b/src/test/ui/parser/issue-66357-unexpected-unreachable.rs @@ -13,4 +13,4 @@ fn f() { |[](* } //~^ ERROR expected one of `,` or `:`, found `(` -//~| ERROR expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*` +//~| ERROR expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `const`, `mut`, `ref`, `|`, identifier, or path, found `*` diff --git a/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr b/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr index c3810999d23..5549f73920d 100644 --- a/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr +++ b/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr @@ -4,7 +4,7 @@ error: expected one of `,` or `:`, found `(` LL | fn f() { |[](* } | ^ expected one of `,` or `:` -error: expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*` +error: expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `const`, `mut`, `ref`, `|`, identifier, or path, found `*` --> $DIR/issue-66357-unexpected-unreachable.rs:14:14 | LL | fn f() { |[](* } From 66e254314d7fbb0defa2feb3b56ab212aafae933 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 6 Oct 2020 16:58:53 -0300 Subject: [PATCH 04/11] Lower inline const's AST to HIR --- compiler/rustc_ast_lowering/src/expr.rs | 5 +++-- compiler/rustc_ast_passes/src/ast_validation.rs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 1841a06eb89..0995231c639 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -30,8 +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::ConstBlock(ref anon_const) => { + let anon_const = self.lower_anon_const(anon_const); + hir::ExprKind::ConstBlock(anon_const) } ExprKind::Repeat(ref expr, ref count) => { let expr = self.lower_expr(expr); diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index d9791fe743c..b1c8e0ee727 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -287,7 +287,7 @@ impl<'a> AstValidator<'a> { // ``` fn check_expr_within_pat(&self, expr: &Expr, allow_paths: bool) { match expr.kind { - ExprKind::Lit(..) | ExprKind::Err => {} + ExprKind::Lit(..) | ExprKind::ConstBlock(..) | ExprKind::Err => {} ExprKind::Path(..) if allow_paths => {} ExprKind::Unary(UnOp::Neg, ref inner) if matches!(inner.kind, ExprKind::Lit(_)) => {} _ => self.err_handler().span_err( From fe922e567fd9768221e8092413f9492998a67451 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 6 Oct 2020 17:51:15 -0300 Subject: [PATCH 05/11] Lower inline const down to MIR --- compiler/rustc_hir/src/hir.rs | 4 ++++ compiler/rustc_hir/src/intravisit.rs | 1 + compiler/rustc_hir_pretty/src/lib.rs | 12 ++++++++++++ .../rustc_mir_build/src/build/expr/as_constant.rs | 1 + compiler/rustc_mir_build/src/build/expr/as_place.rs | 1 + compiler/rustc_mir_build/src/build/expr/as_rvalue.rs | 1 + compiler/rustc_mir_build/src/build/expr/category.rs | 4 +++- compiler/rustc_mir_build/src/build/expr/into.rs | 1 + compiler/rustc_mir_build/src/thir/cx/expr.rs | 6 ++++++ compiler/rustc_mir_build/src/thir/mod.rs | 3 +++ compiler/rustc_mir_build/src/thir/pattern/mod.rs | 5 +++++ compiler/rustc_passes/src/liveness.rs | 3 +++ 12 files changed, 41 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 52727e3a619..0ebed5c3480 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1361,6 +1361,7 @@ impl Expr<'_> { pub fn precedence(&self) -> ExprPrecedence { match self.kind { ExprKind::Box(_) => ExprPrecedence::Box, + ExprKind::ConstBlock(_) => ExprPrecedence::ConstBlock, ExprKind::Array(_) => ExprPrecedence::Array, ExprKind::Call(..) => ExprPrecedence::Call, ExprKind::MethodCall(..) => ExprPrecedence::MethodCall, @@ -1446,6 +1447,7 @@ impl Expr<'_> { | ExprKind::LlvmInlineAsm(..) | ExprKind::AssignOp(..) | ExprKind::Lit(_) + | ExprKind::ConstBlock(..) | ExprKind::Unary(..) | ExprKind::Box(..) | ExprKind::AddrOf(..) @@ -1501,6 +1503,8 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool { pub enum ExprKind<'hir> { /// A `box x` expression. Box(&'hir Expr<'hir>), + /// Allow anonymous constants from an inline `const` block + ConstBlock(AnonConst), /// An array (e.g., `[a, b, c, d]`). Array(&'hir [Expr<'hir>]), /// A function call. diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 820d664c07d..35615af0fc7 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1068,6 +1068,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) ExprKind::Array(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_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 57a38adc169..4686b4989ae 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1135,6 +1135,15 @@ impl<'a> State<'a> { self.end() } + fn print_expr_anon_const(&mut self, anon_const: &hir::AnonConst) { + self.ibox(INDENT_UNIT); + self.s.word_space("const"); + self.s.word("{"); + self.print_anon_const(anon_const); + self.s.word("}"); + self.end() + } + fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::AnonConst) { self.ibox(INDENT_UNIT); self.s.word("["); @@ -1287,6 +1296,9 @@ impl<'a> State<'a> { hir::ExprKind::Array(ref exprs) => { self.print_expr_vec(exprs); } + hir::ExprKind::ConstBlock(ref anon_const) => { + self.print_expr_anon_const(anon_const); + } hir::ExprKind::Repeat(ref element, ref count) => { self.print_expr_repeat(&element, count); } diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 244a70f83b0..3a36ad590c5 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -33,6 +33,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Constant { span, user_ty, literal } } ExprKind::StaticRef { literal, .. } => Constant { span, user_ty: None, literal }, + ExprKind::ConstBlock { value } => Constant { span, user_ty: None, literal: value }, _ => span_bug!(span, "expression is not a valid constant {:?}", kind), } } diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index 39dbb6dd3ff..443025c4f84 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -254,6 +254,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::Continue { .. } | ExprKind::Return { .. } | ExprKind::Literal { .. } + | ExprKind::ConstBlock { .. } | ExprKind::StaticRef { .. } | ExprKind::InlineAsm { .. } | ExprKind::LlvmInlineAsm { .. } diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 9c5fddc6b77..4033cc6cf46 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -234,6 +234,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } ExprKind::Yield { .. } | ExprKind::Literal { .. } + | ExprKind::ConstBlock { .. } | ExprKind::StaticRef { .. } | ExprKind::Block { .. } | ExprKind::Match { .. } diff --git a/compiler/rustc_mir_build/src/build/expr/category.rs b/compiler/rustc_mir_build/src/build/expr/category.rs index 9cabd186d84..ac5cf187aa0 100644 --- a/compiler/rustc_mir_build/src/build/expr/category.rs +++ b/compiler/rustc_mir_build/src/build/expr/category.rs @@ -68,7 +68,9 @@ impl Category { | ExprKind::ThreadLocalRef(_) | ExprKind::LlvmInlineAsm { .. } => Some(Category::Rvalue(RvalueFunc::AsRvalue)), - ExprKind::Literal { .. } | ExprKind::StaticRef { .. } => Some(Category::Constant), + ExprKind::ConstBlock { .. } | ExprKind::Literal { .. } | ExprKind::StaticRef { .. } => { + Some(Category::Constant) + } ExprKind::Loop { .. } | ExprKind::Block { .. } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index a12c22fb850..a268b0b46ff 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -454,6 +454,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::Array { .. } | ExprKind::Tuple { .. } | ExprKind::Closure { .. } + | ExprKind::ConstBlock { .. } | ExprKind::Literal { .. } | ExprKind::ThreadLocalRef(_) | ExprKind::StaticRef { .. } => { diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 13e69474cfb..731bd954246 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -511,6 +511,12 @@ fn make_mirror_unadjusted<'a, 'tcx>( inputs: asm.inputs_exprs.to_ref(), }, + hir::ExprKind::ConstBlock(ref anon_const) => { + let anon_const_def_id = cx.tcx.hir().local_def_id(anon_const.hir_id); + let value = ty::Const::from_anon_const(cx.tcx, anon_const_def_id); + + ExprKind::ConstBlock { value } + } // Now comes the rote stuff: hir::ExprKind::Repeat(ref v, ref count) => { let count_def_id = cx.tcx.hir().local_def_id(count.hir_id); diff --git a/compiler/rustc_mir_build/src/thir/mod.rs b/compiler/rustc_mir_build/src/thir/mod.rs index 4d57fd5c64f..f2a2ef0d8f2 100644 --- a/compiler/rustc_mir_build/src/thir/mod.rs +++ b/compiler/rustc_mir_build/src/thir/mod.rs @@ -232,6 +232,9 @@ crate enum ExprKind<'tcx> { Return { value: Option>, }, + ConstBlock { + value: &'tcx Const<'tcx>, + }, Repeat { value: ExprRef<'tcx>, count: &'tcx Const<'tcx>, diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index d46e9a98825..b05ddb3b464 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -856,6 +856,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { *self.lower_path(qpath, expr.hir_id, expr.span).kind } else { let (lit, neg) = match expr.kind { + hir::ExprKind::ConstBlock(ref anon_const) => { + let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id); + let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id); + return *self.const_to_pat(value, expr.hir_id, expr.span, false).kind; + } hir::ExprKind::Lit(ref lit) => (lit, false), hir::ExprKind::Unary(hir::UnOp::UnNeg, ref expr) => { let lit = match expr.kind { diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index e8b97d7dc7d..ae810b9e79a 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -432,6 +432,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> { | hir::ExprKind::Break(..) | hir::ExprKind::Continue(_) | hir::ExprKind::Lit(_) + | hir::ExprKind::ConstBlock(..) | hir::ExprKind::Ret(..) | hir::ExprKind::Block(..) | hir::ExprKind::Assign(..) @@ -1232,6 +1233,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } hir::ExprKind::Lit(..) + | hir::ExprKind::ConstBlock(..) | hir::ExprKind::Err | hir::ExprKind::Path(hir::QPath::TypeRelative(..)) | hir::ExprKind::Path(hir::QPath::LangItem(..)) => succ, @@ -1478,6 +1480,7 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) { | hir::ExprKind::Break(..) | hir::ExprKind::Continue(..) | hir::ExprKind::Lit(_) + | hir::ExprKind::ConstBlock(..) | hir::ExprKind::Block(..) | hir::ExprKind::AddrOf(..) | hir::ExprKind::Struct(..) From 85b5ce264324c75eb4c67849bc42de5526ed9208 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 6 Oct 2020 17:52:32 -0300 Subject: [PATCH 06/11] Typeck inline consts --- compiler/rustc_typeck/src/check/expr.rs | 1 + compiler/rustc_typeck/src/check/mod.rs | 16 +++++++++++++++- compiler/rustc_typeck/src/collect/type_of.rs | 6 ++++++ compiler/rustc_typeck/src/expr_use_visitor.rs | 5 ++++- compiler/rustc_typeck/src/mem_categorization.rs | 1 + 5 files changed, 27 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 179e383be2e..9990f86a36b 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -286,6 +286,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ExprKind::DropTemps(ref e) => self.check_expr_with_expectation(e, expected), ExprKind::Array(ref args) => self.check_expr_array(args, expected, expr), + ExprKind::ConstBlock(ref anon_const) => self.to_const(anon_const).ty, ExprKind::Repeat(ref element, ref count) => { self.check_expr_repeat(element, count, expected, expr) } diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 24ffe944128..8cf9abaa04e 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -111,6 +111,7 @@ use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{HirIdMap, Node}; use rustc_index::bit_set::BitSet; use rustc_index::vec::Idx; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::subst::GenericArgKind; @@ -528,7 +529,20 @@ fn typeck_with_fallback<'tcx>( hir::TyKind::Infer => Some(AstConv::ast_ty_to_ty(&fcx, ty)), _ => None, }) - .unwrap_or_else(fallback); + .unwrap_or_else(|| match tcx.hir().get(id) { + Node::AnonConst(_) => match tcx.hir().get(tcx.hir().get_parent_node(id)) { + Node::Expr(&hir::Expr { + kind: hir::ExprKind::ConstBlock(ref anon_const), + .. + }) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span, + }), + _ => fallback(), + }, + _ => fallback(), + }); + let expected_type = fcx.normalize_associated_types_in(body.value.span, &expected_type); fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized); diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 4b3250a1d44..5e8c6211408 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -309,6 +309,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { tcx.types.usize } + Node::Expr(&Expr { kind: ExprKind::ConstBlock(ref anon_const), .. }) + if anon_const.hir_id == hir_id => + { + tcx.typeck(def_id).node_type(anon_const.hir_id) + } + Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => tcx .adt_def(tcx.hir().get_parent_did(hir_id).to_def_id()) .repr diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index e16f26c3304..471909a092f 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -258,7 +258,10 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { self.consume_exprs(&ia.inputs_exprs); } - hir::ExprKind::Continue(..) | hir::ExprKind::Lit(..) | hir::ExprKind::Err => {} + hir::ExprKind::Continue(..) + | hir::ExprKind::Lit(..) + | hir::ExprKind::ConstBlock(..) + | hir::ExprKind::Err => {} hir::ExprKind::Loop(ref blk, _, _) => { self.walk_block(blk); diff --git a/compiler/rustc_typeck/src/mem_categorization.rs b/compiler/rustc_typeck/src/mem_categorization.rs index 04ead74936f..f6ac7aa9155 100644 --- a/compiler/rustc_typeck/src/mem_categorization.rs +++ b/compiler/rustc_typeck/src/mem_categorization.rs @@ -370,6 +370,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { | hir::ExprKind::Loop(..) | hir::ExprKind::Match(..) | hir::ExprKind::Lit(..) + | hir::ExprKind::ConstBlock(..) | hir::ExprKind::Break(..) | hir::ExprKind::Continue(..) | hir::ExprKind::Struct(..) From 54596c9b560472b682eaf2487672e135809b7583 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 6 Oct 2020 17:53:12 -0300 Subject: [PATCH 07/11] Add inline const tests --- src/test/ui/feature-gate-inline_const.rs | 2 +- src/test/ui/feature-gate-inline_const.stderr | 8 ++++++-- .../ui/inline-const/const-expr-array-init.rs | 9 +++++++++ .../const-expr-basic.rs} | 7 +++++-- .../ui/inline-const/const-expr-reference.rs | 14 +++++++++++++ src/test/ui/inline-const/const-match-pat.rs | 20 +++++++++++++++++++ .../inline_const/const_match_pat_parses.rs | 20 ------------------- 7 files changed, 55 insertions(+), 25 deletions(-) create mode 100644 src/test/ui/inline-const/const-expr-array-init.rs rename src/test/ui/{parser/inline_const/const_expr_parses.rs => inline-const/const-expr-basic.rs} (66%) create mode 100644 src/test/ui/inline-const/const-expr-reference.rs create mode 100644 src/test/ui/inline-const/const-match-pat.rs delete mode 100644 src/test/ui/parser/inline_const/const_match_pat_parses.rs diff --git a/src/test/ui/feature-gate-inline_const.rs b/src/test/ui/feature-gate-inline_const.rs index 76762489f3a..43ff90d234c 100644 --- a/src/test/ui/feature-gate-inline_const.rs +++ b/src/test/ui/feature-gate-inline_const.rs @@ -1,6 +1,6 @@ fn main() { let _ = const { - //~^ ERROR expected expression, found keyword `const` + //~^ ERROR inline-const is experimental [E0658] true }; } diff --git a/src/test/ui/feature-gate-inline_const.stderr b/src/test/ui/feature-gate-inline_const.stderr index b9498e22585..be2f567155c 100644 --- a/src/test/ui/feature-gate-inline_const.stderr +++ b/src/test/ui/feature-gate-inline_const.stderr @@ -1,8 +1,12 @@ -error: expected expression, found keyword `const` +error[E0658]: inline-const is experimental --> $DIR/feature-gate-inline_const.rs:2:13 | LL | let _ = const { - | ^^^^^ expected expression + | ^^^^^ + | + = note: see issue #76001 for more information + = help: add `#![feature(inline_const)]` to the crate attributes to enable error: aborting due to previous error +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/inline-const/const-expr-array-init.rs b/src/test/ui/inline-const/const-expr-array-init.rs new file mode 100644 index 00000000000..8a92cdbc0f9 --- /dev/null +++ b/src/test/ui/inline-const/const-expr-array-init.rs @@ -0,0 +1,9 @@ +// build-pass + +#![feature(inline_const)] + +use std::cell::Cell; + +fn main() { + let _x = [const { Cell::new(0) }; 20]; +} diff --git a/src/test/ui/parser/inline_const/const_expr_parses.rs b/src/test/ui/inline-const/const-expr-basic.rs similarity index 66% rename from src/test/ui/parser/inline_const/const_expr_parses.rs rename to src/test/ui/inline-const/const-expr-basic.rs index 5319db3482d..9349cee62d6 100644 --- a/src/test/ui/parser/inline_const/const_expr_parses.rs +++ b/src/test/ui/inline-const/const-expr-basic.rs @@ -1,5 +1,4 @@ -// check-pass -// compile-flags: -Z parse-only +// run-pass #![feature(inline_const)] fn foo() -> i32 { @@ -8,3 +7,7 @@ fn foo() -> i32 { x / 3 } } + +fn main() { + assert_eq!(5, foo()); +} diff --git a/src/test/ui/inline-const/const-expr-reference.rs b/src/test/ui/inline-const/const-expr-reference.rs new file mode 100644 index 00000000000..a54d879f69d --- /dev/null +++ b/src/test/ui/inline-const/const-expr-reference.rs @@ -0,0 +1,14 @@ +// run-pass + +#![feature(inline_const)] + +const fn bar() -> i32 { + const { + 2 + 3 + } +} + +fn main() { + let x: &'static i32 = &const{bar()}; + assert_eq!(&5, x); +} diff --git a/src/test/ui/inline-const/const-match-pat.rs b/src/test/ui/inline-const/const-match-pat.rs new file mode 100644 index 00000000000..d4761398d73 --- /dev/null +++ b/src/test/ui/inline-const/const-match-pat.rs @@ -0,0 +1,20 @@ +// run-pass + +#![feature(inline_const)] +const MMIO_BIT1: u8 = 4; +const MMIO_BIT2: u8 = 5; + +fn main() { + let s = match read_mmio() { + 0 => "FOO", + const { 1 << MMIO_BIT1 } => "BAR", + const { 1 << MMIO_BIT2 } => "BAZ", + _ => unreachable!(), + }; + + assert_eq!("BAZ", s); +} + +fn read_mmio() -> i32 { + 1 << 5 +} diff --git a/src/test/ui/parser/inline_const/const_match_pat_parses.rs b/src/test/ui/parser/inline_const/const_match_pat_parses.rs deleted file mode 100644 index 97b05b0a1f2..00000000000 --- a/src/test/ui/parser/inline_const/const_match_pat_parses.rs +++ /dev/null @@ -1,20 +0,0 @@ -// check-pass -// compile-flags: -Z parse-only - -#![feature(inline_const)] -const MMIO_BIT1: u8 = 4; -const MMIO_BIT2: u8 = 5; - -fn main() { - match read_mmio() { - 0 => {} - const { 1 << MMIO_BIT1 } => println!("FOO"), - const { 1 << MMIO_BIT2 } => println!("BAR"), - - _ => unreachable!(), - } -} - -fn read_mmio() -> u8 { - 1 << 5 -} From 27411d6d2bf282d017a464d28098823bc1a16adb Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 6 Oct 2020 18:51:31 -0300 Subject: [PATCH 08/11] Handle ExprKind::ConstBlock on clippy --- src/tools/clippy/clippy_lints/src/loops.rs | 1 + src/tools/clippy/clippy_lints/src/utils/author.rs | 5 +++++ src/tools/clippy/clippy_lints/src/utils/eager_or_lazy.rs | 2 +- src/tools/clippy/clippy_lints/src/utils/hir_utils.rs | 3 +++ src/tools/clippy/clippy_lints/src/utils/inspector.rs | 5 +++++ src/tools/clippy/clippy_lints/src/utils/sugg.rs | 2 ++ 6 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/tools/clippy/clippy_lints/src/loops.rs b/src/tools/clippy/clippy_lints/src/loops.rs index 61b63597b16..4fdcaca8f60 100644 --- a/src/tools/clippy/clippy_lints/src/loops.rs +++ b/src/tools/clippy/clippy_lints/src/loops.rs @@ -742,6 +742,7 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult { | ExprKind::Closure(_, _, _, _, _) | ExprKind::LlvmInlineAsm(_) | ExprKind::Path(_) + | ExprKind::ConstBlock(_) | ExprKind::Lit(_) | ExprKind::Err => NeverLoopResult::Otherwise, } diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 6eda6d1fa83..89425437eee 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -506,6 +506,11 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { println!(" if {}.len() == {};", fields_pat, fields.len()); println!(" // unimplemented: field checks"); }, + ExprKind::ConstBlock(_) => { + let value_pat = self.next("value"); + println!("Const({})", value_pat); + self.current = value_pat; + }, // FIXME: compute length (needs type info) ExprKind::Repeat(ref value, _) => { let value_pat = self.next("value"); diff --git a/src/tools/clippy/clippy_lints/src/utils/eager_or_lazy.rs b/src/tools/clippy/clippy_lints/src/utils/eager_or_lazy.rs index 6938d9971d9..27e9567740d 100644 --- a/src/tools/clippy/clippy_lints/src/utils/eager_or_lazy.rs +++ b/src/tools/clippy/clippy_lints/src/utils/eager_or_lazy.rs @@ -23,7 +23,7 @@ use rustc_middle::hir::map::Map; /// This function is named so to stress that it isn't exhaustive and returns FNs. fn identify_some_pure_patterns(expr: &Expr<'_>) -> bool { match expr.kind { - ExprKind::Lit(..) | ExprKind::Path(..) | ExprKind::Field(..) => true, + ExprKind::Lit(..) | ExprKind::ConstBlock(..) | ExprKind::Path(..) | ExprKind::Field(..) => true, ExprKind::AddrOf(_, _, addr_of_expr) => identify_some_pure_patterns(addr_of_expr), ExprKind::Tup(tup_exprs) => tup_exprs.iter().all(|expr| identify_some_pure_patterns(expr)), ExprKind::Struct(_, fields, expr) => { diff --git a/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs b/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs index c7263f48965..c9e639e8728 100644 --- a/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs +++ b/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs @@ -559,6 +559,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_name(path.ident.name); self.hash_exprs(args); }, + ExprKind::ConstBlock(ref l_id) => { + self.hash_body(l_id.body); + }, ExprKind::Repeat(ref e, ref l_id) => { self.hash_expr(e); self.hash_body(l_id.body); diff --git a/src/tools/clippy/clippy_lints/src/utils/inspector.rs b/src/tools/clippy/clippy_lints/src/utils/inspector.rs index 4701a3f26e6..93bd8299446 100644 --- a/src/tools/clippy/clippy_lints/src/utils/inspector.rs +++ b/src/tools/clippy/clippy_lints/src/utils/inspector.rs @@ -338,6 +338,11 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) { print_expr(cx, base, indent + 1); } }, + hir::ExprKind::ConstBlock(ref anon_const) => { + println!("{}ConstBlock", ind); + println!("{}anon_const:", ind); + print_expr(cx, &cx.tcx.hir().body(anon_const.body).value, indent + 1); + }, hir::ExprKind::Repeat(ref val, ref anon_const) => { println!("{}Repeat", ind); println!("{}value:", ind); diff --git a/src/tools/clippy/clippy_lints/src/utils/sugg.rs b/src/tools/clippy/clippy_lints/src/utils/sugg.rs index ec8b7e59b59..a2a1d109c9a 100644 --- a/src/tools/clippy/clippy_lints/src/utils/sugg.rs +++ b/src/tools/clippy/clippy_lints/src/utils/sugg.rs @@ -110,6 +110,7 @@ impl<'a> Sugg<'a> { | hir::ExprKind::Index(..) | hir::ExprKind::InlineAsm(..) | hir::ExprKind::LlvmInlineAsm(..) + | hir::ExprKind::ConstBlock(..) | hir::ExprKind::Lit(..) | hir::ExprKind::Loop(..) | hir::ExprKind::MethodCall(..) @@ -157,6 +158,7 @@ impl<'a> Sugg<'a> { | ast::ExprKind::Index(..) | ast::ExprKind::InlineAsm(..) | ast::ExprKind::LlvmInlineAsm(..) + | ast::ExprKind::ConstBlock(..) | ast::ExprKind::Lit(..) | ast::ExprKind::Loop(..) | ast::ExprKind::MacCall(..) From 03defb627cd39a3de720f1f829678b9f0d581e8e Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 9 Oct 2020 19:20:06 -0300 Subject: [PATCH 09/11] Add check_generic_arg early pass --- compiler/rustc_ast/src/visit.rs | 17 ++++++++++++----- compiler/rustc_lint/src/early.rs | 5 +++++ compiler/rustc_lint/src/passes.rs | 2 ++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 3da078b760b..507b49616ea 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -200,11 +200,7 @@ pub trait Visitor<'ast>: Sized { walk_generic_args(self, path_span, generic_args) } fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) { - match generic_arg { - GenericArg::Lifetime(lt) => self.visit_lifetime(lt), - GenericArg::Type(ty) => self.visit_ty(ty), - GenericArg::Const(ct) => self.visit_anon_const(ct), - } + walk_generic_arg(self, generic_arg) } fn visit_assoc_ty_constraint(&mut self, constraint: &'ast AssocTyConstraint) { walk_assoc_ty_constraint(self, constraint) @@ -486,6 +482,17 @@ where } } +pub fn walk_generic_arg<'a, V>(visitor: &mut V, generic_arg: &'a GenericArg) +where + V: Visitor<'a>, +{ + match generic_arg { + GenericArg::Lifetime(lt) => visitor.visit_lifetime(lt), + GenericArg::Type(ty) => visitor.visit_ty(ty), + GenericArg::Const(ct) => visitor.visit_anon_const(ct), + } +} + pub fn walk_assoc_ty_constraint<'a, V: Visitor<'a>>( visitor: &mut V, constraint: &'a AssocTyConstraint, diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 998676d44d2..4c8baa49edf 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -195,6 +195,11 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> run_early_pass!(self, check_expr_post, e); } + fn visit_generic_arg(&mut self, arg: &'a ast::GenericArg) { + run_early_pass!(self, check_generic_arg, arg); + ast_visit::walk_generic_arg(self, arg); + } + fn visit_generic_param(&mut self, param: &'a ast::GenericParam) { run_early_pass!(self, check_generic_param, param); ast_visit::walk_generic_param(self, param); diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index 159286c13a4..828f283d2a9 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -33,6 +33,7 @@ macro_rules! late_lint_methods { fn check_expr(a: &$hir hir::Expr<$hir>); fn check_expr_post(a: &$hir hir::Expr<$hir>); fn check_ty(a: &$hir hir::Ty<$hir>); + fn check_generic_arg(a: &$hir hir::GenericArg<$hir>); fn check_generic_param(a: &$hir hir::GenericParam<$hir>); fn check_generics(a: &$hir hir::Generics<$hir>); fn check_where_predicate(a: &$hir hir::WherePredicate<$hir>); @@ -176,6 +177,7 @@ macro_rules! early_lint_methods { fn check_expr(a: &ast::Expr); fn check_expr_post(a: &ast::Expr); fn check_ty(a: &ast::Ty); + fn check_generic_arg(a: &ast::GenericArg); fn check_generic_param(a: &ast::GenericParam); fn check_generics(a: &ast::Generics); fn check_where_predicate(a: &ast::WherePredicate); From 547e5eb49884e521b8a75bf13ad76eb421ca4688 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 9 Oct 2020 19:21:40 -0300 Subject: [PATCH 10/11] Do not check unused braces on inline consts --- compiler/rustc_lint/src/unused.rs | 77 ++++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 3abd9a6325d..4bff7f317cb 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -839,10 +839,6 @@ impl EarlyLintPass for UnusedParens { } } - fn check_anon_const(&mut self, cx: &EarlyContext<'_>, c: &ast::AnonConst) { - self.check_unused_delims_expr(cx, &c.value, UnusedDelimsCtx::AnonConst, false, None, None); - } - fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) { if let StmtKind::Local(ref local) = s.kind { self.check_unused_parens_pat(cx, &local.pat, false, false); @@ -965,13 +961,6 @@ impl UnusedDelimLint for UnusedBraces { if !Self::is_expr_delims_necessary(expr, followed_by_block) && (ctx != UnusedDelimsCtx::AnonConst || matches!(expr.kind, ast::ExprKind::Lit(_))) - // array length expressions are checked during `check_anon_const` and `check_ty`, - // once as `ArrayLenExpr` and once as `AnonConst`. - // - // As we do not want to lint this twice, we do not emit an error for - // `ArrayLenExpr` if `AnonConst` would do the same. - && (ctx != UnusedDelimsCtx::ArrayLenExpr - || !matches!(expr.kind, ast::ExprKind::Lit(_))) && !cx.sess().source_map().is_multiline(value.span) && value.attrs.is_empty() && !value.span.from_expansion() @@ -999,21 +988,54 @@ impl UnusedDelimLint for UnusedBraces { } impl EarlyLintPass for UnusedBraces { - fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { - ::check_expr(self, cx, e) - } - - fn check_anon_const(&mut self, cx: &EarlyContext<'_>, c: &ast::AnonConst) { - self.check_unused_delims_expr(cx, &c.value, UnusedDelimsCtx::AnonConst, false, None, None); - } - fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) { ::check_stmt(self, cx, s) } + fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { + ::check_expr(self, cx, e); + + if let ExprKind::Repeat(_, ref anon_const) = e.kind { + self.check_unused_delims_expr( + cx, + &anon_const.value, + UnusedDelimsCtx::AnonConst, + false, + None, + None, + ); + } + } + + fn check_generic_arg(&mut self, cx: &EarlyContext<'_>, arg: &ast::GenericArg) { + if let ast::GenericArg::Const(ct) = arg { + self.check_unused_delims_expr( + cx, + &ct.value, + UnusedDelimsCtx::AnonConst, + false, + None, + None, + ); + } + } + + fn check_variant(&mut self, cx: &EarlyContext<'_>, v: &ast::Variant) { + if let Some(anon_const) = &v.disr_expr { + self.check_unused_delims_expr( + cx, + &anon_const.value, + UnusedDelimsCtx::AnonConst, + false, + None, + None, + ); + } + } + fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) { - if let &ast::TyKind::Paren(ref r) = &ty.kind { - if let ast::TyKind::Array(_, ref len) = r.kind { + match ty.kind { + ast::TyKind::Array(_, ref len) => { self.check_unused_delims_expr( cx, &len.value, @@ -1023,6 +1045,19 @@ impl EarlyLintPass for UnusedBraces { None, ); } + + ast::TyKind::Typeof(ref anon_const) => { + self.check_unused_delims_expr( + cx, + &anon_const.value, + UnusedDelimsCtx::AnonConst, + false, + None, + None, + ); + } + + _ => {} } } From 03321b8cca91cd5d1f9c82a447add69329e52cea Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 16 Oct 2020 18:15:57 -0300 Subject: [PATCH 11/11] Add inline const to INCOMPLETE_FEATURES --- compiler/rustc_feature/src/active.rs | 1 + src/test/ui/inline-const/const-expr-array-init.rs | 1 + src/test/ui/inline-const/const-expr-basic.rs | 1 + src/test/ui/inline-const/const-expr-reference.rs | 1 + src/test/ui/inline-const/const-match-pat.rs | 1 + 5 files changed, 5 insertions(+) diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 9a70fa4d589..c13fe2ae280 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -621,6 +621,7 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[ sym::const_trait_bound_opt_out, sym::lazy_normalization_consts, sym::specialization, + sym::inline_const, ]; /// Some features are not allowed to be used together at the same time, if diff --git a/src/test/ui/inline-const/const-expr-array-init.rs b/src/test/ui/inline-const/const-expr-array-init.rs index 8a92cdbc0f9..8bb5dab1fa0 100644 --- a/src/test/ui/inline-const/const-expr-array-init.rs +++ b/src/test/ui/inline-const/const-expr-array-init.rs @@ -1,5 +1,6 @@ // build-pass +#![allow(incomplete_features)] #![feature(inline_const)] use std::cell::Cell; diff --git a/src/test/ui/inline-const/const-expr-basic.rs b/src/test/ui/inline-const/const-expr-basic.rs index 9349cee62d6..9254c96a1e7 100644 --- a/src/test/ui/inline-const/const-expr-basic.rs +++ b/src/test/ui/inline-const/const-expr-basic.rs @@ -1,5 +1,6 @@ // run-pass +#![allow(incomplete_features)] #![feature(inline_const)] fn foo() -> i32 { const { diff --git a/src/test/ui/inline-const/const-expr-reference.rs b/src/test/ui/inline-const/const-expr-reference.rs index a54d879f69d..747f14e4bd0 100644 --- a/src/test/ui/inline-const/const-expr-reference.rs +++ b/src/test/ui/inline-const/const-expr-reference.rs @@ -1,5 +1,6 @@ // run-pass +#![allow(incomplete_features)] #![feature(inline_const)] const fn bar() -> i32 { diff --git a/src/test/ui/inline-const/const-match-pat.rs b/src/test/ui/inline-const/const-match-pat.rs index d4761398d73..c0dc90d971a 100644 --- a/src/test/ui/inline-const/const-match-pat.rs +++ b/src/test/ui/inline-const/const-match-pat.rs @@ -1,5 +1,6 @@ // run-pass +#![allow(incomplete_features)] #![feature(inline_const)] const MMIO_BIT1: u8 = 4; const MMIO_BIT2: u8 = 5;