Skip to content

Commit 0d06bdf

Browse files
authored
Merge pull request #440 from oli-obk/patch-1
Document const functions
2 parents 084fa05 + 259ac5f commit 0d06bdf

File tree

4 files changed

+142
-38
lines changed

4 files changed

+142
-38
lines changed

src/SUMMARY.md

+2
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@
9191
- [Behavior considered undefined](behavior-considered-undefined.md)
9292
- [Behavior not considered unsafe](behavior-not-considered-unsafe.md)
9393

94+
- [Constant Evalutation](const_eval.md)
95+
9496
[Appendix: Influences](influences.md)
9597

9698
[Appendix: As-yet-undocumented Features](undocumented.md)

src/const_eval.md

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Constant evaluation
2+
3+
Constant evaluation is the process of computing the result of
4+
[expressions] during compilation. Only a subset of all expressions
5+
can be evaluated at compile-time.
6+
7+
## Constant expressions
8+
9+
Certain types of expressions can be evaluated at compile time. These are called
10+
_constant expressions_ and are required in const contexts. In
11+
other places, such as in [`let` statements](statements.html#let-statements),
12+
constant expressions may be evaluated at compile time. If errors, such as out
13+
of bounds [array indexing] or [overflow] occurs,
14+
then it is a compiler error if the value must be evaluated at compile time,
15+
otherwise it is just a warning, but the code will most likely panic when run.
16+
17+
The following expressions are constant expressions, so long as any operands are
18+
also constant expressions and do not cause any [`Drop::drop`][destructors] calls
19+
to be ran.
20+
21+
* [Literals].
22+
* [Paths] to [functions](items/functions.html) and constants.
23+
Recursively defining constants is not allowed.
24+
* [Tuple expressions].
25+
* [Array expressions].
26+
* [Struct] expressions.
27+
* [Enum variant] expressions.
28+
* [Block expressions], including `unsafe` blocks, which only contain items and
29+
possibly a constant tail expression.
30+
* [Field] expressions.
31+
* Index expressions, [array indexing] or [slice] with a `usize`.
32+
* [Range expressions].
33+
* [Closure expressions] which don't capture variables from the environment.
34+
* Built in [negation], [arithmetic, logical], [comparison] or [lazy boolean]
35+
operators used on integer and floating point types, `bool` and `char`.
36+
* Shared [borrow]s, except if applied to a type with [interior mutability].
37+
* The [dereference operator].
38+
* [Grouped] expressions.
39+
* [Cast] expressions, except pointer to address and
40+
function pointer to address casts.
41+
* calls of const functions and const methods
42+
43+
## Const context
44+
45+
A _const context_ is one of the following:
46+
47+
* [array type length expressions]
48+
* repeat expression length expessions
49+
* the initializer of
50+
* [constants]
51+
* [statics]
52+
* [enum discriminants]
53+
54+
[array type length expressions]: types.html#array-and-slice-types
55+
[enum discriminants]: items/enumerations.html#custom-discriminant-values-for-field-less-enumerations
56+
[constants]: items/constant-items.html
57+
[statics]: items/static-items.html
58+
[expressions]: expressions.html
59+
[array indexing]: expressions/array-expr.html#array-and-slice-indexing-expressions
60+
[overflow]: expressions/operator-expr.html#overflow
61+
[destructors]: destructors.html
62+
[literals]: expressions/literal-expr.html
63+
[paths]: expressions/path-expr.html
64+
[tuple expressions]: expressions/tuple-expr.html
65+
[array expressions]: expressions/array-expr.html
66+
[struct]: expressions/struct-expr.html
67+
[enum variant]: expressions/enum-variant-expr.html
68+
[block expressions]: expressions/block-expr.html
69+
[field]: expressions/field-expr.html
70+
[array indexing]: expressions/array-expr.html#array-and-slice-indexing-expressions
71+
[slice]: types.html#array-and-slice-types
72+
[range expressions]: expressions/range-expr.html
73+
[closure expressions]: expressions/closure-expr.html
74+
[negation]: expressions/operator-expr.html#negation-operators
75+
[arithmetic, logical]: expressions/operator-expr.html#arithmetic-and-logical-binary-operators
76+
[comparison]: expressions/operator-expr.html#comparison-operators
77+
[lazy boolean]: expressions/operator-expr.html#lazy-boolean-operators
78+
[borrow]: expressions/operator-expr.html#borrow-operators
79+
[interior mutability]: interior-mutability.html
80+
[dereference operator]: expressions/operator-expr.html#the-dereference-operator
81+
[grouped]: expressions/grouped-expr.html
82+
[cast]: expressions/operator-expr.html#type-cast-expressions

src/expressions.md

+1-37
Original file line numberDiff line numberDiff line change
@@ -229,43 +229,6 @@ Implicit borrows may be taken in the following expressions:
229229
* Operands of [comparison].
230230
* Left operands of the [compound assignment].
231231

232-
## Constant expressions
233-
234-
Certain types of expressions can be evaluated at compile time. These are called
235-
_constant expressions_. Certain places, such as in
236-
[constants](items/constant-items.html) and [statics](items/static-items.html),
237-
require a constant expression, and are always evaluated at compile time. In
238-
other places, such as in [`let` statements](statements.html#let-statements),
239-
constant expressions may be evaluated at compile time. If errors, such as out
240-
of bounds [array indexing] or [overflow] occurs,
241-
then it is a compiler error if the value must be evaluated at compile time,
242-
otherwise it is just a warning, but the code will most likely panic when run.
243-
244-
The following expressions are constant expressions, so long as any operands are
245-
also constant expressions and do not cause any [`Drop::drop`][destructors] calls
246-
to be ran.
247-
248-
* [Literals].
249-
* [Paths] to [functions](items/functions.html) and constants.
250-
Recursively defining constants is not allowed.
251-
* [Tuple expressions].
252-
* [Array expressions].
253-
* [Struct] expressions.
254-
* [Enum variant] expressions.
255-
* [Block expressions], including `unsafe` blocks, which only contain items and
256-
possibly a constant tail expression.
257-
* [Field] expressions.
258-
* Index expressions, [array indexing] or [slice] with a `usize`.
259-
* [Range expressions].
260-
* [Closure expressions] which don't capture variables from the environment.
261-
* Built in [negation], [arithmetic, logical], [comparison] or [lazy boolean]
262-
operators used on integer and floating point types, `bool` and `char`.
263-
* Shared [borrow]s, except if applied to a type with [interior mutability].
264-
* The [dereference operator].
265-
* [Grouped] expressions.
266-
* [Cast] expressions, except pointer to address and
267-
function pointer to address casts.
268-
269232
## Overloading Traits
270233

271234
Many of the following operators and expressions can also be overloaded for
@@ -313,6 +276,7 @@ exist in `core::ops` and `core::cmp` with the same names.
313276
[let]: statements.html#let-statements
314277
[let statement]: statements.html#let-statements
315278
[Mutable `static` items]: items/static-items.html#mutable-statics
279+
[const contexts]: const_eval.html
316280
[slice]: types.html#array-and-slice-types
317281
[static variables]: items/static-items.html
318282
[Temporary values]: #temporary-lifetimes

src/items/functions.md

+57-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
>       [_BlockExpression_]
99
>
1010
> _FunctionFront_ :\
11-
> &nbsp;&nbsp; `unsafe`<sup>?</sup> (`extern` _Abi_<sup>?</sup>)<sup>?</sup>
11+
> &nbsp;&nbsp; `const`<sup>?</sup> `unsafe`<sup>?</sup> (`extern` _Abi_<sup>?</sup>)<sup>?</sup>
1212
>
1313
> _Abi_ :\
1414
> &nbsp;&nbsp; [STRING_LITERAL] | [RAW_STRING_LITERAL]
@@ -160,6 +160,59 @@ attributes], [`must_use`], [the procedural macro attributes], [the testing
160160
attributes], and [the optimization hint
161161
attributes].
162162

163+
## Const functions
164+
165+
Functions can be `const`, meaning they can be called from within
166+
[const contexts]. When called from a const context, the function is interpreted
167+
by the compiler at compile time. The interpretation happens in the environment
168+
of the compilation target and not the host. So `usize` is `32` bits if you are
169+
compiling against a `32` bit system, irrelevant of whether you are building on
170+
a `64` bit or a `32` bit system.
171+
172+
If a const function is called outside a "const context", it is indistinguishable
173+
from any other function. You can freely do anything with a const function that
174+
you can do with a regular function.
175+
176+
const functions have various restrictions to makes sure that you cannot define a
177+
const function that can't be evaluated at compile-time. It is, for example, not
178+
possible to write a random number generator as a const function. Calling a
179+
const function at compile-time will always yield the same result as calling it at
180+
runtime, even when called multiple times. There's one exception to this rule:
181+
if you are doing complex floating point operations in extreme situations,
182+
then you might get (very slightly) different results.
183+
It is adviseable to not make array lengths and enum discriminants depend
184+
on floating point computations.
185+
186+
Exhaustive list of permitted structures in const functions:
187+
188+
> **Note**: this list is more restrictive than what you can write in
189+
> regular constants
190+
191+
* type parameters where the parameters only have any [trait bounds]
192+
of the following kind:
193+
* lifetimes
194+
* `Sized` or [`?Sized`]
195+
196+
This means that `<T: 'a + ?Sized>`, `<T: 'b + Sized>` and `<T>`
197+
are all permitted.
198+
199+
This rule also applies to type parameters of impl blocks that
200+
contain const methods
201+
202+
* arithmetic and comparison operators on integers
203+
* all boolean operators except for `&&` and `||` which are banned since
204+
they are short-circuiting.
205+
* any kind of aggregate constructor (array, `struct`, `enum`, tuple, ...)
206+
* calls to other *safe* const functions (whether by function call or method call)
207+
* index expressions on arrays and slices
208+
* field accesses on structs and tuples
209+
* reading from constants (but not statics, not even taking a reference to a static)
210+
* `&` and `*` (only dereferencing of references, not raw pointers)
211+
* casts except for raw pointer to integer casts
212+
* `const unsafe fn` is allowed, but the body must consist of safe operations
213+
only and you won't be able to call the `const unsafe fn` from within another
214+
const function even if you use `unsafe`
215+
163216
[IDENTIFIER]: identifiers.html
164217
[RAW_STRING_LITERAL]: tokens.html#raw-string-literals
165218
[STRING_LITERAL]: tokens.html#string-literals
@@ -170,6 +223,7 @@ attributes].
170223
[_Statement_]: statements.html
171224
[_Type_]: types.html
172225
[_WhereClause_]: items/generics.html#where-clauses
226+
[const contexts]: const_eval.html
173227
[external blocks]: items/external-blocks.html
174228
[path]: paths.html
175229
[block]: expressions/block-expr.html
@@ -187,3 +241,5 @@ attributes].
187241
[`doc`]: attributes.html#documentation
188242
[`must_use`]: attributes.html#must_use
189243
[patterns]: patterns.html
244+
[`?Sized`]: trait-bounds.html#sized
245+
[trait bounds]: trait-bounds.html

0 commit comments

Comments
 (0)