Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preliminary feature staging #20663

Merged
merged 1 commit into from
Jan 8, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,18 @@ then
fi
putvar CFG_RELEASE_CHANNEL

# A magic value that allows the compiler to use unstable features
# during the bootstrap even when doing so would normally be an error
# because of feature staging or because the build turns on
# warnings-as-errors and unstable features default to warnings. The
# build has to match this key in an env var. Meant to be a mild
# deterrent from users just turning on unstable features on the stable
# channel.
# Basing CFG_BOOTSTRAP_KEY on CFG_BOOTSTRAP_KEY lets it get picked up
# during a Makefile reconfig.
CFG_BOOTSTRAP_KEY="${CFG_BOOTSTRAP_KEY-`date +%N`}"
putvar CFG_BOOTSTRAP_KEY

step_msg "looking for build programs"

probe_need CFG_PERL perl
Expand Down
11 changes: 11 additions & 0 deletions mk/main.mk
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@ ifeq ($(CFG_RELEASE_CHANNEL),stable)
CFG_RELEASE=$(CFG_RELEASE_NUM)
# This is the string used in dist artifact file names, e.g. "0.12.0", "nightly"
CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)
CFG_DISABLE_UNSTABLE_FEATURES=1
endif
ifeq ($(CFG_RELEASE_CHANNEL),beta)
# The beta channel is temporarily called 'alpha'
CFG_RELEASE=$(CFG_RELEASE_NUM)-alpha$(CFG_BETA_CYCLE)
CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)-alpha$(CFG_BETA_CYCLE)
CFG_DISABLE_UNSTABLE_FEATURES=1
endif
ifeq ($(CFG_RELEASE_CHANNEL),nightly)
CFG_RELEASE=$(CFG_RELEASE_NUM)-nightly
Expand Down Expand Up @@ -319,11 +321,20 @@ export CFG_VERSION_WIN
export CFG_RELEASE
export CFG_PACKAGE_NAME
export CFG_BUILD
export CFG_RELEASE_CHANNEL
export CFG_LLVM_ROOT
export CFG_PREFIX
export CFG_LIBDIR
export CFG_LIBDIR_RELATIVE
export CFG_DISABLE_INJECT_STD_VERSION
ifdef CFG_DISABLE_UNSTABLE_FEATURES
CFG_INFO := $(info cfg: disabling unstable features (CFG_DISABLE_UNSTABLE_FEATURES))
# Turn on feature-staging
export CFG_DISABLE_UNSTABLE_FEATURES
endif
# Subvert unstable feature lints to do the self-build
export CFG_BOOTSTRAP_KEY
export RUSTC_BOOTSTRAP_KEY:=$(CFG_BOOTSTRAP_KEY)

######################################################################
# Per-stage targets and runner
Expand Down
1 change: 1 addition & 0 deletions src/liballoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
#![crate_name = "alloc"]
#![experimental]
#![staged_api]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
Expand Down
1 change: 1 addition & 0 deletions src/libarena/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#![crate_name = "arena"]
#![experimental]
#![staged_api]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
Expand Down
1 change: 1 addition & 0 deletions src/libcollections/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#![crate_name = "collections"]
#![experimental]
#![staged_api]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
Expand Down
1 change: 1 addition & 0 deletions src/libcore/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@

#![crate_name = "core"]
#![experimental]
#![staged_api]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
Expand Down
1 change: 1 addition & 0 deletions src/libflate/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#![crate_name = "flate"]
#![experimental]
#![staged_api]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
Expand Down
1 change: 1 addition & 0 deletions src/libfmt_macros/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#![crate_name = "fmt_macros"]
#![experimental]
#![staged_api]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
Expand Down
1 change: 1 addition & 0 deletions src/libgetopts/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
#![crate_name = "getopts"]
#![experimental = "use the crates.io `getopts` library instead"]
#![staged_api]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
Expand Down
1 change: 1 addition & 0 deletions src/libgraphviz/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@
#![crate_name = "graphviz"]
#![experimental]
#![staged_api]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
Expand Down
1 change: 1 addition & 0 deletions src/liblibc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#![crate_name = "libc"]
#![crate_type = "rlib"]
#![cfg_attr(not(feature = "cargo-build"), experimental)]
#![cfg_attr(not(feature = "cargo-build"), staged_api)]
#![no_std]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
Expand Down
1 change: 1 addition & 0 deletions src/liblog/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@
#![crate_name = "log"]
#![experimental = "use the crates.io `log` library instead"]
#![staged_api]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
Expand Down
1 change: 1 addition & 0 deletions src/librand/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#![no_std]
#![experimental]
#![staged_api]

#[macro_use]
extern crate core;
Expand Down
1 change: 1 addition & 0 deletions src/librbml/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#![crate_name = "rbml"]
#![experimental]
#![staged_api]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
Expand Down
1 change: 1 addition & 0 deletions src/libregex/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![experimental = "use the crates.io `regex` library instead"]
#![staged_api]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/nightly/",
Expand Down
1 change: 1 addition & 0 deletions src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#![crate_name = "rustc"]
#![experimental]
#![staged_api]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
Expand Down
77 changes: 67 additions & 10 deletions src/librustc/lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use middle::{def, pat_util, stability};
use middle::const_eval::{eval_const_expr_partial, const_int, const_uint};
use util::ppaux::{ty_to_string};
use util::nodemap::{FnvHashMap, NodeSet};
use lint::{Context, LintPass, LintArray};
use lint::{Context, LintPass, LintArray, Lint};

use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::num::SignedInt;
Expand Down Expand Up @@ -1643,19 +1643,27 @@ declare_lint! {
"detects use of #[unstable] items (incl. items with no stability attribute)"
}

declare_lint!(STAGED_EXPERIMENTAL, Warn,
"detects use of #[experimental] items in staged builds");

declare_lint!(STAGED_UNSTABLE, Warn,
"detects use of #[unstable] items (incl. items with no stability attribute) \
in staged builds");

/// Checks for use of items with `#[deprecated]`, `#[experimental]` and
/// `#[unstable]` attributes, or no stability attribute.
#[derive(Copy)]
pub struct Stability;

impl Stability {
fn lint(&self, cx: &Context, id: ast::DefId, span: Span) {
let stability = stability::lookup(cx.tcx, id);

let ref stability = stability::lookup(cx.tcx, id);
let cross_crate = !ast_util::is_local(id);

// stability attributes are promises made across crates; only
// check DEPRECATED for crate-local usage.
let (lint, label) = match stability {
let (lint, label) = match *stability {
// no stability attributes == Unstable
None if cross_crate => (UNSTABLE, "unmarked"),
Some(attr::Stability { level: attr::Unstable, .. }) if cross_crate =>
Expand All @@ -1667,24 +1675,53 @@ impl Stability {
_ => return
};

let msg = match stability {
Some(attr::Stability { text: Some(ref s), .. }) => {
format!("use of {} item: {}", label, *s)
output(cx, span, stability, lint, label);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be in an else attached to the if? It seems strange to possibly emit two errors?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps you are correct. I'll do some testing locally.

if cross_crate && stability::is_staged_api(cx.tcx, id) {
if lint.name == UNSTABLE.name {
output(cx, span, stability, STAGED_UNSTABLE, label);
} else if lint.name == EXPERIMENTAL.name {
output(cx, span, stability, STAGED_EXPERIMENTAL, label);
}
_ => format!("use of {} item", label)
};
}

cx.span_lint(lint, span, msg.index(&FullRange));
fn output(cx: &Context, span: Span, stability: &Option<attr::Stability>,
lint: &'static Lint, label: &'static str) {
let msg = match *stability {
Some(attr::Stability { text: Some(ref s), .. }) => {
format!("use of {} item: {}", label, *s)
}
_ => format!("use of {} item", label)
};

cx.span_lint(lint, span, msg.index(&FullRange));
}
}


fn is_internal(&self, cx: &Context, span: Span) -> bool {
cx.tcx.sess.codemap().span_is_internal(span)
}

}

impl LintPass for Stability {
fn get_lints(&self) -> LintArray {
lint_array!(DEPRECATED, EXPERIMENTAL, UNSTABLE)
lint_array!(DEPRECATED, EXPERIMENTAL, UNSTABLE, STAGED_EXPERIMENTAL, STAGED_UNSTABLE)
}

fn check_crate(&mut self, _: &Context, c: &ast::Crate) {
// Just mark the #[staged_api] attribute used, though nothing else is done
// with it during this pass over the source.
for attr in c.attrs.iter() {
if attr.name().get() == "staged_api" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could theoretically just be attr.check_name("staged_api");.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, maybe you're restricting to #[staged_api] only, so #[staged_api = ".."] and #[staged_api(...)] aren't considered used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. We seem to be inconsistent in this.

match attr.node.value.node {
ast::MetaWord(_) => {
attr::mark_used(attr);
}
_ => (/*pass*/)
}
}
}
}

fn check_view_item(&mut self, cx: &Context, item: &ast::ViewItem) {
Expand Down Expand Up @@ -1746,6 +1783,7 @@ impl LintPass for Stability {
}
_ => return
};

self.lint(cx, id, span);
}

Expand Down Expand Up @@ -1878,3 +1916,22 @@ impl LintPass for HardwiredLints {
)
}
}

/// Forbids using the `#[feature(...)]` attribute
#[deriving(Copy)]
pub struct UnstableFeatures;

declare_lint!(UNSTABLE_FEATURES, Allow,
"enabling unstable features");

impl LintPass for UnstableFeatures {
fn get_lints(&self) -> LintArray {
lint_array!(UNSTABLE_FEATURES)
}
fn check_attribute(&mut self, ctx: &Context, attr: &ast::Attribute) {
use syntax::attr;
if attr::contains_name(&[attr.node.value.clone()], "feature") {
ctx.span_lint(UNSTABLE_FEATURES, attr.span, "unstable feature");
}
}
}
46 changes: 43 additions & 3 deletions src/librustc/lint/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ use self::TargetLint::*;
use middle::privacy::ExportedItems;
use middle::ty::{self, Ty};
use session::{early_error, Session};
use session::config::UnstableFeatures;
use lint::{Level, LevelSource, Lint, LintId, LintArray, LintPass, LintPassObject};
use lint::{Default, CommandLine, Node, Allow, Warn, Deny, Forbid};
use lint::{Default, CommandLine, Node, Allow, Warn, Deny, Forbid, ReleaseChannel};
use lint::builtin;
use util::nodemap::FnvHashMap;

Expand Down Expand Up @@ -210,6 +211,7 @@ impl LintStore {
UnusedAllocation,
Stability,
MissingCopyImplementations,
UnstableFeatures,
);

add_builtin_with_new!(sess,
Expand Down Expand Up @@ -298,6 +300,29 @@ impl LintStore {
}
}
}

fn maybe_stage_features(&mut self, sess: &Session) {
let lvl = match sess.opts.unstable_features {
UnstableFeatures::Default => return,
UnstableFeatures::Disallow => Warn,
UnstableFeatures::Cheat => Allow
};
match self.by_name.get("unstable_features") {
Some(&Id(lint_id)) => self.set_level(lint_id, (lvl, ReleaseChannel)),
Some(&Renamed(_, lint_id)) => self.set_level(lint_id, (lvl, ReleaseChannel)),
None => unreachable!()
}
match self.by_name.get("staged_unstable") {
Some(&Id(lint_id)) => self.set_level(lint_id, (lvl, ReleaseChannel)),
Some(&Renamed(_, lint_id)) => self.set_level(lint_id, (lvl, ReleaseChannel)),
None => unreachable!()
}
match self.by_name.get("staged_experimental") {
Some(&Id(lint_id)) => self.set_level(lint_id, (lvl, ReleaseChannel)),
Some(&Renamed(_, lint_id)) => self.set_level(lint_id, (lvl, ReleaseChannel)),
None => unreachable!()
}
}
}

/// Context for lint checking.
Expand Down Expand Up @@ -380,6 +405,7 @@ pub fn raw_emit_lint(sess: &Session, lint: &'static Lint,
if level == Allow { return }

let name = lint.name_lower();
let mut def = None;
let mut note = None;
let msg = match source {
Default => {
Expand All @@ -394,7 +420,13 @@ pub fn raw_emit_lint(sess: &Session, lint: &'static Lint,
}, name.replace("_", "-"))
},
Node(src) => {
note = Some(src);
def = Some(src);
msg.to_string()
}
ReleaseChannel => {
let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
note = Some(format!("this feature may not be used in the {} release channel",
release_channel));
msg.to_string()
}
};
Expand All @@ -410,7 +442,11 @@ pub fn raw_emit_lint(sess: &Session, lint: &'static Lint,
_ => sess.bug("impossible level in raw_emit_lint"),
}

for span in note.into_iter() {
for note in note.into_iter() {
sess.note(note.index(&FullRange));
}

for span in def.into_iter() {
sess.span_note(span, "lint level defined here");
}
}
Expand Down Expand Up @@ -767,6 +803,10 @@ impl LintPass for GatherNodeLevels {
/// Consumes the `lint_store` field of the `Session`.
pub fn check_crate(tcx: &ty::ctxt,
exported_items: &ExportedItems) {

// If this is a feature-staged build of rustc then flip several lints to 'forbid'
tcx.sess.lint_store.borrow_mut().maybe_stage_features(&tcx.sess);

let krate = tcx.map.krate();
let mut cx = Context::new(tcx, krate, exported_items);

Expand Down
Loading