Preliminary feature staging
This partially implements the feature staging described in the [release channel RFC][rc]. It does not yet fully conform to the RFC as written, but does accomplish its goals sufficiently for the 1.0 alpha release. It has three primary user-visible effects: * On the nightly channel, use of unstable APIs generates a warning. * On the beta channel, use of unstable APIs generates a warning. * On the beta channel, use of feature gates generates a warning. Code that does not trigger these warnings is considered 'stable', modulo pre-1.0 bugs. Disabling the warnings for unstable APIs continues to be done in the existing (i.e. old) style, via `#[allow(...)]`, not that specified in the RFC. I deem this marginally acceptable since any code that must do this is not using the stable dialect of Rust. Use of feature gates is itself gated with the new 'unstable_features' lint, on nightly set to 'allow', and on beta 'warn'. The attribute scheme used here corresponds to an older version of the RFC, with the `#[staged_api]` crate attribute toggling the staging behavior of the stability attributes, but the user impact is only in-tree so I'm not concerned about having to make design changes later (and I may ultimately prefer the scheme here after all, with the `#[staged_api]` crate attribute). Since the Rust codebase itself makes use of unstable features the compiler and build system to a midly elaborate dance to allow it to bootstrap while disobeying these lints (which would otherwise be errors because Rust builds with `-D warnings`). This patch includes one significant hack that causes a regression. Because the `format_args!` macro emits calls to unstable APIs it would trigger the lint. I added a hack to the lint to make it not trigger, but this in turn causes arguments to `println!` not to be checked for feature gates. I don't presently understand macro expansion well enough to fix. This is bug #20661. Closes #16678 [rc]: https://github.com/rust-lang/rfcs/blob/master/text/0507-release-channels.md
This commit is contained in:
@@ -48,7 +48,7 @@ fn no_prelude(attrs: &[ast::Attribute]) -> bool {
|
||||
}
|
||||
|
||||
struct StandardLibraryInjector<'a> {
|
||||
alt_std_name: Option<String>,
|
||||
alt_std_name: Option<String>
|
||||
}
|
||||
|
||||
impl<'a> fold::Folder for StandardLibraryInjector<'a> {
|
||||
@@ -84,14 +84,13 @@ impl<'a> fold::Folder for StandardLibraryInjector<'a> {
|
||||
|
||||
fn inject_crates_ref(krate: ast::Crate, alt_std_name: Option<String>) -> ast::Crate {
|
||||
let mut fold = StandardLibraryInjector {
|
||||
alt_std_name: alt_std_name,
|
||||
alt_std_name: alt_std_name
|
||||
};
|
||||
fold.fold_crate(krate)
|
||||
}
|
||||
|
||||
struct PreludeInjector<'a>;
|
||||
|
||||
|
||||
impl<'a> fold::Folder for PreludeInjector<'a> {
|
||||
fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
|
||||
// Add #![no_std] here, so we don't re-inject when compiling pretty-printed source.
|
||||
@@ -104,20 +103,10 @@ impl<'a> fold::Folder for PreludeInjector<'a> {
|
||||
attr::mark_used(&no_std_attr);
|
||||
krate.attrs.push(no_std_attr);
|
||||
|
||||
// only add `use std::prelude::*;` if there wasn't a
|
||||
// `#![no_implicit_prelude]` at the crate level.
|
||||
// fold_mod() will insert glob path.
|
||||
if !no_prelude(krate.attrs.index(&FullRange)) {
|
||||
// only add `use std::prelude::*;` if there wasn't a
|
||||
// `#![no_implicit_prelude]` at the crate level.
|
||||
// fold_mod() will insert glob path.
|
||||
let globs_attr = attr::mk_attr_inner(attr::mk_attr_id(),
|
||||
attr::mk_list_item(
|
||||
InternedString::new("feature"),
|
||||
vec!(
|
||||
attr::mk_word_item(InternedString::new("globs")),
|
||||
)));
|
||||
// std_inject runs after feature checking so manually mark this attr
|
||||
attr::mark_used(&globs_attr);
|
||||
krate.attrs.push(globs_attr);
|
||||
|
||||
krate.module = self.fold_mod(krate.module);
|
||||
}
|
||||
krate
|
||||
|
||||
Reference in New Issue
Block a user