diff --git a/src/const_eval.md b/src/const_eval.md
index 34e34d703..af8d4862c 100644
--- a/src/const_eval.md
+++ b/src/const_eval.md
@@ -27,7 +27,7 @@ to be run.
* [Tuple expressions].
* [Array expressions].
* [Struct] expressions.
-* [Block expressions], including `unsafe` blocks.
+* [Block expressions], including `unsafe` and `const` blocks.
* [let statements] and thus irrefutable [patterns], including mutable bindings
* [assignment expressions]
* [compound assignment expressions]
@@ -59,6 +59,7 @@ A _const context_ is one of the following:
* [statics]
* [enum discriminants]
* A [const generic argument]
+* A [const block]
## Const Functions
@@ -106,6 +107,7 @@ Conversely, the following are possible in a const function, but not in a const c
[cast]: expressions/operator-expr.md#type-cast-expressions
[closure expressions]: expressions/closure-expr.md
[comparison]: expressions/operator-expr.md#comparison-operators
+[const block]: expressions/block-expr.md#const-blocks
[const functions]: items/functions.md#const-functions
[const generic argument]: items/generics.md#const-generics
[const generic parameters]: items/generics.md#const-generics
diff --git a/src/expressions.md b/src/expressions.md
index ad4cc5f54..9e10dcea3 100644
--- a/src/expressions.md
+++ b/src/expressions.md
@@ -35,6 +35,7 @@
> [_OuterAttribute_]\*[†](#expression-attributes)\
> (\
> [_BlockExpression_]\
+> | [_ConstBlockExpression_]\
> | [_UnsafeBlockExpression_]\
> | [_LoopExpression_]\
> | [_IfExpression_]\
@@ -311,6 +312,7 @@ They are never allowed before:
[_ClosureExpression_]: expressions/closure-expr.md
[_ComparisonExpression_]: expressions/operator-expr.md#comparison-operators
[_CompoundAssignmentExpression_]: expressions/operator-expr.md#compound-assignment-expressions
+[_ConstBlockExpression_]: expressions/block-expr.md#const-blocks
[_ContinueExpression_]: expressions/loop-expr.md#continue-expressions
[_FieldExpression_]: expressions/field-expr.md
[_GroupedExpression_]: expressions/grouped-expr.md
diff --git a/src/expressions/block-expr.md b/src/expressions/block-expr.md
index bd9c0a623..890cf856d 100644
--- a/src/expressions/block-expr.md
+++ b/src/expressions/block-expr.md
@@ -117,6 +117,44 @@ loop {
}
```
+## `const` blocks
+
+> **Syntax**\
+> _ConstBlockExpression_ :\
+> `const` _BlockExpression_
+
+A *const block* is a variant of a block expression which evaluates at compile-time instead of at runtime.
+
+Const blocks allows you to define a constant value without having to define new [constant items], and thus they are also sometimes referred as *inline consts*.
+It also supports type inference so there is no need to specify the type, unlike [constant items].
+
+Const blocks have the ability to reference generic parameters in scope, unlike [free][free item] constant items.
+They are desugared to associated constant items with generic parameters in scope.
+For example, this code:
+
+```rust
+fn foo() -> usize {
+ const { std::mem::size_of::() + 1 }
+}
+```
+
+is equivalent to:
+
+```rust
+fn foo() -> usize {
+ {
+ struct Const(T);
+ impl Const {
+ const CONST: usize = std::mem::size_of::() + 1;
+ }
+ Const::::CONST
+ }
+}
+```
+
+This also means that const blocks are treated similarly to associated constants.
+For example, they are not guaranteed to be evaluated when the enclosing function is unused.
+
## `unsafe` blocks
> **Syntax**\
@@ -181,6 +219,8 @@ fn is_unix_platform() -> bool {
[array expressions]: array-expr.md
[call expressions]: call-expr.md
[capture modes]: ../types/closure.md#capture-modes
+[constant items]: ../items/constant-items.md
+[free item]: ../glossary.md#free-item
[function]: ../items/functions.md
[inner attributes]: ../attributes.md
[method]: ../items/associated-items.md#methods
diff --git a/src/macros-by-example.md b/src/macros-by-example.md
index 51aa919fc..014fb852b 100644
--- a/src/macros-by-example.md
+++ b/src/macros-by-example.md
@@ -146,6 +146,7 @@ For reasons of backwards compatibility, though `_` [is also an
expression][_UnderscoreExpression_], a standalone underscore is not matched by
the `expr` fragment specifier. However, `_` is matched by the `expr` fragment
specifier when it appears as a subexpression.
+For the same reason, a standalone [const block] is not matched but it is matched when appearing as a subexpression.
> **Edition Differences**: Starting with the 2021 edition, `pat` fragment-specifiers match top-level or-patterns (that is, they accept [_Pattern_]).
>
@@ -492,6 +493,7 @@ expansions, taking separators into account. This means:
For more detail, see the [formal specification].
+[const block]: expressions/block-expr.md#const-blocks
[Hygiene]: #hygiene
[IDENTIFIER]: identifiers.md
[IDENTIFIER_OR_KEYWORD]: identifiers.md