-
Notifications
You must be signed in to change notification settings - Fork 524
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
Start a chapter about the evolving const effect system #1808
Changes from 1 commit
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 | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,60 @@ | ||||||
# Effects and effect checking | ||||||
|
||||||
Note: all of this describes the implementation of the unstable `effects` and | ||||||
`const_trait` features. None of this implementation is usable or visible from | ||||||
stable Rust. | ||||||
|
||||||
The implementation of const traits and `~const` bounds is a limited effect system. | ||||||
It is used to allow trait bounds on `const fn` to be used within the `const fn` for | ||||||
method calls. Within the function, in order to know whether a method on a trait | ||||||
bound is `const`, we need to know whether there is a `~const` bound for the trait. | ||||||
In order to know whether we can instantiate a `~const` bound on a `const fn`, we | ||||||
need to know whether there is a `const_trait` impl for the type and trait being | ||||||
used (or whether the `const fn` is used at runtime, then any type implementing the | ||||||
trait is ok, just like with other bounds). | ||||||
|
||||||
We perform these checks via a const generic boolean that gets attached to all | ||||||
`const fn` and `const trait`. The following sections will explain the desugarings | ||||||
and the way we perform the checks at call sites. | ||||||
|
||||||
The const generic boolean is inverted to the meaning of `const`. In the compiler | ||||||
it is called `host`, because it enables "host APIs" like `static` items, network | ||||||
oli-obk marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
access, disk access, random numbers and everything else that isn't available in | ||||||
`const` contexts. So `false` means "const", `true` means "not const" and if it's | ||||||
a generic parameter, it means "maybe const" (meaning we're in a const fn or const | ||||||
trait). | ||||||
|
||||||
## `const fn` | ||||||
|
||||||
All `const fn` have a `#[rustc_host] const host: bool` generic parameter that is | ||||||
hidden from users. Any `~const Trait` bounds in the generics list or `where` bounds | ||||||
of a `const fn` get converted to `Trait<host> + Trait<true>` bounds. The `Trait<true>` | ||||||
exists so that associated types of the generic param can be used from projections | ||||||
like `<T as Trait>::Assoc`, because there are no `<T as ~Trait>` projections for now. | ||||||
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.
Suggested change
|
||||||
|
||||||
## `#[const_trait] trait`s | ||||||
|
||||||
The `#[const_trait]` attribute gives the marked trait a `#[rustc_host] const host: bool` | ||||||
generic parameter. All functions of the trait "inherit" this generic parameter, just like | ||||||
they have all the regular generic parameters of the trait. Any `~const Trait` super-trait | ||||||
bounds get desugared to `Trait<host> + Trait<true>` in order to allow using associated | ||||||
types and consts of the super traits in the trait declaration. This is necessary, because | ||||||
`<Self as SuperTrait>::Assoc` is always `<Self as SuperTrait<true>>::Assoc` as there is | ||||||
no `<Self as ~const SuperTrait>` syntax. | ||||||
|
||||||
## `typeck` performing method and function call checks. | ||||||
|
||||||
When generic parameters are instantiated for any items, the `host` generic parameter | ||||||
is always instantiated as an inference variable. These variables fall back to `true` at | ||||||
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. We should probably mention that it is a special kind of const infer var just so that the fallback works 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. Yeah, should link or mention |
||||||
the end of typeck to ensure that `let _ = some_fn_item_name;` will keep compiling. | ||||||
|
||||||
All actually used (in function calls, casts, or anywhere else) function items, will | ||||||
have the `enforce_context_effects` method invoked. | ||||||
It trivially returns if the function being called has no `host` generic parameter. | ||||||
|
||||||
TODO: how do we bail out if a non-const function is called in a const context? | ||||||
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. AFAIK that is still in the Mir check_consts pass |
||||||
|
||||||
The function call's `host` parameter is then equated to the context's `host` value, | ||||||
which almost always trivially succeeds, as it was an inference var. If the inference | ||||||
var has already been bound (since the function item is invoked twice), the second | ||||||
invocation checks it against the first. |
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.
Should this be
const_trait_impl
?