-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge RFC 3695: Boolean literals as cfg predicates
The FCP for RFC 3695 completed on 2024-09-28 with a disposition to merge. Let's merge it.
- Loading branch information
Showing
1 changed file
with
80 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
- Feature Name: `cfg_boolean_literals` | ||
- Start Date: 2024-09-16 | ||
- RFC PR: [rust-lang/rfcs#3695](https://github.com/rust-lang/rfcs/pull/3695) | ||
- Tracking Issue: [rust-lang/rust#131204](https://github.com/rust-lang/rust/issues/131204) | ||
|
||
# Summary | ||
[summary]: #summary | ||
|
||
Allow `true` and `false` boolean literals as `cfg` predicates, i.e. `cfg(true)`/`cfg(false)`. | ||
|
||
# Motivation | ||
[motivation]: #motivation | ||
|
||
Often, we may want to temporarily disable a block of code while working on a project; this can be useful, for example, to disable functions which have errors while refactoring a codebase. | ||
|
||
Currently, the easiest ways for programmers to do this are to comment out the code block (which means syntax highlighting no longer works), or to use `cfg(any())` (which is not explicit in meaning). | ||
|
||
By allowing `#[cfg(false)]`, we can provide programmers with an explicit and more intuitive way to disable code, while retaining IDE functionality. | ||
|
||
Allowing `cfg(true)` would also make temporarily enabling `cfg`'ed out code easier; a `true` may be added to a `cfg(any(..))` list. Adding a `cfg(all())` is the current equivalent of this. | ||
|
||
# Guide-level explanation | ||
[guide-level-explanation]: #guide-level-explanation | ||
|
||
Boolean literals (i.e. `true` and `false`) may be used as `cfg` predicates, to evaluate as always true/false respectively. | ||
|
||
# Reference-level explanation | ||
[reference-level-explanation]: #reference-level-explanation | ||
|
||
The syntax for configuration predicates should be extended to include boolean literals: | ||
|
||
> **<sup>Syntax</sup>**\ | ||
> _ConfigurationPredicate_ :\ | ||
> _ConfigurationOption_\ | ||
> | _ConfigurationAll_\ | ||
> | _ConfigurationAny_\ | ||
> | _ConfigurationNot_ \ | ||
> | `true` | `false` | ||
And the line | ||
> - `true` or `false` literals, which are always `true`/`false` respectively | ||
should be added to the explanation of the predicates. | ||
|
||
`cfg(r#true)` and `cfg(r#false)` should continue to work as they did previously (i.e. enabled when `--cfg true`/`--cfg false` are passed). | ||
|
||
`true` and `false` should be expected everywhere Configuration Predicates are used, i.e. | ||
- the `#[cfg(..)]` attribute | ||
- the `cfg!(..)` macro | ||
- the `#[cfg_attr(.., ..)]` attribute | ||
|
||
# Drawbacks | ||
[drawbacks]: #drawbacks | ||
|
||
By making it more convenient, this may encourage unconditionally disabled blocks of code being committed, which is undesirable. | ||
|
||
# Rationale and alternatives | ||
[rationale-and-alternatives]: #rationale-and-alternatives | ||
|
||
- This could instead be spelled as `cfg(disabled|enabled)`, or `cfg(none)` for disabling code only. However, giving special meaning to a valid identifier will change the meaning of existing code, requiring a new edition | ||
- As the existing predicates evaluate to booleans, using boolean literals is the most intuitive way to spell this | ||
|
||
# Prior art | ||
[prior-art]: #prior-art | ||
|
||
Many languages with conditional compilation constructs have a way to disable a block entirely. | ||
|
||
- C: `#if 0` | ||
- C#: `#if false` | ||
- Dlang: `version(none)` | ||
- Haskell: `#if 0` | ||
|
||
Searching for `cfg(false)` on [GitHub](https://github.com/search?q=%23%5Bcfg%28false%29%5D+language%3ARust&type=code) reveals many examples of projects (including Rust itself) using `cfg(FALSE)` as a way to get this behavior - although this raises a `check-cfg` warning. | ||
|
||
# Future possibilities | ||
[future-possibilities]: #future-possibilities | ||
|
||
A future lint could suggest replacing constructs such as `cfg(any())` with `cfg(false)`, and `cfg(all())` with `cfg(true)`. | ||
|
||
The `check-cfg` lint could be with a special case for identifiers such as `FALSE` and suggest `cfg(false)` instead. |