-
Notifications
You must be signed in to change notification settings - Fork 301
Announce automatic checking of cfgs at compile-time #1313
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
Merged
Merged
Changes from 3 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
c560529
Announce automatic checking of cfgs at compile-time
Urgau 3fdb571
Apply some suggestions from programmerjake
Urgau b02d576
Apply second round of suggestions from code review
Urgau d9f2a08
Apply suggestions and update links to rustc book
Urgau 8375ca8
Add section for non-Cargo based build systems + fix typos
Urgau 6b2803f
Host the SVG on the blog directly instead of a third-party website
Urgau 80c2bb9
Schedule for the 8th of may and populate last remaining links
Urgau 2682b15
Change the schedule to tomorrow (2024-05-05)
Urgau b360281
Stylist nitpicks
Urgau 97e7058
Double-column and put unconditional in bold
Urgau 09e360c
Update SVG with latest diagnostics updates
Urgau 1337ead
Changed publication date to 2024-05-06
Urgau e65e0ad
Apply suggestions from epage
Urgau File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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,115 @@ | ||
--- | ||
layout: post | ||
title: "Automatic checking of cfgs at compile-time" | ||
author: Urgau | ||
team: The Cargo Team <https://www.rust-lang.org/governance/teams/dev-tools#cargo> | ||
--- | ||
|
||
# Automatic checking of cfgs at compile-time | ||
|
||
The Cargo and Compiler team are delighted to announce that starting with Rust 1.80 (or nightly-2024-04-XX) every _reachable_ `#[cfg]` will be automatically checked that they match the expected config names and values. | ||
|
||
This can help with verifying that the crate is correctly handling conditional compilation for different target platforms or features. It ensures that the cfg settings are consistent between what is intended and what is used, helping to catch potential bugs or errors early in the development process. | ||
|
||
This addresses a common pitfall for new and advanced users. | ||
|
||
This is another step to our commitment to provide user-focused tooling and we are eager and excited to finally see it fixed, after more than two years since the original [RFC 3013](https://github.com/rust-lang/rfcs/pull/3013)[^1]. | ||
|
||
[^1]: The stabilized implementation and RFC 3013 diverge significantly, in particular there is only one form for `--check-cfg`: `cfg()` (instead of `values()` and `names()` being incomplete and subtlety incompatible with each other). | ||
|
||
## A look at the feature | ||
|
||
Every time a Cargo feature is declared that feature is transformed into a config that is passed to `rustc` (the Rust compiler) so it can verify with its [well known cfgs](TODO) if any of the `#[cfg]`, `#![cfg_attr]` and `cfg!` have unexpected configs and report a warning with the `unexpected_cfgs` lint. | ||
|
||
*`Cargo.toml`*: | ||
|
||
```toml | ||
[package] | ||
name = "foo" | ||
|
||
[features] | ||
lasers = [] | ||
zapping = [] | ||
``` | ||
|
||
*`src/lib.rs`:* | ||
```rust | ||
#[cfg(feature = "lasers")] // This condition is expected | ||
// as "lasers" is an expected value of `feature` | ||
fn shoot_lasers() {} | ||
|
||
#[cfg(feature = "monkeys")] // This condition is UNEXPECTED | ||
// as "monkeys" is NOT an expected value of `feature` | ||
fn write_shakespeare() {} | ||
|
||
#[cfg(windosw)] // This condition is UNEXPECTED | ||
// it's supposed to be `windows` | ||
fn win() {} | ||
``` | ||
|
||
*`cargo check`*: | ||
 | ||
|
||
## Custom cfgs and build scripts | ||
|
||
> In Cargo point-of-view: a custom cfg is one that is neither defined by `rustc` nor by a Cargo feature. Think of `tokio_unstable`, `has_foo`, ... but not `feature = "lasers"`, `unix`, ... | ||
|
||
Some crates use custom cfgs that they either expected from the environment (`RUSTFLAGS`or other means) or is enabled by some logic in the crate `build.rs`. For those crates Cargo provides a new instruction: [`cargo::rustc-check-cfg`](TODO)[^2] (or `cargo:rustc-check-cfg` for older Cargo version). | ||
|
||
[^2]: `cargo::rustc-check-cfg` will start working in Rust 1.80 (or nightly-2024-04-XX), between Rust 1.77 and Rust 1.79 *(included)* it silently did nothing and before that (so Rust 1.76 and below) it warned when used without the unstable Cargo `-Zcheck-cfg`. | ||
Urgau marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
The syntax to use is described in the [rustc book](https://doc.rust-lang.org/rustc/index.html) section [checking configuration](TODO), but in a nutshell the basic syntax of `--check-cfg` is: | ||
Urgau marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
> `cfg(name, values("value1", "value2", ..., "valueN"))` | ||
|
||
Note that every custom cfgs must always be expected, regardless if the cfg is active or not! | ||
|
||
### `build.rs` example | ||
|
||
`build.rs`: | ||
```rust | ||
fn main() { | ||
println!("cargo::rustc-check-cfg=cfg(has_foo)"); // <-- new with Cargo 1.80 | ||
if has_foo() { | ||
println!("cargo::rustc-cfg=has_foo"); | ||
} | ||
} | ||
``` | ||
|
||
> Note: Each `cargo::rustc-cfg` must always have a accompanying _unconditional_ `cargo::rustc-check-cfg` directive otherwise you risk having warnings like this:`unexpected cfg condition name: has_foo`. | ||
|
||
### Equivalence table | ||
|
||
| `cargo::rustc-cfg` | `cargo::rustc-check-cfg` | | ||
|-------------------------|------------------------------------------------| | ||
| `foo` | `cfg(foo)` or `cfg(foo, values(none()))` | | ||
| `foo=""` | `cfg(foo, values(""))` | | ||
| `foo="bar"` | `cfg(foo, values("bar"))` | | ||
| `foo="1"` and `foo="2"` | `cfg(foo, values("1", "2"))` | | ||
| `foo="1"` and `bar="2"` | `cfg(foo, values("1"))` and `cfg(bar, values("2"))` | | ||
| `foo` and `foo="bar"` | `cfg(foo, values(none(), "bar"))` | | ||
|
||
More details can be found on the [`rustc` book](TODO). | ||
Urgau marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
## Frequently asked questions | ||
|
||
### Can it be disabled? | ||
|
||
The feature is **always on** and _cannot_ be disabled from Cargo, but like any other lints it can be controlled: `#![allow(unexpected_cfgs)]`. | ||
|
||
### How does it interact with the `RUSTFLAGS` env ? | ||
|
||
You should be able to use the `RUSTFLAGS` environment variable like it was before. | ||
*Currently `--cfg` arguments are not checked, only usage in code are.* | ||
|
||
This means that doing `RUSTFLAGS="--cfg tokio_unstable" cargo check` will not report any warnings, unless `tokio_unstable` is used within your local crates, in which case crate author will need to make sure that that custom cfg is expected with `cargo::rustc-check-cfg` in the `build.rs` of that crate. | ||
|
||
### How to expect custom cfgs without a `build.rs` ? | ||
|
||
There is not **currently no way** to expect a custom cfg other than with `cargo::rustc-check-cfg` in a `build.rs`. | ||
Urgau marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Crate author that don't want to use a `build.rs` are encouraged to use Cargo features instead. | ||
Urgau marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
### Does it affect dependencies ? | ||
Urgau marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
No, the lint only affects local packages; only those will report the lint. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.