Skip to content

Const function #447

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

Merged
merged 3 commits into from
Oct 15, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/const_eval.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@ to be ran.
* [Grouped] expressions.
* [Cast] expressions, except pointer to address and
function pointer to address casts.
* calls of const functions and const methods
* Calls of const functions and const methods

## Const context

A _const context_ is one of the following:

* [array type length expressions]
* repeat expression length expessions
* the initializer of
* [Array type length expressions]
* Repeat expression length expessions
* The initializer of
* [constants]
* [statics]
* [enum discriminants]
Expand Down
2 changes: 1 addition & 1 deletion src/expressions/array-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ order they are written.

Alternatively there can be exactly two expressions inside the brackets,
separated by a semi-colon. The expression after the `;` must be a have type
`usize` and be a [constant expression](expressions.html#constant-expressions),
`usize` and be a [constant expression],
such as a [literal](tokens.html#literals) or a [constant
item](items/constant-items.html). `[a; b]` creates an array containing `b`
copies of the value of `a`. If the expression after the semi-colon has a value
Expand Down
4 changes: 2 additions & 2 deletions src/items/associated-items.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ let _: f64 = f64::from_i32(42);
### Methods

> _Method_ :\
> &nbsp;&nbsp; [_FunctionFront_] `fn` [IDENTIFIER]&nbsp;[_Generics_]<sup>?</sup>\
> &nbsp;&nbsp; [_FunctionQualifiers_] `fn` [IDENTIFIER]&nbsp;[_Generics_]<sup>?</sup>\
> &nbsp;&nbsp; &nbsp;&nbsp; `(` _SelfParam_ (`,` [_FunctionParam_])<sup>\*</sup> `,`<sup>?</sup> `)`\
> &nbsp;&nbsp; &nbsp;&nbsp; [_FunctionReturnType_]<sup>?</sup> [_WhereClause_]<sup>?</sup>\
> &nbsp;&nbsp; &nbsp;&nbsp; [_BlockExpression_]
Expand Down Expand Up @@ -287,8 +287,8 @@ fn main() {
```

[_BlockExpression_]: expressions/block-expr.html
[_FunctionFront_]: items/functions.html
[_FunctionParam_]: items/functions.html
[_FunctionQualifiers_]: items/functions.html
[_FunctionReturnType_]: items/functions.html
[_Generics_]: items/generics.html
[_Lifetime_]: trait-bounds.html
Expand Down
9 changes: 5 additions & 4 deletions src/items/enumerations.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ then the discriminant can be directly chosen and accessed.

These enumerations can be cast to integer types with the `as` operator by a
[numeric cast]. The enumeration can optionally specify which integer each
discriminant gets by following the variant name with `=` and then an integer
literal. If the first variant in the declaration is unspecified, then it is set
to zero. For every unspecified discriminant, it is set to one higher than the
previous variant in the declaration.
discriminant gets by following the variant name with `=` followed by a [constant
expression]. If the first variant in the declaration is unspecified, then it is
set to zero. For every other unspecified discriminant, it is set to one higher
than the previous variant in the declaration.

```rust
enum Foo {
Expand Down Expand Up @@ -141,6 +141,7 @@ enum ZeroVariants {}
[`mem::discriminant`]: ../std/mem/fn.discriminant.html
[numeric cast]: expressions/operator-expr.html#semantics
[`repr` attribute]: attributes.html#ffi-attributes
[constant expression]: const_eval.html#constant-expressions
[default representation]: type-layout.html#the-default-representation
[primitive representation]: type-layout.html#primitive-representations
[`C` representation]: type-layout.html#the-c-representation
101 changes: 50 additions & 51 deletions src/items/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

> **<sup>Syntax</sup>**\
> _Function_ :\
> &nbsp;&nbsp; _FunctionFront_ `fn` [IDENTIFIER]&nbsp;[_Generics_]<sup>?</sup>\
> &nbsp;&nbsp; _FunctionQualifiers_ `fn` [IDENTIFIER]&nbsp;[_Generics_]<sup>?</sup>\
> &nbsp;&nbsp; &nbsp;&nbsp; `(` _FunctionParameters_<sup>?</sup> `)`\
> &nbsp;&nbsp; &nbsp;&nbsp; _FunctionReturnType_<sup>?</sup> [_WhereClause_]<sup>?</sup>\
> &nbsp;&nbsp; &nbsp;&nbsp; [_BlockExpression_]
>
> _FunctionFront_ :\
> _FunctionQualifiers_ :\
> &nbsp;&nbsp; `const`<sup>?</sup> `unsafe`<sup>?</sup> (`extern` _Abi_<sup>?</sup>)<sup>?</sup>
>
> _Abi_ :\
Expand Down Expand Up @@ -114,7 +114,7 @@ opposite functionality to [external blocks]. Whereas external
blocks allow Rust code to call foreign code, extern functions with bodies
defined in Rust code _can be called by foreign code_. They are defined in the
same way as any other Rust function, except that they have the `extern`
modifier.
qualifier.

```rust
// Declares an extern fn, the ABI defaults to "C"
Expand All @@ -137,58 +137,34 @@ As non-Rust calling conventions do not support unwinding, unwinding past the end
of an extern function will cause the process to abort. In LLVM, this is
implemented by executing an illegal instruction.

## Attributes on functions

[Outer attributes][attributes] are allowed on functions. [Inner
attributes][attributes] are allowed directly after the `{` inside its [block].

This example shows an inner attribute on a function. The function will only be
available while running tests.

```
fn test_only() {
#![test]
}
```

> Note: Except for lints, it is idiomatic to only use outer attributes on
> function items.

The attributes that have meaning on a function are [`cfg`], [`deprecated`],
[`doc`], `export_name`, `link_section`, `no_mangle`, [the lint check
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
[const contexts]. When called from a 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.
Functions qualified with the `const` keyword are const functions. _Const
funcions_ can be called from within [const contexts]. When called from a 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 function is called outside a "const context", it is indistinguishable
If a const function is called outside a [const context], it is indistinguishable
from any other function. You can freely do anything with a const function that
you can do with a regular function.

const functions have various restrictions to makes sure that you cannot define a
const function that can't be evaluated at compile-time. It is, for example, not
possible to write a random number generator as a const function. Calling a
const function 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.
Const functions have various restrictions to makes sure that they can't be
evaluated at compile-time. It is, for example, not possible to write a random
number generator as a const function. Calling a const function 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 functions:

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

* type parameters where the parameters only have any [trait bounds]
* Type parameters where the parameters only have any [trait bounds]
of the following kind:
* lifetimes
* `Sized` or [`?Sized`]
Expand All @@ -199,20 +175,43 @@ Exhaustive list of permitted structures in const functions:
This rule also applies to type parameters of impl blocks that
contain const methods

* arithmetic and comparison operators on integers
* all boolean operators except for `&&` and `||` which are banned since
* 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 functions (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)
* Any kind of aggregate constructor (array, `struct`, `enum`, tuple, ...)
* Calls to other *safe* const functions (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
* 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 function even if you use `unsafe`

## Attributes on functions

[Outer attributes][attributes] are allowed on functions. [Inner
attributes][attributes] are allowed directly after the `{` inside its [block].

This example shows an inner attribute on a function. The function will only be
available while running tests.

```
fn test_only() {
#![test]
}
```

> Note: Except for lints, it is idiomatic to only use outer attributes on
> function items.

The attributes that have meaning on a function are [`cfg`], [`deprecated`],
[`doc`], `export_name`, `link_section`, `no_mangle`, [the lint check
attributes], [`must_use`], [the procedural macro attributes], [the testing
attributes], and [the optimization hint
attributes].

[IDENTIFIER]: identifiers.html
[RAW_STRING_LITERAL]: tokens.html#raw-string-literals
[STRING_LITERAL]: tokens.html#string-literals
Expand Down
6 changes: 3 additions & 3 deletions src/items/traits.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
> &nbsp;&nbsp; &nbsp;&nbsp; _TraitMethodDecl_ ( `;` | [_BlockExpression_] )
>
> _TraitFunctionDecl_ :\
> &nbsp;&nbsp; [_FunctionFront_] `fn` [IDENTIFIER]&nbsp;[_Generics_]<sup>?</sup>\
> &nbsp;&nbsp; [_FunctionQualifiers_] `fn` [IDENTIFIER]&nbsp;[_Generics_]<sup>?</sup>\
> &nbsp;&nbsp; &nbsp;&nbsp; `(` _TraitFunctionParameters_<sup>?</sup> `)`\
> &nbsp;&nbsp; &nbsp;&nbsp; [_FunctionReturnType_]<sup>?</sup> [_WhereClause_]<sup>?</sup>
>
> _TraitMethodDecl_ :\
> &nbsp;&nbsp; [_FunctionFront_] `fn` [IDENTIFIER]&nbsp;[_Generics_]<sup>?</sup>\
> &nbsp;&nbsp; [_FunctionQualifiers_] `fn` [IDENTIFIER]&nbsp;[_Generics_]<sup>?</sup>\
> &nbsp;&nbsp; &nbsp;&nbsp; `(` [_SelfParam_] (`,` _TraitFunctionParam_)<sup>\*</sup> `,`<sup>?</sup> `)`\
> &nbsp;&nbsp; &nbsp;&nbsp; [_FunctionReturnType_]<sup>?</sup> [_WhereClause_]<sup>?</sup>
>
Expand Down Expand Up @@ -201,8 +201,8 @@ trait T {
[WildcardPattern]: patterns.html#wildcard-pattern
[_BlockExpression_]: expressions/block-expr.html
[_Expression_]: expressions.html
[_FunctionFront_]: items/functions.html
[_FunctionParam_]: items/functions.html
[_FunctionQualifiers_]: items/functions.html
[_FunctionReturnType_]: items/functions.html
[_Generics_]: items/generics.html
[_OuterAttribute_]: attributes.html
Expand Down
4 changes: 2 additions & 2 deletions src/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ All function items implement [`Fn`], [`FnMut`], [`FnOnce`], [`Copy`],

> **<sup>Syntax</sup>**\
> _BareFunctionType_ :\
> &nbsp;&nbsp; [_ForLifetimes_]<sup>?</sup> [_FunctionFront_] `fn`\
> &nbsp;&nbsp; [_ForLifetimes_]<sup>?</sup> [_FunctionQualifiers_] `fn`\
> &nbsp;&nbsp; &nbsp;&nbsp; `(` _FunctionParametersMaybeNamedVariadic_<sup>?</sup> `)` _BareFunctionReturnType_<sup>?</sup>
>
> _BareFunctionReturnType_:\
Expand Down Expand Up @@ -862,8 +862,8 @@ impl Printable for String {
[_BareFunctionType_]: #function-pointer-types
[_Expression_]: expressions.html
[_ForLifetimes_]: items/generics.html#where-clauses
[_FunctionFront_]: items/functions.html
[_FunctionParametersMaybeNamed_]: items/functions.html
[_FunctionQualifiers_]: items/functions.html
[_ImplTraitTypeOneBound_]: #impl-trait
[_ImplTraitType_]: #impl-trait
[_InferredType_]: #inferred-type
Expand Down