|
| 1 | +- Feature Name: `cfg_boolean_literals` |
| 2 | +- Start Date: 2024-09-16 |
| 3 | +- RFC PR: [rust-lang/rfcs#3695](https://github.com/rust-lang/rfcs/pull/3695) |
| 4 | +- Tracking Issue: [rust-lang/rust#131204](https://github.com/rust-lang/rust/issues/131204) |
| 5 | + |
| 6 | +# Summary |
| 7 | +[summary]: #summary |
| 8 | + |
| 9 | +Allow `true` and `false` boolean literals as `cfg` predicates, i.e. `cfg(true)`/`cfg(false)`. |
| 10 | + |
| 11 | +# Motivation |
| 12 | +[motivation]: #motivation |
| 13 | + |
| 14 | +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. |
| 15 | + |
| 16 | +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). |
| 17 | + |
| 18 | +By allowing `#[cfg(false)]`, we can provide programmers with an explicit and more intuitive way to disable code, while retaining IDE functionality. |
| 19 | + |
| 20 | +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. |
| 21 | + |
| 22 | +# Guide-level explanation |
| 23 | +[guide-level-explanation]: #guide-level-explanation |
| 24 | + |
| 25 | +Boolean literals (i.e. `true` and `false`) may be used as `cfg` predicates, to evaluate as always true/false respectively. |
| 26 | + |
| 27 | +# Reference-level explanation |
| 28 | +[reference-level-explanation]: #reference-level-explanation |
| 29 | + |
| 30 | +The syntax for configuration predicates should be extended to include boolean literals: |
| 31 | + |
| 32 | +> **<sup>Syntax</sup>**\ |
| 33 | +> _ConfigurationPredicate_ :\ |
| 34 | +> _ConfigurationOption_\ |
| 35 | +> | _ConfigurationAll_\ |
| 36 | +> | _ConfigurationAny_\ |
| 37 | +> | _ConfigurationNot_ \ |
| 38 | +> | `true` | `false` |
| 39 | +
|
| 40 | +And the line |
| 41 | +> - `true` or `false` literals, which are always `true`/`false` respectively |
| 42 | +
|
| 43 | +should be added to the explanation of the predicates. |
| 44 | + |
| 45 | +`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). |
| 46 | + |
| 47 | +`true` and `false` should be expected everywhere Configuration Predicates are used, i.e. |
| 48 | +- the `#[cfg(..)]` attribute |
| 49 | +- the `cfg!(..)` macro |
| 50 | +- the `#[cfg_attr(.., ..)]` attribute |
| 51 | + |
| 52 | +# Drawbacks |
| 53 | +[drawbacks]: #drawbacks |
| 54 | + |
| 55 | +By making it more convenient, this may encourage unconditionally disabled blocks of code being committed, which is undesirable. |
| 56 | + |
| 57 | +# Rationale and alternatives |
| 58 | +[rationale-and-alternatives]: #rationale-and-alternatives |
| 59 | + |
| 60 | +- 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 |
| 61 | +- As the existing predicates evaluate to booleans, using boolean literals is the most intuitive way to spell this |
| 62 | + |
| 63 | +# Prior art |
| 64 | +[prior-art]: #prior-art |
| 65 | + |
| 66 | +Many languages with conditional compilation constructs have a way to disable a block entirely. |
| 67 | + |
| 68 | +- C: `#if 0` |
| 69 | +- C#: `#if false` |
| 70 | +- Dlang: `version(none)` |
| 71 | +- Haskell: `#if 0` |
| 72 | + |
| 73 | +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. |
| 74 | + |
| 75 | +# Future possibilities |
| 76 | +[future-possibilities]: #future-possibilities |
| 77 | + |
| 78 | +A future lint could suggest replacing constructs such as `cfg(any())` with `cfg(false)`, and `cfg(all())` with `cfg(true)`. |
| 79 | + |
| 80 | +The `check-cfg` lint could be with a special case for identifiers such as `FALSE` and suggest `cfg(false)` instead. |
0 commit comments