Skip to content
Closed
Changes from 1 commit
Commits
Show all changes
110 commits
Select commit Hold shift + click to select a range
4dbd2d2
Fork cfg_version v2 skeleton
epage Sep 13, 2025
ecb3459
Initial draft
epage Sep 15, 2025
236f2a5
Rename the version predicate to since
epage Sep 15, 2025
2ee3718
Rename file for RFC #
epage Sep 15, 2025
20233b0
Link out to the RFC
epage Sep 15, 2025
3d827bc
Add another problem with vendor version
epage Sep 15, 2025
a24a6a4
Fix grammar
epage Sep 15, 2025
5a7c0e9
Fix grammar
epage Sep 15, 2025
d392d50
Clean up a sentence
epage Sep 15, 2025
e51caf2
Remove behavior left behind from a previous iteration
epage Sep 15, 2025
cb8acba
Revert "Remove behavior left behind from a previous iteration"
epage Sep 15, 2025
a1a8164
Update Guide to reflect how nightlies are proposed
epage Sep 15, 2025
c5e9d5f
Misc cleanup
epage Sep 15, 2025
465cecc
Update text/3857-cfg-version.md
epage Sep 15, 2025
0fed553
Fix grammar
epage Sep 15, 2025
3a7609a
Unquoted versions may negstively interact with target_version
epage Sep 15, 2025
55a7632
Fix unclosed literal
epage Sep 15, 2025
545ef52
Add counter balance to build probe drawback
epage Sep 15, 2025
4352a95
Clarify Python's post-release version comment
epage Sep 15, 2025
c0a7dc4
Fix grammar
epage Sep 15, 2025
ce77858
Fix print=cfg syntax
epage Sep 15, 2025
7ba5578
Fix print=cfg syntax
epage Sep 15, 2025
0d7f46c
Clarify check-cfg
epage Sep 15, 2025
b2e8cdb
Clarify the alternatives for check-cfg
epage Sep 15, 2025
50e6949
Provide unique anchors
epage Sep 16, 2025
2348d45
Future possibility for check-cfg version without a minimum
epage Sep 16, 2025
6f656d5
fix(drawback): Simplify nightly discussion
epage Sep 16, 2025
21b8dc0
fix(ref): Draw more attention to the warnings when discussion cfg
epage Sep 16, 2025
ee1c8cf
fix(guide): Fix bad versions and try to clarify example
epage Sep 16, 2025
ec2e54c
feat(rationale): Cover before
epage Sep 17, 2025
96ffa15
feat(drawbacks): Cover pre-releases of major versions
epage Sep 17, 2025
a07e1c6
fix(summary): Be name the predicate being added
epage Sep 17, 2025
c386700
fix(drawbacks): Tweak language around cargo requiring msrv bump for s…
epage Sep 17, 2025
741f854
fix(drawback): Be explicit on why -0 is chosen for the recommendation…
epage Sep 17, 2025
5ee6b1e
feat(prior): Include swift
epage Sep 17, 2025
95c2998
feat(ref): Discuss usability improvement to check-cfg warning
epage Sep 17, 2025
1b8355a
refactor(future): Group related items
epage Sep 17, 2025
0ab2847
fix: Update ConfigurationVersion for the rename to 'since'
epage Sep 17, 2025
f1dedc5
feat(future): Add an is_set predicate which came up while working on …
epage Sep 17, 2025
7139923
fix: Introduce has_rust to replace incorrect use of cfg(rust)
epage Sep 17, 2025
e71bdc1
fix(future): Include alternate name for 'before'
epage Sep 17, 2025
c12e4a4
Revert "fix: Introduce has_rust to replace incorrect use of cfg(rust)"
epage Sep 17, 2025
28b52e1
fix: Workaround #[cfg(rust)] with --cfg rust
epage Sep 17, 2025
b445f73
refactor(ref):? Include rust's --check-cfg in the rust-specific section
epage Sep 17, 2025
5eef426
fix(ref): Be more precise when talking about check-cfg
epage Sep 17, 2025
9da21e1
fix(ref): Correct where we cross-link check-cfg for since
epage Sep 17, 2025
d27c10d
fix(ref): Separate since logic for unset/name-only
epage Sep 17, 2025
0a839bd
fix(rationale): Acknowledge impact of cfg(rust) on cfg_value
epage Sep 17, 2025
005c608
fix(ref): Specify when multiple cfg's are present for the same name
epage Sep 17, 2025
5d01721
style: Fix spelling
epage Sep 17, 2025
e036b23
style: Be more consistent in quoting
epage Sep 17, 2025
940b979
fix(ref): Turn non-semver 'since' from false to error
epage Sep 17, 2025
b37fe10
feat(future): Speak to how `edition` would work
epage Sep 17, 2025
2c3cbe4
fix(drawbacks): Speak to general vs specialized solutions
epage Sep 17, 2025
75c486b
fix(rationale): Include another benefit for non-semver erroring
epage Sep 18, 2025
602eec6
fix(ref): Syntax error
epage Sep 18, 2025
e352338
fix(rationale): Cover a little more about extending version syntax
epage Sep 18, 2025
995eeed
fix(future): Discuss a slow roll out of relaxing version definition
epage Sep 18, 2025
c7ebc40
fix(alt): Cover has_rust
epage Sep 18, 2025
679116a
fix(alt): Include cfg rust_version name
epage Sep 18, 2025
5accada
feat(unresolved): Call out main T-lang questions within RFC
epage Sep 18, 2025
19dca3e
feat(alt): Add an operator variant
epage Sep 18, 2025
12f6745
feat(unresolved): Include discussion of nightlies
epage Sep 18, 2025
303bb64
style: Try to fix formatting
epage Sep 18, 2025
4347c60
fix(ref): Update examples for changes to compiler errors
epage Sep 18, 2025
53e0d39
fix(ref): Address a cardinality issue
epage Sep 19, 2025
8a57b6b
fix(summary): Fully specify the cfg
epage Sep 19, 2025
97d86b6
fix(motivation): Re-order for clarity
epage Sep 19, 2025
6241a5d
style: Fix grammar
epage Sep 19, 2025
955a11e
fix(ref): Remove a line from before bad string literals errored
epage Sep 19, 2025
3e89ae8
fix(ref): Delegate to SemVer, rather than Cargo, on comparisons
epage Sep 19, 2025
e544016
fix(ref): Clarify use of +build
epage Sep 19, 2025
3e632bf
fix(rationale): Further clarify +build
epage Sep 19, 2025
5b9fefe
fix(ref): Be consistent with +build
epage Sep 19, 2025
1024808
fix(rationale): Explain lack of +build for check-cfg
epage Sep 19, 2025
4031627
fix(ref): Be consistent with string literal
epage Sep 19, 2025
2bbed78
fix(ref): Clarify unexpected_cfgs
epage Sep 19, 2025
56305c3
fix(unresolved): Discusss pre-release name
epage Sep 19, 2025
7561a72
fix(drawback): Add findings on use of --cfg rust
epage Sep 19, 2025
fed559b
fix(drawback): Add context to the not(since) concern
epage Sep 19, 2025
459c87b
style(drawback): Fix grammar
epage Sep 19, 2025
dbbcab4
style(drawback): Fill in assumed gaps about generality
epage Sep 19, 2025
bc71f84
feat(alt): Cover version(since)
epage Sep 21, 2025
94d2438
style: Fix typo
epage Sep 21, 2025
b3b7c76
style: Grammar
epage Sep 22, 2025
be317a1
style: Grammar
epage Sep 22, 2025
851d2ed
fix(ref): Remove stale reference to invalid string literals being false
epage Sep 23, 2025
f461c5b
feat(unresolved): Call out decision on betas and incomplete
epage Sep 23, 2025
102adb1
fix: Use shorthand for values(none())
epage Sep 23, 2025
83a393c
fix(unresolved): Decide on values(none())
epage Sep 23, 2025
fb896af
feat(rationale): Cover more trade offs for `values(none())`
epage Sep 23, 2025
18a9594
style: Fix spelling
epage Sep 23, 2025
f3b4a69
fix(future): Correct sorting of post releases
epage Sep 23, 2025
ae5822c
fix(rationale): Clarify about since name
epage Sep 24, 2025
6b7ec78
feat(rationale): Cover since evaluting to false
epage Sep 24, 2025
1589434
feat(alt): Add unresolved question for operators in version()
epage Sep 24, 2025
cab1e93
style(unresolved): Fix spelling
epage Sep 24, 2025
674ec04
feat(alt): Cover typing/operator overloading
epage Sep 24, 2025
be94add
fix(alt): Alude to implicit type support
epage Sep 24, 2025
79f50aa
feat(alt): Bring up possible check-cfg syntax
epage Sep 24, 2025
3f765c1
feat(future): Clippy lint to use since with cfg_alias
epage Sep 24, 2025
56ddfc3
fix(ref): Nightly and beta are incomplete
epage Sep 24, 2025
3519b83
style: Fix typo
epage Sep 24, 2025
b3bff0f
fix(ref): Drop patch, specify Version syntax and precedence
epage Sep 24, 2025
b4338cb
feat(alt): Problem with future possibilities and operators
epage Sep 24, 2025
6703ecd
fix(ref): Be more precise in the name with version_since
epage Sep 24, 2025
ff3f075
feat(alt): Provide another reason for version(since)
epage Sep 25, 2025
ce9390b
feat(rationale): More reasons for version_since than since_version
epage Sep 25, 2025
d089ddd
feat(alt): Cover more operator concerns
epage Sep 25, 2025
4551bbd
fix(prior): Switch Swift to actual prior art
epage Oct 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions text/3857-cfg-version.md
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,65 @@ so we do not include that information.

## Alternative designs

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we have a vote on the proposed "since" versus the alternative designs?

I personally like them better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "vote" will be done by the owning team for this RFC (T-lang). The responsibility for the rest of us is to provide meaningful feedback that can be included for them to review in their evaluation.

Keep in mind though that part of why this RFC came about is concerns that came up during the stabilization of rust_version(_) which makes it unlikely we will pivot in that direction.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From @kornelski at #3857 (comment)

Currently #[cfg()] has its own microsyntax, being a language inside a language, with its own design that is quite different from Rust's expressions. There's a proposal to move away from that, and make it behave more like normal expressions, using &&/|| instead of all()/any(). Syntactically, this will end up allowing everything matching macro expr inside cfg().

I think it would be great to generally move towards using a syntax that's more natural as Rust expressions, and use >= and < for comparisons.

#[cfg(rust_version >= "1.99")]
#[cfg(rust_version < "1.99")]

There's a proposal for #[stable(since = "semver")] or #[doc(since = "semver")] attribute: rust-lang/rust#74182 and there's #[deprecated(since = "v")] already. Use of >= operator avoids giving since multiple roles.

Copy link
Contributor Author

@epage epage Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From @tmandry at #3857 (comment)

What strikes me when considering @kornelski's comment above is that we haven't yet explored the idea of introducing a new type of cfg value for versions to the language.

This RFC introduces a new cfg predicate and a new check-cfg predicate to match. If we instead had typed cfg values we could redefine predicates like = to do something more specific for that type, in addition to defining additional predicates like >= and <.

The question is how to introduce values of a type. Following Rust, we can introduce them as version("1.85"). So on the command line you would say --cfg rust=version("1.85"), and in code you could write

#[cfg(rust >= version("1.85")]
#[cfg(rust < version("1.85")]

Again, following Rust, we could choose to allow comparison between a version on the left and a string literal on the right. Probably I would defer this for now, but could be convinced either way.

Beyond the syntactic improvements, this gives us some extra flexibility. For example:

  • I can write --check-cfg cfg(rust >= version("1.85")) and this defines the set of operators that are allowed with that value.

  • We can choose to enforce that all values of a cfg are the same type. Or in the case of versions, we can enforce that you only have one value to begin with.

  • As a future possibility we could have something like cratename = version("1.100+metadata") check for an exact match to +metadata on the LHS, while a more general requirement like cratename = version("1.100") would ignore any metadata that happens to exist on the LHS. Supporting this kind of comparison in the current RFC is less straightforward.

I still support the current RFC; I think it's better than anything we've considered before and it gets the details right. But this other direction is worth considering as a possibility. Using typed comparisons instead of operators on strings feels more Rusty to me.

We've already reserved space for cfg types with rustc's --cfg foo="bar" syntax that requires the double quotes, so we might as well make use of it. And of course, another future possibility is to add integer configs.

Currently #[cfg()] has its own microsyntax, being a language inside a language, with its own design that is quite different from Rust's expressions. There's a proposal to move away from that, and make it behave more like normal expressions, using &&/|| instead of all()/any(). Syntactically, this will end up allowing everything matching macro expr inside cfg().

For the record, I'm very much open to this direction. I don't think it cuts strongly against a comparison operator like since(), since that already looks like a function call.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From @traviscross at #3857 (comment)

If we instead had typed cfg values we could...

What I'd really like eventually is to not have a DSL here at all and just use Rust within cfg attributes. We already have a Rust interpreter on hand -- consteval. Obviously nothing from the crate itself would be in scope.

Clearly I don't think cfg_version should wait for that. But when we start talking about typed cfg values, generic predicates, and, presumably therefore, type inference and type checking for cfg, it does make me wonder whether using Rust here and consteval might not be more straightforward after all.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've covered binary operators and types in 674ec04. This greatly enlarges the scope of this RFC which has me worried about this being available in a reasonable time frame and, if we go down this route, I wonder if we should have a short-term solution, like rust_version("1.95").

From @traviscross

What I'd really like eventually is to not have a DSL here at all and just use Rust within cfg attributes. We already have a Rust interpreter on hand -- consteval. Obviously nothing from the crate itself would be in scope.

Keep in mind that Cargo also parses and evaluates the syntax.

We'd also have to figure out how concepts like name-only cfg's translates to "rust".


### `cfg(rust >= "1.95")`

[RFC #3796](https://github.com/rust-lang/rfcs/pull/3796)
will be allowing operators in addition to predicates and it stands to reason that we can extend that
to version comparisons as well.

The expression `rust >= "1.95"` without any other changes would be a string comparison and not a version precedence comparison.
We'd need to add the concept of types to cfg.
We could make check-cfg load-bearing by relying on its type information
or we could add coercion functions to cfg.

So given `--cfg=rust --cfg=rust=version("1.95.0")`, you could do `cfg(rust >= version("1.95"))`.

With typing,
`cfg_values!` (a future possibility) could evaluate to the given type.
So for `--cfg foo=integer("1')`, `cfg_value!(foo)` would be as if you typed `1`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we write this as --cfg foo=1?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can also consider implicit types. I recorded this in be94add.

For versions,
as there is no native Rust type,
we'd likely have it evaluate to a `&'static str`.

[RFC #3796](https://github.com/rust-lang/rfcs/pull/3796)
does not address questions around binary operators,
requiring us to work it out.
For example, are the sides of the operator fully swappable?
If we define all comparisons, would `==` be different than `=`?
How will these operators work in the presence of multiple values or a name-only cfg?

Would we allow implicit coercion so you can skip the `version` inside of `cfg`, like `cfg(rust >= "1.95")`?
I would suggest not because this would make it harder to catch bugs where
- The `--cfg` is not a version but you thought it was
- The `--cfg` should be a version but `version()` was left off

Currently, check-cfg does not apply at all to `--cfg` because it is commonly used with `RUSTFLAGS` which
are applied to all packages and would warn that an unknown `IDENTIFIER` is in use for packages that don't care.
We could still skip checking for unknown `IDENTIFIER`s and instead warn on misuse of `IDENTIFIER`s which would increase the chance of catching a mistake (unless a person duplicated there `--cfg` mistake with `--check-cfg`.

Another is how to handle check-cfg.
The proposed syntax is a binary operator but there is no left-hand side in check-cfg.
Would we accept `cfg(rust, values(>="1.95"))`?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My suggestion is to use cfg(rust >= version("1.95")).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recorded this in 79f50aa

How would we specify types? Would we replace `values` with `versions`?

Adding typing to cfg,
while likely something we'll do one day,
greatly enlarges the scope of this RFC.
This makes it harder to properly evaluate each part,
making it more likely we'll make mistakes.
This further delays the feature as the unstable period is likely to be longer.
We also are not ready to evaluate other use cases for typing to evaluate the impact
and likely won't until we move forward with [global features](https://internals.rust-lang.org/t/pre-rfc-mutually-excusive-global-features/19618)
and `cfg_values!`,
allowing us to cover use cases like embedded using [toml_cfg](https://crates.io/crates/toml-cfg).

If we defer typing, we'll have to allow implicit coercion of values so we can mark `rust` as a version in the future without it being a breaking change.

If we consider typing the correct long term solution but defer it,
we may want to consider the most narrowly scoped solution in the short term,
like `rust_version("1.95")`.
These "big questions" can then have dedicated issues and versions can be built on top of that.

### `version(rust, ">=1.95")`

Instead of having an assumed operator for the predicate,
Expand Down