diff --git a/active/0000-const-block-expr.md b/active/0000-const-block-expr.md new file mode 100644 index 00000000000..59e8723934a --- /dev/null +++ b/active/0000-const-block-expr.md @@ -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.