Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document const functions #440

Merged
merged 13 commits into from
Oct 13, 2018
58 changes: 57 additions & 1 deletion src/items/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
>       [_BlockExpression_]
>
> _FunctionFront_ :\
> &nbsp;&nbsp; `unsafe`<sup>?</sup> (`extern` _Abi_<sup>?</sup>)<sup>?</sup>
> &nbsp;&nbsp; `const`<sup>?</sup> `unsafe`<sup>?</sup> (`extern` _Abi_<sup>?</sup>)<sup>?</sup>
>
> _Abi_ :\
> &nbsp;&nbsp; [STRING_LITERAL] | [RAW_STRING_LITERAL]
Expand Down Expand Up @@ -160,6 +160,60 @@ attributes], [`must_use`], [the procedural macro attributes], [the testing
attributes], and [the optimization hint
attributes].

## Const functions

Functions can be `const`, meaning they can be called from within array length
expressions and the initializer of constants, statics and enum discriminants.
When called from such a so-called "const context", the function is interpreted
by the compiler at compile time. The interpretation happens in the environment
of the compilation target and not the host. So `usize` is `32` bits if you are
compiling against a `32` bit system, irrelevant of whether you are building on
a `64` bit or a `32` bit system.

If a `const fn` is called outside a "const context", it is indistinguishable
from any other function. You can freely do anything with a `const fn` that
you can do with a regular function.

`const fn`s have various restrictions to makes sure that you cannot define a
`const fn` that can't be evaluated at compile-time. It is, for example, not
possible to write a random number generator as a const fn. Calling a
const fn at compile-time will always yield the same result as calling it at
runtime, even when called multiple times. There's one exception to this rule:
if you are doing complex floating point operations in extreme situations,
then you might get (very slightly) different results.
It is adviseable to not make array lengths and enum discriminants depend
on floating point computations.

Exhaustive list of permitted structures in `const fn`:

This comment was marked as resolved.

This comment was marked as resolved.


> **Note**: this list is more restrictive than what you can write in
regular constants
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing >.


* type parameters where the parameters only have any [trait bounds]
of the following kind:
* lifetimes
* `Sized` or [`?Sized`]

This means that `<T: 'a + ?Sized>`, `<T: 'b + Sized>` and `<T>`
are all permitted.

This rule also applies to type parameters of impl blocks that
contain `const fn` methods

* arithmetic and comparison operators on integers
* all boolean operators except for `&&` and `||` which are banned since
they are short-circuiting.
* any kind of aggregate constructor (array, `struct`, `enum`, tuple, ...)
* calls to other *safe* `const fn`s (whether by function call or method call)
* index expressions on arrays and slices
* field accesses on structs and tuples
* reading from constants (but not statics, not even taking a reference to a static)
* `&` and `*` (only dereferencing of references, not raw pointers)
* casts except for raw pointer to integer casts
* `const unsafe fn` is allowed, but the body must consist of safe operations
only and you won't be able to call the `const unsafe fn` from within another
`const fn` even if you use `unsafe`

[IDENTIFIER]: identifiers.html
[RAW_STRING_LITERAL]: tokens.html#raw-string-literals
[STRING_LITERAL]: tokens.html#string-literals
Expand Down Expand Up @@ -187,3 +241,5 @@ attributes].
[`doc`]: attributes.html#documentation
[`must_use`]: attributes.html#must_use
[patterns]: patterns.html
[`?Sized`]: trait-bounds.html#sized
[trait bounds]: trait-bounds.html