Skip to content

Commit 9da3eb8

Browse files
committed
Allow blocks in constants
1 parent 62bfca4 commit 9da3eb8

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

active/0000-const-block-expr.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
- Start Date: 2014-05-07
2+
- RFC PR #: (leave this empty)
3+
- Rust Issue #: (leave this empty)
4+
5+
# Summary
6+
7+
Allow block expressions in statics, as long as they only contain items
8+
and a trailing const expression.
9+
10+
Example:
11+
12+
```rust
13+
static FOO: uint = { 100 };
14+
static BAR: fn() -> int = {
15+
fn hidden() -> int {
16+
42
17+
}
18+
hidden
19+
};
20+
```
21+
22+
# Motivation
23+
24+
This change allows defining items as part of a const expression,
25+
and evaluating to a value using them.
26+
This is mainly useful for macros, as it allows hiding complex machinery behind something
27+
that expands to a value, but also enables using `unsafe {}` blocks in a static initializer.
28+
29+
Real life examples include the `regex!` macro, which currently expands to a block containing a
30+
function definition and a value, and would be usable in a static with this.
31+
32+
Another example would be to expose a static reference to a fixed memory address by
33+
dereferencing a raw pointer in a const expr, which is useful in
34+
embedded and kernel, but requires a `unsafe` block to do.
35+
36+
The outcome of this is that one additional expression type becomes valid as a const
37+
expression, with semantics that are a strict subset of its equivalent in a function.
38+
39+
# Drawbacks
40+
41+
Block expressions in a function are usually just used to run arbitrary code before
42+
evaluating to a value. Allowing them in statics without allowing code
43+
execution might be confusing.
44+
45+
# Detailed design
46+
47+
A branch implementing this feature can be found at
48+
https://github.com/Kimundi/rust/tree/const_block.
49+
50+
It mainly involves the following changes:
51+
52+
- const check now allows block expressions in statics:
53+
- All statements that are not item declarations lead to an compile error.
54+
- trans and const eval are made aware of block expressions:
55+
- A trailing expression gets evaluated as a constant.
56+
- A missing trailing expressions is treated as a unit value.
57+
- trans is made to recurse into static expressions to generate possible items.
58+
59+
Things like privacy/reachability of definitions inside a static block
60+
are already handled more generally at other places, as the situation is
61+
very similar to a regular function.
62+
63+
The branch also includes tests that show how this feature works in practice.
64+
65+
# Alternatives
66+
67+
Because this feature is a straight forward extension of the valid const expressions,
68+
it already causes a very minimal impact on the language, with most alternative ways
69+
of enabling the same benefits being more complex.
70+
71+
For example, a expression AST node that can include items but is only usable from procedural macros
72+
could be added.
73+
74+
Not having this feature would not prevent anything interesting from getting implemented,
75+
but it would lead to less nice looking solutions.
76+
77+
For example, a comparison between static-supporting `regex!` with and without this feature:
78+
79+
```rust
80+
// With this feature, you can just initialize a static:
81+
static R: Regex = regex!("[0-9]");
82+
83+
// Without it, the static needs to be generated by the
84+
// macro itself, alongside all generated items:
85+
regex! {
86+
static R = "[0-9]";
87+
}
88+
```
89+
90+
# Unresolved questions
91+
92+
None so far.

0 commit comments

Comments
 (0)