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

Tracking issue for RFC 2523, #[cfg(version(..))] #64796

Open
2 of 6 tasks
Centril opened this issue Sep 26, 2019 · 94 comments
Open
2 of 6 tasks

Tracking issue for RFC 2523, #[cfg(version(..))] #64796

Centril opened this issue Sep 26, 2019 · 94 comments
Labels
B-RFC-approved Feature: Approved by a merged RFC but not yet implemented. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. F-cfg_version `#![feature(cfg_version)]` S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@Centril
Copy link
Contributor

Centril commented Sep 26, 2019

This is a tracking issue for #[cfg(version(..))] (rust-lang/rfcs#2523).

Steps:

Unresolved questions:

@Centril Centril added B-RFC-approved Feature: Approved by a merged RFC but not yet implemented. T-lang Relevant to the language team, which will review and decide on the PR/issue. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. labels Sep 26, 2019
@Centril Centril added the F-cfg_version `#![feature(cfg_version)]` label Sep 26, 2019
csmoe added a commit to csmoe/rust that referenced this issue Sep 29, 2019
@pickfire
Copy link
Contributor

@csmoe Are you working on this? If not I might want to try out this task first since @petrochenkov mentioned that this task is easier than cfg(accessible = ::path).

@csmoe
Copy link
Member

csmoe commented Nov 16, 2019

@pickfire I didn't have much bandwidth on this, seems you have already made some progress on cfg(accessible = ::path), so feel free to check this :)
(Don't forget to assign yourself with @rustbot claim)

@pickfire
Copy link
Contributor

@csmoe Nice, thanks a lot for telling me that. I did not know such thing exist.

@rustbot claim

@rustbot rustbot self-assigned this Nov 16, 2019
@pickfire
Copy link
Contributor

Can anyone please help to write up the mentoring instructions. Based on what I know, this should be similar to #64797 (comment)

1. Syntax:
   
   1. Add a new `sym::accessible` in https://doc.rust-lang.org/nightly/nightly-rustc/src/syntax_pos/symbol.rs.html#22.
   2. Feature gate `accessible` in [`GATED_CFGS`](https://doc.rust-lang.org/nightly/nightly-rustc/syntax/feature_gate/builtin_attrs/constant.GATED_CFGS.html). Also add `cfg_accessible` to `active.rs`: https://doc.rust-lang.org/nightly/nightly-rustc/src/syntax/feature_gate/active.rs.html#530. This will also require a new `sym::cfg_accessible`.
   3. Introduce a match arm for `sym::accessible` in [`cfg_matches`](https://doc.rust-lang.org/nightly/nightly-rustc/syntax/attr/fn.cfg_matches.html). This should look mostly like [the case for `sym::not`](https://doc.rust-lang.org/nightly/nightly-rustc/src/syntax/attr/builtin.rs.html#591).
      Here you need to extract an [`&ast::Path`](https://doc.rust-lang.org/nightly/nightly-rustc/syntax/ast/struct.Path.html) and delegate the interpretation to a function of the rough shape `fn is_accessible(sess: &ParseSess, path: &Path) -> bool { ... }`

2. Implement `fn is_accessible`.
   
   1. First do some validation. We want to emit errors if [`!path.is_global()`](https://doc.rust-lang.org/nightly/nightly-rustc/syntax/ast/struct.Path.html#method.is_global). Use [`sess.span_diagnostic.struct_span_err`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Handler.html#method.struct_span_err).

I believed step 1 and 2 should be the same. For step 3, based on what I know requires me to modify somewhere around

MetaItemKind::List(..) => {
error(cfg.span, "unexpected parentheses after `cfg` predicate key")
}
.

Based on fn is_accessible, the next thing to be done should be to implement fn min_version and then somehow reference version_check on how to do the min_version logic by checking the CFG_VERSION environment variable?

@mibac138
Copy link
Contributor

Hi, @pickfire. Are you still working on this?

@pickfire
Copy link
Contributor

No, I was stuck working on this and don't know how to proceed.

@mibac138
Copy link
Contributor

Ok, thanks for quick response. I'll take my shot at this.
@rustbot claim

@rustbot rustbot assigned rustbot and unassigned rustbot Apr 18, 2020
@pickfire
Copy link
Contributor

@mibac138 Do you want me to publish my progress?

@mibac138
Copy link
Contributor

@pickfire sure, that'd be great!

@pickfire
Copy link
Contributor

pickfire commented Apr 20, 2020

@mibac138 Err, no need. You have already done more than me, I don't know how to change the eval_condition. Oh, it didn't seemed that hard after looking at your PR but I didn't know how to work on that.

@petrochenkov
Copy link
Contributor

Status update: #71314 implemented this RFC with a slightly different syntax - #[cfg(version("1.2.3"))] instead of #[cfg(version(1.2.3))].

The reason is that 1.2.3 doesn't fit into some existing attribute-parsing infrastructure in the compiler (MetaItems), so it requires separate work.

Additionally, the version_check crate currently used to parse versions wants a string as an input, so we need to stringify 1.2.3 before passing it, which we can only do imprecisely (up to whitespaces).
So we can turn 1 . 2 .3 into e.g. "1.2.3" during stringification and it may be a problem depending on what exactly we are supposed to accept as a valid version.

Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue May 3, 2020
Implement RFC 2523, `#[cfg(version(..))]`

Hi! This is my first contribution to rust, I hope I didn't miss anything. I tried to implement this feature so that `#[cfg(version(1.44.0))]` works but the parser was printing an error that I wasn't sure how to fix so I just opted for implementing `#[cfg(version("1.44.0"))]` (note the quotes).

Tracking issue: rust-lang#64796
@roblabla
Copy link
Contributor

roblabla commented May 6, 2020

The RFC had an unresolved question about how this feature would interact with nightly/beta. Should #[cfg(version("1.45.0"))] return true or false for nightly/beta 1.45.0?

Currently, the implementation returns true. E.G. for rustc 1.45.0-nightly, the following code prints Yes:

#![feature(cfg_version)]
fn main() {
    test();
}

#[cfg(version("1.45.0"))]
fn test() {
    println!("Yes")
}

#[cfg(not(version("1.45.0")))]
fn test() {
    println!("No")
}

IMO, this is a mistake. The main use-case for cfg(version), at least for me, is to allow use of new features that are known to be stable at a given version. For instance, in the core-error crate, I was planning to use cfg(version) to implement my custom core::error::Error trait on the various error structures of libcore/liballoc automatically, based on cfg(version). Unfortunately, this is not possible as it will certainly cause breakage in the in-between nightly versions that are reported as implementing a version, whilst not having all the types associated with it.

@nikomatsakis
Copy link
Contributor

That sounds like good reasoning to me, but I've not been following this RFC that closely. @joshtriplett -- I feel like you were "liaison'ing" for this before we had a term for it, do you have a take?

@nikomatsakis
Copy link
Contributor

Nominating for lang-team meeting to discuss

@dekellum
Copy link

dekellum commented May 6, 2020

Currently, the implementation returns true

Which is most useful, the way it is, AFAICT.

Isn't there a way to combine this with cfg test(s) for "train", e.g. beta or nightly and unstable feature gates?

@Nemo157
Copy link
Member

Nemo157 commented May 6, 2020

Isn't there a way to combine this with cfg test(s) for "train", e.g. beta or nightly and unstable feature gates?

Code written for the stable compiler should not have to know about beta or nightly.

@dekellum
Copy link

dekellum commented May 6, 2020

I'm not surprised with that as a goal, but I can think of cases where for practical reasons I nead to dev on 1.45 nightly with expectation that it will then work on 1.45 stable. I'm surprised if I'm the only one.

@joshtriplett
Copy link
Member

joshtriplett commented May 20, 2021 via email

@HTGAzureX1212
Copy link
Contributor

HTGAzureX1212 commented Jun 9, 2021

Stabilization report

I propose that the cfg_version feature be stabilized. The feature guards the cfg(version) predicate, which takes a version number like cfg(version("1.50.0")) and evaluates to true if the compiler's/language's version is newer or equal to the contained version number. Notation wise, "1.50" is allowed too, but any postfixes like -stable or -beta.2 are not allowed.

#[cfg(version("1.50.0"))]
fn foo() {}

#[cfg(version("1.27.0"))]
fn bar() {}

The predicate is one of the two predicates proposed by RFC 2523, the other being cfg(accessible(path)), tracked by #64797. The main alteration from the RFC was to surround the version number with "" to better fit into the compiler's internal data structures.

The implementation issues a warning if invalid version syntax is contained in the string literal. This is done to provide forward compatibility. Literal-free invocations like version(1.50) do cause errors just as version(foo) does.

version on the nightly channel

In the post-RFC discussion there has been a conversation about which version the nightly compiler should use as its supported version. Unlike beta or stable compilers, nightly compilers can still gain new features, and un-stabilizations are possible. So technically it's possible that newer code can rely on a feature that someone's pinned or not updated nightly does not support yet. On the other hand, during the stabilized-in-nightly phase, features often attain their largest extent of exposure before being shipped as part of a stable release.

The proposed compromise is to treat as a nightly's version as complete, but to add the -Z assume-incomplete-release flag added by #81468 . Users who pin their nightlies can enable it to back-date the supported version to the prior release. Intent is to keep it perma-unstable as it targets nightly users only. As this question only affects nightly compilers, the decision can also be revisited in the future.

Implementation history

Documentation

Tests in the compiler

See also

See also the cfg(accessible) feature (issue #64797).

I propose to add the specific nightly compiler commit to the attribute, as in:

#[cfg(version("1.54.0-nightly (ed597e7e1 2021-06-08)"))]

Such that nightly builds earlier than that (or after than that) would consider the code annotated with that attribute as "conditionally disabled code" even if it is exactly 1.54.0-nightly, but not the same commit? Not sure would that be too specific; but that might solve the problem.

@jhpratt
Copy link
Member

jhpratt commented Jun 9, 2021

Setting aside the fact that I don't believe this is the appropriate time or place to discuss that (a new issue should be opened imo), that would effectively preclude an alternative implementation of Rust from ever existing. Matching the behavior of an exact SHA and date would not be worth the effort to say the least.

@HTGAzureX1212
Copy link
Contributor

That is true though

@joshtriplett
Copy link
Member

Setting aside the fact that I don't believe this is the appropriate time or place to discuss that (a new issue should be opened imo), that would effectively preclude an alternative implementation of Rust from ever existing.

Not inherently; it would just allow Rust code to detect the exact compiler version it's running on. That might be useful for code that intends to be pinned to a specific compiler version.

@roblabla
Copy link
Contributor

I expect alternative implementations to target stable rust, not nightly. So a feature to pin a particular nightly would not need to be implemented by alternative rust compilers (or they could even be implemented with alternative semantics).

@Kixunil
Copy link
Contributor

Kixunil commented Oct 9, 2021

Regarding:

Should we also support version = "..."

Yes, please! I have a bunch of projects (and contribute to a bunch of others) that want to support at least the version available in Debian stable. However additional features would be sometimes useful.

Unfortunately, this would not work as-is. Let's say I want to do this:

#cfg(version= "1.60")
struct Foo;
// ...

If I write such code it'll behave strangely:

  • It compiles just fine for old Rust versions (e.g. 1.41)
  • It errors in newer versions (e.g. 1.48)
  • It starts to compile in even newer version again (e.g. let's say it's stabilized in 1.58)
  • It turns on the additional functionality in the given version (1.60)

To an uninformed observer this would look like certain versions had regression.

To solve this I propose renaming version to rust_version in the same release this gets stabilized in. (In other words renaming would be mandatory part of the stabilization commit.) I find that name more readable anyway and it's in line with similar cargo feature. An alternative is just to get this in ASAP but that incentivizes rushed decisions. (Maybe not too big issue given this is a very simple feature?)

@est31
Copy link
Member

est31 commented Oct 12, 2021

@Kixunil yeah the same behaviour occurs with edition = "..." in Cargo.toml which is ignored by older cargos, then newer cargos error about it, until cargo 1.31.0 onwards accepts it.

I think the best solution to the problem is to just wait it out, because even if this feature exists, projects will increase their MSRV eventually to one that supports #[cfg(version)]. I think that's better than adding the trademarked rust term to even more places in the language (this can be problematic for forks for example, or people who don't want to/can't abide by the trademark policy the foundation sets).

@Kixunil
Copy link
Contributor

Kixunil commented Oct 12, 2021

@est31 WTF, "Rust" is name of the programming language so if you make a fork it's reasonable to keep the name of the language. Does the trademark disallow people forking?

IMO version is not clear - is it crate version? Dep version? std version? cargo version? Rust version? Renaming kills two birds with one stone. (Or if we want to avoid trademark discussion, lang-version is fine.)

@Lokathor
Copy link
Contributor

I'd agree that lang_version is better than just version.

@est31
Copy link
Member

est31 commented Oct 12, 2021

Does the trademark disallow people forking?

The copyright doesn't but the trademark rights are separate and it's up to the owner of the trademark to set the policy. When the trademarks were owned by Mozilla, they were under basically the same rules as the Firefox trademark. Some distros were forced to create different branding for their Firefox builds even though they only added a few patches. Not familiar enough with what the foundation's been doing to tell whether there has been any change of the trademark policy. The website still treats the trademarks as if they were owned by Mozilla. Even if, such policies can change any minute.

Also, generally it's a good idea to rename a project when forking it to avoid confusion, even if you are not required to do so.

I feel that fairness owes it that if possible, it would be best to not refer to the name of the language in proper language features.

IMO version is not clear - is it crate version? Dep version? std version? cargo version? Rust version? Renaming kills two birds with one stone. (Or if we want to avoid trademark discussion, lang-version is fine.)

I like lang_version.

@nikomatsakis
Copy link
Contributor

@rfcbot cancel

Hi all. This has been in FCP for a very long time and so I am going to cancel the FCP (my personal philosophy is that FCPs should not last this long). I believe it is currently blocked waiting on progress around some kind of subset of cfg-accessible, as described by @joshtriplett here (or perhaps in comments that @joshtriplett is referencing there).

If somebody would like to move this issue forward: The next step would be to open a separate issue regarding that proposal and link it from here, and perhaps we can try to drive that work forward with mentorship or other means?

@rfcbot
Copy link

rfcbot commented Oct 12, 2021

@nikomatsakis proposal cancelled.

@rfcbot rfcbot removed proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. labels Oct 12, 2021
@joshtriplett
Copy link
Member

It looks like cfg(accessible(...)) may be at a state where we could stabilize enough of it to be generally useful, and what's available is enough that I'd consider it to unblock this.

#64797

@joshtriplett joshtriplett added the S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work. label Jun 22, 2022
@alex
Copy link
Member

alex commented Apr 23, 2023

#64797 appears to have stalled out somewhat. I'd like to make an argument for why I believe it'd be appropriate to consider stabilizing this even before cfg(accessible(...)) is stabilized:

  1. There are many use cases for version checking beyond core library types being available. A particularly common one I've seen is version checking to see whether a particular piece of functionality can be used in const contexts.
  2. 3rd party crates for this functionality are already quite common version_check and autocfg both have more than 100 million downloads from crates.io. Under many circumstances, availability of adequate 3rd party crates would ameliorate the need for an in-language solution, however in this case they have a major downside: they require the use of build scripts, which impose a non-trivial compilation time overhead. Build speed is of course a major area of interest -- in a survey of a crate with 56 items in Cargo.lock, about half the build scripts are solely to do version checks.
  3. Because this functionality ultimately is aimed at enabling folks to support multiple versions of Rust more easily, its users won't be able to adopt it until its been stable for quite a while. Therefore getting it out sooner is a big benefit.

@karolherbst
Copy link

karolherbst commented Oct 6, 2023

I hit a bug in Rustc today, where rustc fails to derive Send and Sync automatically in some cyclic type relation context. This is fixed with 1.72, so my use case here would be to #[cfg(version(..))] an unsafe Send block to make sure code compiles with older Rustc.

This is important for the project I'm working on as it's Mesa, the OpenGL/Vulkan/OpenCL/etc.. implementation for the Linux desktop and we need to be mindful of what Rustc version to support.

Edit: Apparently it was Sync stabilized in 1.72 for mpsc::Sender

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B-RFC-approved Feature: Approved by a merged RFC but not yet implemented. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. F-cfg_version `#![feature(cfg_version)]` S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests