Open
Description
we really should not have features that are available only on nightly but do not have a feature gate. this leads to people unknowingly using unstable features, which in turn leads to situations where we have no choice but to stabilize features unchanged because otherwise we break too much of the ecosystem. it also defeats the whole point of -Z allow-features
.
we should do two things:
- audit all existing features to make sure they have a feature gate. @jieyouxu tells me that at least
#[cfg(target_has_atomic)]
does not. - add an internal lint against
UnstableFeatures::is_nightly_build
. basically the only reason it's valid to check this is for diagnostics, or very early in session building, and both of those can add an explicitallow()
.
@rustbot label A-stability
Metadata
Metadata
Assignees
Labels
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
Zalathar commentedon Apr 16, 2025
There are a few different ways for arbitrary compiler code to check whether the compiler is nightly:
Session::is_nightly_build
(ontcx.sess
)UnstableFeatures::is_nightly_build
(obtained viaUnstableFeatures::from_environment
)nightly_options
So it would be useful to audit all of these.
I could also imagine splitting some of these APIs into diagnostic-only and non-diagnostic variants, so that it's easier to audit the legitimate exceptions.
RalfJung commentedon Apr 16, 2025
FWIW,
cfg(target_feature)
also changes behavior on nighty by adding information about nightly target features. I think the reason is the lack of a good discoverable alternative: we don't really have a way to gatecfg(target_feature = "nightly_feature")
specifically; that expression compiles fine on stable, it just always evaluates to false. We could say you have to set#[feature(nightly_target_features)]
, or set the feature gate guarding that specific nightly target feature, but thencfg(target_feature = "nightly_feature")
would just silently become "false" and users wouldn't know they have to set a feature gate.bjorn3 commentedon Apr 16, 2025
All unstable cfg's are implicitly available on the nightly channel. Note that cargo needs to know which cfg's are set before compiling a single line of rust code (so
#![feature]
wouldn't work for it) and rustc doesn't know which features are enabled until the cfg's for the crate root are evaluated.jyn514 commentedon Apr 16, 2025
what does cargo need this information for? my understanding is that this is an internal feature that is only used by libstd - we shouldn't have
[cfg.'target_has_atomic'.dependencies]
or anything like that.we should ban unstable cfgs at the crate root IMO.
that makes sense to me and is a little trickier - perhaps it could continue to be "false", but not silently? where we give a future-incompat lint that the behavior may change, and you can use
feature()
to opt in today?bjorn3 commentedon Apr 16, 2025
target_has_atomic_load_store
andtarget_has_atomic_equal_alignment
are not the only unstable cfgs (target_has_atomic
is stable by the way). The example Ralf gave ofcfg(target_feature = "nightly_feature")
is another one which will become stable in the future. Andtarget_has_atomic_load_store
seems like it would be useful to stabilize in the future. And some code (especially those that use inline asm) needscfg(relocation_model)
.jyn514 commentedon Apr 16, 2025
got it, that makes sense. i still think "continues to evaluate to false until you enable a feature gate, warns if the gate is disabled" is a reasonable solution and better than enabling unconditionally on nightly.
target_has_atomic with a value (e.g. 16) is stable, but target_has_atomic without a value is not.