How about enabling semi-stable features in Cargo.toml
as was proposed by @bill_myers? This way we will keep notion of semi-stable features outside of stable language and will be able to use semi-stable feature versions for nice errors. Plus you will be able to quickly understand semi-stable features used by a crate.
In other words, something like this:
[package]
name = "foo"
version = "0.1.0"
[lang-features]
async = "1"
const-generics = "1"
Yes, cargo
will have to keep table of stable and semi-stable features, but at the first glance it does not look like a too complex addition.
Stable toolchain will check versions of enabled lang features and if those feature/version pairs were indeed stabilized will emit a warning and will continue as usual, otherwise it will return compilation error.
Maybe we could even use it for enabling unstable features as well, e.g. by using foo = "0"
to indicate instability.