Allow external crate to use unnecessary #[feature] on stable

I suspect the rules will need to be slightly changed if the feature attribute itself becomes stable, like this post proposes.

E.g. #![feature(ident)] is a feature error if ident belongs to the list of unstable features, and a lint from the unused group otherwise (probably deny-by-default).

This way we can garbage collect stable features as we want, it will only affect diagnostics wording.
There is a minor compatibility issue though - introduction of a new feature foo is technically a breaking change since it moves #![feature(foo)] from a lint to a hard error, but that’s probably not an issue in practice.

It’s not entirely clear how the “unstable” list is collected though.
For language features it’s hard-coded, but for library features it needs to be actively collected, which may be unfriendly to lazy compilation (i.e. want to check feature(foo) -> look through the whole standard library? other dependencies?).

1 Like

I was proposing something similar in this thread:

One of the concerns was adding notion of features to stable lang, this is why one of the alternatives developed during discussion was to move enabling of features to Cargo.toml.

1 Like

My reaction to this case is that, if the feature went through no significant changes for that long, then either it should’ve been stabilized a while ago, or it’s fallen into some kind of “limbo” status.

So maybe this is all just a symptom of us having too many feature flags in limbo status, and the proper solution is instead addressing things like “organizational debt” and the backlog of almost-but-not-quite-finished features, which are already explicit parts of our roadmap.


(This isn’t true anymore; we have INCOMPLETE_FEATURES for the things that aren’t (but we also emit a lint for such features so you will know when you use them).)

I think this adds hugely to the complexity and burden of being a compiler developer since you have to bump the version everytime you do a subtle “breaking” change. I’m not willing to add this burden to an already overburdened compiler team.

Yes, as I see it, + are monotonically adding garbage with the current situation.

Stabilizing the feature system not only stabilizes names (worse if you have some sort of #[cfg(rust_feature = "my_feature")] in which case you cannot ever garbage collect), as @petrochenkov notes we can still probably garbage collect with #![feature(foo)] but it forces a particular mode of language development using feature gates on rustc and alternative Rust compiler.

If we insist on supporting situations like this, then #[cfg(accessible(::std::foo::bar))] + #[cfg_attr(feature = "unstable", feature(feature_that_provides_foo_bar))] seems cleaner.

I’d like to observe that this need not be true- there is certainly no reason that we can’t make the behavior of #![feature("..")] implementation-defined and non-portable. I argue that this is the current behavior, wherein stable completely bans it, and nightly changes its behavior on a small whitelist of values.


Couldn’t the stable compiler just simply ignore any #![feature(..)] pragmas?

I think this should not be a feature of the Rust language, that is it would be really weird to have a page in the Rust language reference saying that you can write #![feature(repr_transparent)] at the top of your crate.

If anything, it could be a convenience feature of rustc itself where some recently stabilized features only emit a warning instead of an error, where recently could mean during the last two or four or eight versions, or maybe even more, but still a limited period.

I think I would find this compelling if there were multiple Rust compilers and every “serious” project was expected to run at least two of them in their CI, like in the C++ world. But for better or worse, that’s not a thing yet, so anything that rustc deems a non-error on stable today simply is de facto standardized forever.


Personally, I find the near constant calls to allow “Unstable” things on “Stable” to be a complete contradiction. Either you are targeting stable or you are experimenting with unstable features on nightly. Never the two shall meet.

If a library you want to use is unstable, and you want to target stable, you simply cannot use that library, FULL STOP. If a library remains on nightly just because no one has updated it to use the stable features (and remove references to the unstable “feature” flag), then there are two and ONLY two solutions:

  • Get the maintainers to fix the library
  • Fork the library and make a stable version

That’s it. That’s the fix. Please, DO NOT COMPROMISE on this. DO NOT mix unstable/nightly into the stable branch in some sort of frankenstein-like, chimeric disaster.


No one in this thread is proposing to make unstable features accessible on stable. This post uses a very dramatic register while significantly misunderstanding the discussion. I find this frustrating and disappointing.


What if I don’t depend on that library directly? Instead, the library I use uses no #[feature] flag but depends on another library that uses one.

This is very unproductive. I first have to make an issue, then I have to wait for the secondary dependency to resolve my request, and then my direct dependency to update the secondary dependency, only then shall I be able to continue normally.

If it is "just allow #[feature]", then only that library needs an update: it’s a semver-patch level change, and then a cargo update to recalculate your lock will pick the new version.

And a crate depending on a crate which is nightly-only is nightly-only as well, it’s transitive.

To those who want this kind of feature for rustc: what feature flags would you have benefitted from having this, and what libraries did they reside in? I’d posit any feature that is both stable and old enough to hurt here probably should have been stabilized already, and the correct direction is to push for the stabilization or removal of these older, “almost finished” features before forward-stable-compatibility of using them.


I think his post understands the situation precisely and it actually reflects my understanding and opinion. Stating whether you’re frustrated or not doesn’t seem to add to the discussion.

1 Like

Moderation note: Let’s please increase the quality of discussion here. It is veering into unproductive territory. If it doesn’t improve, then we’re just going to lock the thread.

1 Like

I think part of the problem with allowing #[feature] on stable (for features that are already stabilized) is that it’s not clear that the crate intends to support stable Rust just yet. Any crate that is using #[feature] is targeting nightly (and any crate that depends on such crate is also targeting nightly, by necessity).

If #[feature(foo)] gets stabilized and #[feature(foo)] is permitted on stable, it might give the false impression that the crate supports stable Rust. But that’s not necessarily the case. The crate might target only nightly (even if it’s only using stable features) because it wants to use an upcoming unstable feature. If the crate then adds #[feature(bar)] (where bar is unstable), all stable Rust users of the crate will break.

This is why I’m personally opposed to using #[feature] on stable. I think it’s best to fix the upstream crate, which will give the crate authors the opportunity to reject stable Rust if they’re intentionally targeting nightly Rust and don’t want to give the false impression of stability.


This has me convinced:

Switching from stable to nightly is (at least!) equivalent to a semver major version bump. So letting nightly crates more-or-less accidentally work on stable means that authors of nightly crates would have the surprising duty, before releasing a new minor version, of making sure either that the old version didn’t work on stable, or that the new version does. And that applies to every nightly crate, not just old unmaintained crates.

Bump the major version number for the bug fix that happens to start using an unstable feature, or face the wrath of your users! Your stable users, that you didn’t want in the first place. :slight_smile:


Then the library isn’t stable because it has dependencies that aren’t stable.

As a long time open source maintainer, I’ll give you the advice that I gave to every user who opened an issue on our repository. The fastest way to see a change made is to do the work and submit a pull request. Most of us building OOS do it as a hobby in our spare time. We always appreciate contributions. Yes, you may need to point your actual project at your fork for a minute until the maintainer can merge your PR and publish a new release, but it gives you a path forward and the library gets a needed update. That’s a win for everyone involved. That’s how open source is supposed to work, and in my humble opinion, is the right solution to this problem. Not all problems require technical solutions. Some just require people working together to make the community a better place for everyone.


This deserves to be the “Quote of the Week” IMHO!


This is actually a very fair concern that probably tips the scales. To reiterate it in other language: right now, if you already use the feature attribute, it is considered fair game to only support the latest nightly. This means its not a breaking change to add dependencies on additional features. But if that could spill over into supporting some stable versions, you would be breaking those users.

This could lead to more surprise broken builds, which are worse than crates that don’t compile on stable for no reason, because they impact users at unexpected times.


This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.