Couple of thoughts, sorry for the scattershot reply but there’s not a common thread between them.
Features are supposed to be additive, so a feature to disable parts of a crate doesn’t make much sense
By “feature” I just mean some flag for conditional compilation. Also, features can totally be used to disable compilation through #[cfg(not())] attributes, but that’s neither here nor there because I’m imagining a more native support than ‘just’ using the feature system.
Everything that belongs to a top-level crate is built no matter what (otherwise main() would have to be #[stable], for example).
If you feel that main needs to always be built, Rust already has an internal notion of the “main” function, and you could just always build that item. Though with #[cfg(not())], you could conditionally fail to compile main today & I don’t see that as an inherent problem. More importantly, I don’t think this attribute should be aware of which module it is in.
I don’t see why a binary would ever be compiled with the “stable only” feature activated, but I think that ties into my next comment.
By default, dependencies only have their stable and unspecified items built.
There are a few different definitions of “by default” - what rustc does by default and what cargo does by default.
I think, by default, rustc should ignore these attributes. But rustc can accept flags which control how it interprets stable/unstable/absent attributes.
I think there are a couple of different valid default options for cargo. What you’ve said is one of them, but here’s another (I’ve no strong opinion about which is better):
cargo does not pass any argument to rustc by default; by default this system is ignored. A crate’s Cargo.toml, though, can have an attribute indicating that it is using stability attributes; if it has that attribute that means that when compiling it as a dependency, only stable items should be compiled (not untagged items).
Rust gains a new extern crate attribute, #[unstable_use], which is basically #[macro_use] but for unstable items.
I’d much rather this be an attribute you add to your declaration of that dependency in Cargo.toml, not an attribute to the extern crate declaration. But the principle is the same.
rustc does not gain awareness of crate stability. Instead, Cargo is responsible for ensuring that >= 1.0.0 crates are sound (i.e. contain either no publically-visible items, or at least one publically-visible stable item; eventually unspecified items will be banned as well).
I don’t like this part of the RFC at all - I don’t think crates should be compelled to use this system. I’d much rather the situation be that crates can choose to use this system, in which untagged items are treated as unstable.
Long story short: if an item is #[deprecated], it’s now recognised as being unstable in addition to being recognised as deprecated (but rustc only warns about the item being deprecated). I agree that the text should be clearer about this.
This isn’t consistent with how deprecation works in std. In std, if an item is deprecated, it is still “stable,” it just emits a deprecation warning.