What is the best way to make a crate compatible with the beta (and eventually stable) channel, while using unstable features/APIs if compiled with a nightly channel release? As an example, take the ecs-rs crate: it's only incompatible with the beta because it uses Vec<T>::drain
and VecMap<T>
which are behind feature gates. There are less efficient alternatives in the beta channel that could be easily substituted for these unstable features (cf. https://github.com/tomjakubowski/ecs-rs/commit/52cfc692224e634d882e3feb5347109db4e2e84e).
Would this be an appropriate use of Cargo features (combined with #[cfg_attr(.)] and #[cfg(..)]
, to swap out implementations depending on Rust release one wishes to use? It seems like it could be problematic (consider if ecs-rs
is a transitive dependency, for example). Is this a feature worth supporting directly in Cargo?
1 Like
As I read the cargo docs, that's exactly what features are for. And they are supported directly in Cargo.
It's awfully inconvenient to use them for this purpose because every library crate that depends on such a library would need to have its own ad-hoc beta/nightly support feature, so it could build its dependencies with the correct beta/nightly feature as well. That sounds like a nightmare to me.
I found this thread on internals which suggests an appropriate enhancement to the Rust distribution to support this use case. Setting cfg(nightly) on nightly by default - Rust Internals
Exactly. Cargo features are not flags. They are not designed for these kind of things.
In that case I misread the cargo docs and you should disregard my previous comment.
My two cents:
I think cargo features really are what you should use for this, with a 'nightly-features' feature which depends on the nightly versions of all of your crate's dependencies.
I would oppose a method to compile code depending on rust channel without having input from the end binary crate (like enabling the nightly feature).
The problem I see with having some way to change the code depending on release channel is that you can then have a crate which compiles on the latest release, and then fails to compile on the nightly directly after. If your crate compiles on the latest beta/stable, there should be a guarantee that is compiles on later versions (even if those are nightly).
Allowing a crate that compiles on 1.0.0 to be subject to breaking changes in unstable features on nightlies without the user explicitly choosing to have the library use unstable features is a breach of contract.