Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Allow boolean literals as cfg predicates #3695

Merged
merged 13 commits into from
Oct 4, 2024
74 changes: 74 additions & 0 deletions text/0000-cfg_boolean_literal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
- Feature Name: `cfg_boolean_literal`
- Start Date: 2024-09-16
- RFC PR: [rust-lang/rfcs#3695](https://github.com/rust-lang/rfcs/pull/3695)
- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)

# 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 the end of a `cfg(any(..))` list.
joshtriplett marked this conversation as resolved.
Show resolved Hide resolved

# 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_ :\
> &nbsp;&nbsp; &nbsp;&nbsp; _ConfigurationOption_\
> &nbsp;&nbsp; | _ConfigurationAll_\
> &nbsp;&nbsp; | _ConfigurationAny_\
> &nbsp;&nbsp; | _ConfigurationNot_ \
> &nbsp;&nbsp; | `true` | `false`

And the line
> - `true` or `false` literals, which are always `true`/`false` respectively

should be added to the explanation of the predicates.

# 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
clubby789 marked this conversation as resolved.
Show resolved Hide resolved
- Giving special meaning to a valid identifier can change the meaning of existing code (although `check-cfg` warnings should reduce the impact of this)
clubby789 marked this conversation as resolved.
Show resolved Hide resolved
- 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 blog entirely.
joshtriplett marked this conversation as resolved.
Show resolved Hide resolved

- 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)`.
joshtriplett marked this conversation as resolved.
Show resolved Hide resolved

The `check-cfg` lint could be with a special case for identifiers such as `FALSE` and suggest `cfg(false)` instead.