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