mirror of https://github.com/rust-lang/rfcs
Merge remote-tracking branch 'kimundi/const-block-expr'
This commit is contained in:
commit
0f3603d33c
|
@ -0,0 +1,92 @@
|
|||
- Start Date: 2014-05-07
|
||||
- RFC PR #: (leave this empty)
|
||||
- Rust Issue #: (leave this empty)
|
||||
|
||||
# Summary
|
||||
|
||||
Allow block expressions in statics, as long as they only contain items
|
||||
and a trailing const expression.
|
||||
|
||||
Example:
|
||||
|
||||
```rust
|
||||
static FOO: uint = { 100 };
|
||||
static BAR: fn() -> int = {
|
||||
fn hidden() -> int {
|
||||
42
|
||||
}
|
||||
hidden
|
||||
};
|
||||
```
|
||||
|
||||
# Motivation
|
||||
|
||||
This change allows defining items as part of a const expression,
|
||||
and evaluating to a value using them.
|
||||
This is mainly useful for macros, as it allows hiding complex machinery behind something
|
||||
that expands to a value, but also enables using `unsafe {}` blocks in a static initializer.
|
||||
|
||||
Real life examples include the `regex!` macro, which currently expands to a block containing a
|
||||
function definition and a value, and would be usable in a static with this.
|
||||
|
||||
Another example would be to expose a static reference to a fixed memory address by
|
||||
dereferencing a raw pointer in a const expr, which is useful in
|
||||
embedded and kernel, but requires a `unsafe` block to do.
|
||||
|
||||
The outcome of this is that one additional expression type becomes valid as a const
|
||||
expression, with semantics that are a strict subset of its equivalent in a function.
|
||||
|
||||
# Drawbacks
|
||||
|
||||
Block expressions in a function are usually just used to run arbitrary code before
|
||||
evaluating to a value. Allowing them in statics without allowing code
|
||||
execution might be confusing.
|
||||
|
||||
# Detailed design
|
||||
|
||||
A branch implementing this feature can be found at
|
||||
https://github.com/Kimundi/rust/tree/const_block.
|
||||
|
||||
It mainly involves the following changes:
|
||||
|
||||
- const check now allows block expressions in statics:
|
||||
- All statements that are not item declarations lead to an compile error.
|
||||
- trans and const eval are made aware of block expressions:
|
||||
- A trailing expression gets evaluated as a constant.
|
||||
- A missing trailing expressions is treated as a unit value.
|
||||
- trans is made to recurse into static expressions to generate possible items.
|
||||
|
||||
Things like privacy/reachability of definitions inside a static block
|
||||
are already handled more generally at other places, as the situation is
|
||||
very similar to a regular function.
|
||||
|
||||
The branch also includes tests that show how this feature works in practice.
|
||||
|
||||
# Alternatives
|
||||
|
||||
Because this feature is a straight forward extension of the valid const expressions,
|
||||
it already causes a very minimal impact on the language, with most alternative ways
|
||||
of enabling the same benefits being more complex.
|
||||
|
||||
For example, a expression AST node that can include items but is only usable from procedural macros
|
||||
could be added.
|
||||
|
||||
Not having this feature would not prevent anything interesting from getting implemented,
|
||||
but it would lead to less nice looking solutions.
|
||||
|
||||
For example, a comparison between static-supporting `regex!` with and without this feature:
|
||||
|
||||
```rust
|
||||
// With this feature, you can just initialize a static:
|
||||
static R: Regex = regex!("[0-9]");
|
||||
|
||||
// Without it, the static needs to be generated by the
|
||||
// macro itself, alongside all generated items:
|
||||
regex! {
|
||||
static R = "[0-9]";
|
||||
}
|
||||
```
|
||||
|
||||
# Unresolved questions
|
||||
|
||||
None so far.
|
Loading…
Reference in New Issue