use parse::token::InternedString;
use std::ascii::AsciiExt;
+use std::env;
macro_rules! setter {
($field: ident) => {{
is just used for rustc unit tests \
and will never be stable",
cfg_fn!(rustc_attrs))),
+ ("rustc_metadata_dirty", Whitelisted, Gated("rustc_attrs",
+ "the `#[rustc_metadata_dirty]` attribute \
+ is just used for rustc unit tests \
+ and will never be stable",
+ cfg_fn!(rustc_attrs))),
+ ("rustc_metadata_clean", Whitelisted, Gated("rustc_attrs",
+ "the `#[rustc_metadata_clean]` attribute \
+ is just used for rustc unit tests \
+ and will never be stable",
+ cfg_fn!(rustc_attrs))),
("rustc_partition_reused", Whitelisted, Gated("rustc_attrs",
"this attribute \
is just used for rustc unit tests \
pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) {
let (cfg, feature, has_feature) = GATED_CFGS[self.index];
if !has_feature(features) && !sess.codemap().span_allows_unstable(self.span) {
- let diagnostic = &sess.span_diagnostic;
let explain = format!("`cfg({})` is experimental and subject to change", cfg);
- emit_feature_err(diagnostic, feature, self.span, GateIssue::Language, &explain);
+ emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain);
}
}
}
struct Context<'a> {
features: &'a Features,
- span_handler: &'a Handler,
+ parse_sess: &'a ParseSess,
cm: &'a CodeMap,
plugin_attributes: &'a [(String, AttributeType)],
}
let has_feature: bool = has_feature(&$cx.features);
debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
if !has_feature && !cx.cm.span_allows_unstable(span) {
- emit_feature_err(cx.span_handler, name, span, GateIssue::Language, explain);
+ emit_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain);
}
}}
}
}
}
-pub fn check_attribute(attr: &ast::Attribute, handler: &Handler,
+pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess,
cm: &CodeMap, features: &Features) {
let cx = Context {
- features: features, span_handler: handler,
+ features: features, parse_sess: parse_sess,
cm: cm, plugin_attributes: &[]
};
cx.check_attribute(attr, true);
Library(Option<u32>)
}
-pub fn emit_feature_err(diag: &Handler, feature: &str, span: Span, issue: GateIssue,
+pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
explain: &str) {
+ let diag = &sess.span_diagnostic;
+
let issue = match issue {
GateIssue::Language => find_lang_feature_issue(feature),
GateIssue::Library(lib) => lib,
};
// #23973: do not suggest `#![feature(...)]` if we are in beta/stable
- if option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some() {
- err.emit();
- return;
+ if sess.unstable_features.is_nightly_build() {
+ err.help(&format!("add #![feature({})] to the \
+ crate attributes to enable",
+ feature));
}
- err.help(&format!("add #![feature({})] to the \
- crate attributes to enable",
- feature));
+
err.emit();
}
if attr::contains_name(&i.attrs[..], "simd") {
gate_feature_post!(&self, simd, i.span,
"SIMD types are experimental and possibly buggy");
- self.context.span_handler.span_warn(i.span,
- "the `#[simd]` attribute is deprecated, \
- use `#[repr(simd)]` instead");
+ self.context.parse_sess.span_diagnostic.span_warn(i.span,
+ "the `#[simd]` attribute \
+ is deprecated, use \
+ `#[repr(simd)]` instead");
}
for attr in &i.attrs {
if attr.name() == "repr" {
fn visit_pat(&mut self, pattern: &ast::Pat) {
match pattern.node {
- PatKind::Vec(_, Some(_), ref last) if !last.is_empty() => {
+ PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => {
gate_feature_post!(&self, advanced_slice_patterns,
pattern.span,
"multiple-element slice matches anywhere \
but at the end of a slice (e.g. \
`[0, ..xs, 0]`) are experimental")
}
- PatKind::Vec(..) => {
+ PatKind::Slice(..) => {
gate_feature_post!(&self, slice_patterns,
pattern.span,
"slice pattern syntax is experimental");
maybe_stage_features(&sess.span_diagnostic, krate, unstable);
let ctx = Context {
features: features,
- span_handler: &sess.span_diagnostic,
+ parse_sess: sess,
cm: sess.codemap(),
plugin_attributes: plugin_attributes,
};
Cheat
}
+impl UnstableFeatures {
+ pub fn from_environment() -> UnstableFeatures {
+ // Whether this is a feature-staged build, i.e. on the beta or stable channel
+ let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
+ // The secret key needed to get through the rustc build itself by
+ // subverting the unstable features lints
+ let bootstrap_secret_key = option_env!("CFG_BOOTSTRAP_KEY");
+ // The matching key to the above, only known by the build system
+ let bootstrap_provided_key = env::var("RUSTC_BOOTSTRAP_KEY").ok();
+ match (disable_unstable_features, bootstrap_secret_key, bootstrap_provided_key) {
+ (_, Some(ref s), Some(ref p)) if s == p => UnstableFeatures::Cheat,
+ (true, _, _) => UnstableFeatures::Disallow,
+ (false, _, _) => UnstableFeatures::Allow
+ }
+ }
+
+ pub fn is_nightly_build(&self) -> bool {
+ match *self {
+ UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
+ _ => false,
+ }
+ }
+}
+
fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
unstable: UnstableFeatures) {
let allow_features = match unstable {