-
Notifications
You must be signed in to change notification settings - Fork 493
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
Changes from 2 commits
20221fb
41cbeb0
4e7bb21
310812a
eee560c
d9c33a4
17485ac
9b2fb7a
6bc96f8
3e3be42
3a7b6d8
b89691f
259ac5f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ | |
> [_BlockExpression_] | ||
> | ||
> _FunctionFront_ :\ | ||
> `unsafe`<sup>?</sup> (`extern` _Abi_<sup>?</sup>)<sup>?</sup> | ||
> `const`<sup>?</sup> `unsafe`<sup>?</sup> (`extern` _Abi_<sup>?</sup>)<sup>?</sup> | ||
> | ||
> _Abi_ :\ | ||
> [STRING_LITERAL] | [RAW_STRING_LITERAL] | ||
|
@@ -160,6 +160,38 @@ 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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Your `"const context" is already defined as a constant expression. That said, the bit about interpretation using the target's environment is useful to add there. And the explicit list of where constant expressions must be evaluated at compile-time is 💯. I like the example as well, but it should probably say what the target's pointer size is before saying the size of usize. E.g. "For example, if you are compiling on a 32-bit OS, then There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not quite. "const context" requires a constant expression. The definition in the documentation you linked is also incomplete. I'll add an entry and make both documentations point to it. |
||
|
||
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 fn. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Last "fn" -> "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. You will, for example, never be able 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 if you call it 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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. concision nit: "that you cannot define a tone nit: Let's not blame the reader for having the audacity of trying to write an RNG as a constant function. Perhaps they're merely curious if somebody could, as it'd be something important to keep in mind if it was possible. "For example, a random number generator cannot be written as a constant function." nit: "if you call" -> "when called" Since floating point is not permitted currently, the floating point section can be removed until it is decided what we do with it. We don't document the future. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. only floating point math is forbidden. You can define |
||
|
||
Exhaustive list of permitted structures in `const fn`: | ||
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
Sorry, something went wrong. |
||
|
||
1. type parameters where the parameters only have any of the following as part of their bounds (either on `where` or directly on the parameters): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The parenthetical can be replaced by just making "bounds" a link to |
||
1. lifetimes | ||
2. `Sized` | ||
|
||
This means that `<T: 'a + ?Sized>`, `<T: 'b + Sized>` and `<T>` are all permitted. | ||
Note that `?Sized` is the absence of a constraint when bounds have been fully elaborated | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This note can replaced by putting |
||
which includes adding implicit `Sized` bounds. | ||
This entails that permitting `Sized` + lifetimes allows the above examples. | ||
|
||
This rule also applies to type parameters of items that contain `const fn`s. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By "contain", I presume you mean implementations and traits. But do you also mean e.g. functions that contain a block expression that contains a constant function? Listing them out would help readability here. |
||
|
||
2. arithmetic and comparison operators on integers | ||
3. all boolean operators except for `&&` and `||` which are banned since they are short-circuiting. | ||
4. any kind of aggregate constructor (array, `struct`, `enum`, tuple, ...) | ||
5. calls to other *safe* `const fn`s (methods and functions) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: "(methods and functions)" -> "whether by function call or method call |
||
6. index operations on arrays and slices | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Index expressions? Or does operations mean more than just the syntactic |
||
7. field accesses on structs and tuples | ||
8. reading from constants (but not statics, not even taking a reference to a static) | ||
9. `&` and `*` (only dereferencing of references, not raw pointers) | ||
10. casts except for raw pointer to integer casts | ||
11. `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 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's actually give a name and definition with this. You informally call it
`const fn`
in future paragraphs, but the name should be prose, not code, so I think "const function" or "constant function" (or both?) works. We should also be more explicit about how they are defined. I propose the following, but feel to tweak it:The name should then be used in other parts of the text as appropriate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to avoid calling these "constant functions" because it gives the impression that the functions are somehow constant; they aren't. They are pure functions (at least currently and besides some weird business with floating points). They also can't always be called in
const ITEM = the_const_fn(...);
contexts if given runtime arguments and they can always be called in runtime contexts.If you must have a name in prose (which strikes me as less formal) then I would call it "const functions".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
constant expression
section currently states "The following expressions are constant expressions, so long as any operands are also constant expressions and do not cause anyDrop::drop
calls to be ran.". It's not the most precise wording, but it's supposed to handle that.All constant expressions can be.
We want to have the name for other documentation none-the-less. And we want the name so that we can then discuss it in the prose further on.
This comment was marked as outdated.
Sorry, something went wrong.