Skip to content

Commit 6af9846

Browse files
committed
Auto merge of #77124 - spastorino:const-exprs-rfc-2920, r=oli-obk
Implement const expressions and patterns (RFC 2920) cc `@ecstatic-morse` `@lcnr` `@oli-obk` `@petrochenkov`
2 parents dda2b5e + 03321b8 commit 6af9846

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+298
-33
lines changed

compiler/rustc_ast/src/ast.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1152,6 +1152,7 @@ impl Expr {
11521152
match self.kind {
11531153
ExprKind::Box(_) => ExprPrecedence::Box,
11541154
ExprKind::Array(_) => ExprPrecedence::Array,
1155+
ExprKind::ConstBlock(_) => ExprPrecedence::ConstBlock,
11551156
ExprKind::Call(..) => ExprPrecedence::Call,
11561157
ExprKind::MethodCall(..) => ExprPrecedence::MethodCall,
11571158
ExprKind::Tup(_) => ExprPrecedence::Tup,
@@ -1207,6 +1208,8 @@ pub enum ExprKind {
12071208
Box(P<Expr>),
12081209
/// An array (`[a, b, c, d]`)
12091210
Array(Vec<P<Expr>>),
1211+
/// Allow anonymous constants from an inline `const` block
1212+
ConstBlock(AnonConst),
12101213
/// A function call
12111214
///
12121215
/// The first field resolves to the function itself,

compiler/rustc_ast/src/mut_visit.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,9 @@ pub fn noop_visit_expr<T: MutVisitor>(
11061106
match kind {
11071107
ExprKind::Box(expr) => vis.visit_expr(expr),
11081108
ExprKind::Array(exprs) => visit_exprs(exprs, vis),
1109+
ExprKind::ConstBlock(anon_const) => {
1110+
vis.visit_anon_const(anon_const);
1111+
}
11091112
ExprKind::Repeat(expr, count) => {
11101113
vis.visit_expr(expr);
11111114
vis.visit_anon_const(count);

compiler/rustc_ast/src/token.rs

+1
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ pub fn ident_can_begin_expr(name: Symbol, span: Span, is_raw: bool) -> bool {
153153
kw::Do,
154154
kw::Box,
155155
kw::Break,
156+
kw::Const,
156157
kw::Continue,
157158
kw::False,
158159
kw::For,

compiler/rustc_ast/src/util/parser.rs

+2
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ pub enum ExprPrecedence {
282282
ForLoop,
283283
Loop,
284284
Match,
285+
ConstBlock,
285286
Block,
286287
TryBlock,
287288
Struct,
@@ -346,6 +347,7 @@ impl ExprPrecedence {
346347
ExprPrecedence::ForLoop |
347348
ExprPrecedence::Loop |
348349
ExprPrecedence::Match |
350+
ExprPrecedence::ConstBlock |
349351
ExprPrecedence::Block |
350352
ExprPrecedence::TryBlock |
351353
ExprPrecedence::Async |

compiler/rustc_ast/src/visit.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -200,11 +200,7 @@ pub trait Visitor<'ast>: Sized {
200200
walk_generic_args(self, path_span, generic_args)
201201
}
202202
fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) {
203-
match generic_arg {
204-
GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
205-
GenericArg::Type(ty) => self.visit_ty(ty),
206-
GenericArg::Const(ct) => self.visit_anon_const(ct),
207-
}
203+
walk_generic_arg(self, generic_arg)
208204
}
209205
fn visit_assoc_ty_constraint(&mut self, constraint: &'ast AssocTyConstraint) {
210206
walk_assoc_ty_constraint(self, constraint)
@@ -486,6 +482,17 @@ where
486482
}
487483
}
488484

485+
pub fn walk_generic_arg<'a, V>(visitor: &mut V, generic_arg: &'a GenericArg)
486+
where
487+
V: Visitor<'a>,
488+
{
489+
match generic_arg {
490+
GenericArg::Lifetime(lt) => visitor.visit_lifetime(lt),
491+
GenericArg::Type(ty) => visitor.visit_ty(ty),
492+
GenericArg::Const(ct) => visitor.visit_anon_const(ct),
493+
}
494+
}
495+
489496
pub fn walk_assoc_ty_constraint<'a, V: Visitor<'a>>(
490497
visitor: &mut V,
491498
constraint: &'a AssocTyConstraint,
@@ -717,6 +724,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
717724
ExprKind::Array(ref subexpressions) => {
718725
walk_list!(visitor, visit_expr, subexpressions);
719726
}
727+
ExprKind::ConstBlock(ref anon_const) => visitor.visit_anon_const(anon_const),
720728
ExprKind::Repeat(ref element, ref count) => {
721729
visitor.visit_expr(element);
722730
visitor.visit_anon_const(count)

compiler/rustc_ast_lowering/src/expr.rs

+4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
3030
let kind = match e.kind {
3131
ExprKind::Box(ref inner) => hir::ExprKind::Box(self.lower_expr(inner)),
3232
ExprKind::Array(ref exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
33+
ExprKind::ConstBlock(ref anon_const) => {
34+
let anon_const = self.lower_anon_const(anon_const);
35+
hir::ExprKind::ConstBlock(anon_const)
36+
}
3337
ExprKind::Repeat(ref expr, ref count) => {
3438
let expr = self.lower_expr(expr);
3539
let count = self.lower_anon_const(count);

compiler/rustc_ast_passes/src/ast_validation.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ impl<'a> AstValidator<'a> {
287287
// ```
288288
fn check_expr_within_pat(&self, expr: &Expr, allow_paths: bool) {
289289
match expr.kind {
290-
ExprKind::Lit(..) | ExprKind::Err => {}
290+
ExprKind::Lit(..) | ExprKind::ConstBlock(..) | ExprKind::Err => {}
291291
ExprKind::Path(..) if allow_paths => {}
292292
ExprKind::Unary(UnOp::Neg, ref inner) if matches!(inner.kind, ExprKind::Lit(_)) => {}
293293
_ => self.err_handler().span_err(

compiler/rustc_ast_passes/src/feature_gate.rs

+1
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
629629
gate_all!(const_trait_bound_opt_out, "`?const` on trait bounds is experimental");
630630
gate_all!(const_trait_impl, "const trait impls are experimental");
631631
gate_all!(half_open_range_patterns, "half-open range patterns are unstable");
632+
gate_all!(inline_const, "inline-const is experimental");
632633

633634
// All uses of `gate_all!` below this point were added in #65742,
634635
// and subsequently disabled (with the non-early gating readded).

compiler/rustc_ast_pretty/src/pprust/state.rs

+11
Original file line numberDiff line numberDiff line change
@@ -1714,6 +1714,14 @@ impl<'a> State<'a> {
17141714
self.end();
17151715
}
17161716

1717+
fn print_expr_anon_const(&mut self, expr: &ast::AnonConst, attrs: &[ast::Attribute]) {
1718+
self.ibox(INDENT_UNIT);
1719+
self.s.word("const");
1720+
self.print_inner_attributes_inline(attrs);
1721+
self.print_expr(&expr.value);
1722+
self.end();
1723+
}
1724+
17171725
fn print_expr_repeat(
17181726
&mut self,
17191727
element: &ast::Expr,
@@ -1890,6 +1898,9 @@ impl<'a> State<'a> {
18901898
ast::ExprKind::Array(ref exprs) => {
18911899
self.print_expr_vec(&exprs[..], attrs);
18921900
}
1901+
ast::ExprKind::ConstBlock(ref anon_const) => {
1902+
self.print_expr_anon_const(anon_const, attrs);
1903+
}
18931904
ast::ExprKind::Repeat(ref element, ref count) => {
18941905
self.print_expr_repeat(element, count, attrs);
18951906
}

compiler/rustc_feature/src/active.rs

+4
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,9 @@ declare_features! (
598598
/// Allows `#[instruction_set(_)]` attribute
599599
(active, isa_attribute, "1.48.0", Some(74727), None),
600600

601+
/// Allow anonymous constants from an inline `const` block
602+
(active, inline_const, "1.49.0", Some(76001), None),
603+
601604
// -------------------------------------------------------------------------
602605
// feature-group-end: actual feature gates
603606
// -------------------------------------------------------------------------
@@ -618,6 +621,7 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
618621
sym::const_trait_bound_opt_out,
619622
sym::lazy_normalization_consts,
620623
sym::specialization,
624+
sym::inline_const,
621625
];
622626

623627
/// Some features are not allowed to be used together at the same time, if

compiler/rustc_hir/src/hir.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1361,6 +1361,7 @@ impl Expr<'_> {
13611361
pub fn precedence(&self) -> ExprPrecedence {
13621362
match self.kind {
13631363
ExprKind::Box(_) => ExprPrecedence::Box,
1364+
ExprKind::ConstBlock(_) => ExprPrecedence::ConstBlock,
13641365
ExprKind::Array(_) => ExprPrecedence::Array,
13651366
ExprKind::Call(..) => ExprPrecedence::Call,
13661367
ExprKind::MethodCall(..) => ExprPrecedence::MethodCall,
@@ -1446,6 +1447,7 @@ impl Expr<'_> {
14461447
| ExprKind::LlvmInlineAsm(..)
14471448
| ExprKind::AssignOp(..)
14481449
| ExprKind::Lit(_)
1450+
| ExprKind::ConstBlock(..)
14491451
| ExprKind::Unary(..)
14501452
| ExprKind::Box(..)
14511453
| ExprKind::AddrOf(..)
@@ -1501,6 +1503,8 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool {
15011503
pub enum ExprKind<'hir> {
15021504
/// A `box x` expression.
15031505
Box(&'hir Expr<'hir>),
1506+
/// Allow anonymous constants from an inline `const` block
1507+
ConstBlock(AnonConst),
15041508
/// An array (e.g., `[a, b, c, d]`).
15051509
Array(&'hir [Expr<'hir>]),
15061510
/// A function call.

compiler/rustc_hir/src/intravisit.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1068,6 +1068,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
10681068
ExprKind::Array(subexpressions) => {
10691069
walk_list!(visitor, visit_expr, subexpressions);
10701070
}
1071+
ExprKind::ConstBlock(ref anon_const) => visitor.visit_anon_const(anon_const),
10711072
ExprKind::Repeat(ref element, ref count) => {
10721073
visitor.visit_expr(element);
10731074
visitor.visit_anon_const(count)

compiler/rustc_hir_pretty/src/lib.rs

+12
Original file line numberDiff line numberDiff line change
@@ -1135,6 +1135,15 @@ impl<'a> State<'a> {
11351135
self.end()
11361136
}
11371137

1138+
fn print_expr_anon_const(&mut self, anon_const: &hir::AnonConst) {
1139+
self.ibox(INDENT_UNIT);
1140+
self.s.word_space("const");
1141+
self.s.word("{");
1142+
self.print_anon_const(anon_const);
1143+
self.s.word("}");
1144+
self.end()
1145+
}
1146+
11381147
fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::AnonConst) {
11391148
self.ibox(INDENT_UNIT);
11401149
self.s.word("[");
@@ -1287,6 +1296,9 @@ impl<'a> State<'a> {
12871296
hir::ExprKind::Array(ref exprs) => {
12881297
self.print_expr_vec(exprs);
12891298
}
1299+
hir::ExprKind::ConstBlock(ref anon_const) => {
1300+
self.print_expr_anon_const(anon_const);
1301+
}
12901302
hir::ExprKind::Repeat(ref element, ref count) => {
12911303
self.print_expr_repeat(&element, count);
12921304
}

compiler/rustc_lint/src/early.rs

+5
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,11 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
195195
run_early_pass!(self, check_expr_post, e);
196196
}
197197

198+
fn visit_generic_arg(&mut self, arg: &'a ast::GenericArg) {
199+
run_early_pass!(self, check_generic_arg, arg);
200+
ast_visit::walk_generic_arg(self, arg);
201+
}
202+
198203
fn visit_generic_param(&mut self, param: &'a ast::GenericParam) {
199204
run_early_pass!(self, check_generic_param, param);
200205
ast_visit::walk_generic_param(self, param);

compiler/rustc_lint/src/passes.rs

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ macro_rules! late_lint_methods {
3333
fn check_expr(a: &$hir hir::Expr<$hir>);
3434
fn check_expr_post(a: &$hir hir::Expr<$hir>);
3535
fn check_ty(a: &$hir hir::Ty<$hir>);
36+
fn check_generic_arg(a: &$hir hir::GenericArg<$hir>);
3637
fn check_generic_param(a: &$hir hir::GenericParam<$hir>);
3738
fn check_generics(a: &$hir hir::Generics<$hir>);
3839
fn check_where_predicate(a: &$hir hir::WherePredicate<$hir>);
@@ -176,6 +177,7 @@ macro_rules! early_lint_methods {
176177
fn check_expr(a: &ast::Expr);
177178
fn check_expr_post(a: &ast::Expr);
178179
fn check_ty(a: &ast::Ty);
180+
fn check_generic_arg(a: &ast::GenericArg);
179181
fn check_generic_param(a: &ast::GenericParam);
180182
fn check_generics(a: &ast::Generics);
181183
fn check_where_predicate(a: &ast::WherePredicate);

compiler/rustc_lint/src/unused.rs

+53-18
Original file line numberDiff line numberDiff line change
@@ -839,10 +839,6 @@ impl EarlyLintPass for UnusedParens {
839839
}
840840
}
841841

842-
fn check_anon_const(&mut self, cx: &EarlyContext<'_>, c: &ast::AnonConst) {
843-
self.check_unused_delims_expr(cx, &c.value, UnusedDelimsCtx::AnonConst, false, None, None);
844-
}
845-
846842
fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
847843
if let StmtKind::Local(ref local) = s.kind {
848844
self.check_unused_parens_pat(cx, &local.pat, false, false);
@@ -965,13 +961,6 @@ impl UnusedDelimLint for UnusedBraces {
965961
if !Self::is_expr_delims_necessary(expr, followed_by_block)
966962
&& (ctx != UnusedDelimsCtx::AnonConst
967963
|| matches!(expr.kind, ast::ExprKind::Lit(_)))
968-
// array length expressions are checked during `check_anon_const` and `check_ty`,
969-
// once as `ArrayLenExpr` and once as `AnonConst`.
970-
//
971-
// As we do not want to lint this twice, we do not emit an error for
972-
// `ArrayLenExpr` if `AnonConst` would do the same.
973-
&& (ctx != UnusedDelimsCtx::ArrayLenExpr
974-
|| !matches!(expr.kind, ast::ExprKind::Lit(_)))
975964
&& !cx.sess().source_map().is_multiline(value.span)
976965
&& value.attrs.is_empty()
977966
&& !value.span.from_expansion()
@@ -999,21 +988,54 @@ impl UnusedDelimLint for UnusedBraces {
999988
}
1000989

1001990
impl EarlyLintPass for UnusedBraces {
991+
fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
992+
<Self as UnusedDelimLint>::check_stmt(self, cx, s)
993+
}
994+
1002995
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
1003-
<Self as UnusedDelimLint>::check_expr(self, cx, e)
996+
<Self as UnusedDelimLint>::check_expr(self, cx, e);
997+
998+
if let ExprKind::Repeat(_, ref anon_const) = e.kind {
999+
self.check_unused_delims_expr(
1000+
cx,
1001+
&anon_const.value,
1002+
UnusedDelimsCtx::AnonConst,
1003+
false,
1004+
None,
1005+
None,
1006+
);
1007+
}
10041008
}
10051009

1006-
fn check_anon_const(&mut self, cx: &EarlyContext<'_>, c: &ast::AnonConst) {
1007-
self.check_unused_delims_expr(cx, &c.value, UnusedDelimsCtx::AnonConst, false, None, None);
1010+
fn check_generic_arg(&mut self, cx: &EarlyContext<'_>, arg: &ast::GenericArg) {
1011+
if let ast::GenericArg::Const(ct) = arg {
1012+
self.check_unused_delims_expr(
1013+
cx,
1014+
&ct.value,
1015+
UnusedDelimsCtx::AnonConst,
1016+
false,
1017+
None,
1018+
None,
1019+
);
1020+
}
10081021
}
10091022

1010-
fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
1011-
<Self as UnusedDelimLint>::check_stmt(self, cx, s)
1023+
fn check_variant(&mut self, cx: &EarlyContext<'_>, v: &ast::Variant) {
1024+
if let Some(anon_const) = &v.disr_expr {
1025+
self.check_unused_delims_expr(
1026+
cx,
1027+
&anon_const.value,
1028+
UnusedDelimsCtx::AnonConst,
1029+
false,
1030+
None,
1031+
None,
1032+
);
1033+
}
10121034
}
10131035

10141036
fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
1015-
if let &ast::TyKind::Paren(ref r) = &ty.kind {
1016-
if let ast::TyKind::Array(_, ref len) = r.kind {
1037+
match ty.kind {
1038+
ast::TyKind::Array(_, ref len) => {
10171039
self.check_unused_delims_expr(
10181040
cx,
10191041
&len.value,
@@ -1023,6 +1045,19 @@ impl EarlyLintPass for UnusedBraces {
10231045
None,
10241046
);
10251047
}
1048+
1049+
ast::TyKind::Typeof(ref anon_const) => {
1050+
self.check_unused_delims_expr(
1051+
cx,
1052+
&anon_const.value,
1053+
UnusedDelimsCtx::AnonConst,
1054+
false,
1055+
None,
1056+
None,
1057+
);
1058+
}
1059+
1060+
_ => {}
10261061
}
10271062
}
10281063

compiler/rustc_mir_build/src/build/expr/as_constant.rs

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
3333
Constant { span, user_ty, literal }
3434
}
3535
ExprKind::StaticRef { literal, .. } => Constant { span, user_ty: None, literal },
36+
ExprKind::ConstBlock { value } => Constant { span, user_ty: None, literal: value },
3637
_ => span_bug!(span, "expression is not a valid constant {:?}", kind),
3738
}
3839
}

compiler/rustc_mir_build/src/build/expr/as_place.rs

+1
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
254254
| ExprKind::Continue { .. }
255255
| ExprKind::Return { .. }
256256
| ExprKind::Literal { .. }
257+
| ExprKind::ConstBlock { .. }
257258
| ExprKind::StaticRef { .. }
258259
| ExprKind::InlineAsm { .. }
259260
| ExprKind::LlvmInlineAsm { .. }

compiler/rustc_mir_build/src/build/expr/as_rvalue.rs

+1
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
234234
}
235235
ExprKind::Yield { .. }
236236
| ExprKind::Literal { .. }
237+
| ExprKind::ConstBlock { .. }
237238
| ExprKind::StaticRef { .. }
238239
| ExprKind::Block { .. }
239240
| ExprKind::Match { .. }

compiler/rustc_mir_build/src/build/expr/category.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@ impl Category {
6868
| ExprKind::ThreadLocalRef(_)
6969
| ExprKind::LlvmInlineAsm { .. } => Some(Category::Rvalue(RvalueFunc::AsRvalue)),
7070

71-
ExprKind::Literal { .. } | ExprKind::StaticRef { .. } => Some(Category::Constant),
71+
ExprKind::ConstBlock { .. } | ExprKind::Literal { .. } | ExprKind::StaticRef { .. } => {
72+
Some(Category::Constant)
73+
}
7274

7375
ExprKind::Loop { .. }
7476
| ExprKind::Block { .. }

compiler/rustc_mir_build/src/build/expr/into.rs

+1
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
454454
| ExprKind::Array { .. }
455455
| ExprKind::Tuple { .. }
456456
| ExprKind::Closure { .. }
457+
| ExprKind::ConstBlock { .. }
457458
| ExprKind::Literal { .. }
458459
| ExprKind::ThreadLocalRef(_)
459460
| ExprKind::StaticRef { .. } => {

0 commit comments

Comments
 (0)