- Feature Name:
cfg_boolean_literals
- Start Date: 2024-09-16
- RFC PR: rust-lang/rfcs#3695
- Tracking Issue: rust-lang/rust#131204
Summary
Allow true
and false
boolean literals as cfg
predicates, i.e. cfg(true)
/cfg(false)
.
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
Boolean literals (i.e. true
and false
) may be used as cfg
predicates, to evaluate as always true/false respectively.
Reference-level explanation
The syntax for configuration predicates should be extended to include boolean literals:
Syntax
ConfigurationPredicate :
ConfigurationOption
| ConfigurationAll
| ConfigurationAny
| ConfigurationNot
|true
|false
And the line
true
orfalse
literals, which are alwaystrue
/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
By making it more convenient, this may encourage unconditionally disabled blocks of code being committed, which is undesirable.
Rationale and alternatives
- This could instead be spelled as
cfg(disabled|enabled)
, orcfg(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
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 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
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.