diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 0273f4fe00f3b..560a1c152dc9a 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -43,8 +43,9 @@ use lint::{LintPass, LateLintPass, EarlyLintPass, EarlyContext}; use std::collections::HashSet; -use syntax::{ast, feature_gate}; +use syntax::ast; use syntax::attr; +use syntax::feature_gate::{AttributeGate, Stability, with_deprecated_attributes}; use syntax_pos::Span; use rustc::hir::{self, PatKind}; @@ -760,18 +761,23 @@ impl LintPass for DeprecatedAttr { impl EarlyLintPass for DeprecatedAttr { fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) { let name = &*attr.name(); - for &(n, _, ref g) in feature_gate::KNOWN_ATTRIBUTES { - if n == name { - if let &feature_gate::AttributeGate::Gated(feature_gate::Stability::Deprecated, - ref name, - ..) = g { - cx.span_lint(DEPRECATED, - attr.span, - &format!("use of deprecated attribute: {}", name)); + with_deprecated_attributes(|depr_attrs| { + for &&(n, _, ref g) in depr_attrs { + if n == name { + if let &AttributeGate::Gated(Stability::Deprecated(link), + ref name, + ref reason, + _) = g { + cx.span_lint(DEPRECATED, + attr.span, + &format!("use of deprecated attribute `{}`: {}. See {}", + name, reason, link)); + } + // Returns from the closure, skipping the rest of the loop. + return; } - return; } - } + }) } } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index c14496f31db50..64cd686420e9e 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -37,6 +37,7 @@ #![feature(rustc_private)] #![feature(slice_patterns)] #![feature(staged_api)] +#![feature(dotdot_in_tuple_patterns)] #[macro_use] extern crate syntax; diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 2e15a454df12e..bb3cf3512f078 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -377,17 +377,28 @@ pub enum AttributeGate { Ungated, } -#[derive(Copy, Clone, PartialEq, Eq)] +impl AttributeGate { + fn is_deprecated(&self) -> bool { + match *self { + Gated(Stability::Deprecated(_), ..) => true, + _ => false, + } + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum Stability { Unstable, - Deprecated, + // Argument is tracking issue link. + Deprecated(&'static str), } // fn() is not Debug impl ::std::fmt::Debug for AttributeGate { fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { match *self { - Gated(_, ref name, ref expl, _) => write!(fmt, "Gated({}, {})", name, expl), + Gated(ref stab, ref name, ref expl, _) => + write!(fmt, "Gated({:?}, {}, {})", stab, name, expl), Ungated => write!(fmt, "Ungated") } } @@ -402,6 +413,21 @@ macro_rules! cfg_fn { }} } +pub fn with_deprecated_attributes(f: F) -> T + where F: FnOnce(&[&'static (&'static str, AttributeType, AttributeGate)]) -> T +{ + static mut DEPR_ATTRS: Option> + = None; + + unsafe { + if DEPR_ATTRS.is_none() { + DEPR_ATTRS = Some(KNOWN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()); + } + + f(DEPR_ATTRS.as_ref().unwrap()) + } +} + // Attributes that have a special meaning to rustc or rustdoc pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[ // Normal attributes @@ -643,11 +669,11 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGat ("link_section", Whitelisted, Ungated), ("no_builtins", Whitelisted, Ungated), ("no_mangle", Whitelisted, Ungated), - ("no_debug", Whitelisted, Gated(Stability::Deprecated, - "no_debug", - "the `#[no_debug]` attribute \ - is an experimental feature", - cfg_fn!(no_debug))), + ("no_debug", Whitelisted, Gated( + Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"), + "no_debug", + "the `#[no_debug]` attribute is an experimental feature", + cfg_fn!(no_debug))), ("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable, "omit_gdb_pretty_printer_section", "the `#[omit_gdb_pretty_printer_section]` \ diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 6e671c9efdcf8..7ddf1a70d7738 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -34,6 +34,8 @@ #![cfg_attr(stage0, feature(question_mark))] #![feature(rustc_diagnostic_macros)] #![feature(specialization)] +#![feature(dotdot_in_tuple_patterns)] +#![feature(drop_types_in_const)] extern crate serialize; extern crate term; diff --git a/src/test/compile-fail/feature-gate-no-debug-2.rs b/src/test/compile-fail/feature-gate-no-debug-2.rs index 853aaea8ef9b3..b663c136ee525 100644 --- a/src/test/compile-fail/feature-gate-no-debug-2.rs +++ b/src/test/compile-fail/feature-gate-no-debug-2.rs @@ -11,5 +11,5 @@ #![deny(deprecated)] #![feature(no_debug)] -#[no_debug] //~ ERROR use of deprecated attribute: no_debug +#[no_debug] //~ ERROR use of deprecated attribute `no_debug` fn main() {}