Add possibility of deprecating attributes
This commit is contained in:
parent
3a25b65c1f
commit
121e903f17
|
@ -314,5 +314,4 @@ pub enum LintSource {
|
|||
pub type LevelSource = (Level, LintSource);
|
||||
|
||||
pub mod builtin;
|
||||
|
||||
mod context;
|
||||
|
|
|
@ -39,11 +39,11 @@ use rustc::traits::{self, Reveal};
|
|||
use rustc::hir::map as hir_map;
|
||||
use util::nodemap::NodeSet;
|
||||
use lint::{Level, LateContext, LintContext, LintArray, Lint};
|
||||
use lint::{LintPass, LateLintPass};
|
||||
use lint::{LintPass, LateLintPass, EarlyLintPass, EarlyContext};
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::{ast, feature_gate};
|
||||
use syntax::attr;
|
||||
use syntax_pos::Span;
|
||||
|
||||
|
@ -741,6 +741,40 @@ impl LateLintPass for Deprecated {
|
|||
}
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
DEPRECATED_ATTR,
|
||||
Warn,
|
||||
"detects use of deprecated attributes"
|
||||
}
|
||||
|
||||
/// Checks for use of attributes which have been deprecated.
|
||||
#[derive(Clone)]
|
||||
pub struct DeprecatedAttr;
|
||||
|
||||
impl LintPass for DeprecatedAttr {
|
||||
fn get_lints(&self) -> LintArray {
|
||||
lint_array!(DEPRECATED_ATTR)
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub UNCONDITIONAL_RECURSION,
|
||||
Warn,
|
||||
|
|
|
@ -103,6 +103,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
|||
|
||||
add_early_builtin!(sess,
|
||||
UnusedParens,
|
||||
DeprecatedAttr,
|
||||
);
|
||||
|
||||
add_builtin!(sess,
|
||||
|
|
|
@ -371,17 +371,23 @@ pub enum AttributeType {
|
|||
pub enum AttributeGate {
|
||||
/// Is gated by a given feature gate, reason
|
||||
/// and function to check if enabled
|
||||
Gated(&'static str, &'static str, fn(&Features) -> bool),
|
||||
Gated(Stability, &'static str, &'static str, fn(&Features) -> bool),
|
||||
|
||||
/// Ungated attribute, can be used on all release channels
|
||||
Ungated,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Stability {
|
||||
Unstable,
|
||||
Deprecated,
|
||||
}
|
||||
|
||||
// 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 name, ref expl, _) => write!(fmt, "Gated({}, {})", name, expl),
|
||||
Ungated => write!(fmt, "Ungated")
|
||||
}
|
||||
}
|
||||
|
@ -432,7 +438,8 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGat
|
|||
("macro_escape", Normal, Ungated),
|
||||
|
||||
// RFC #1445.
|
||||
("structural_match", Whitelisted, Gated("structural_match",
|
||||
("structural_match", Whitelisted, Gated(Stability::Unstable,
|
||||
"structural_match",
|
||||
"the semantics of constant patterns is \
|
||||
not yet settled",
|
||||
cfg_fn!(structural_match))),
|
||||
|
@ -440,150 +447,181 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGat
|
|||
// Not used any more, but we can't feature gate it
|
||||
("no_stack_check", Normal, Ungated),
|
||||
|
||||
("plugin", CrateLevel, Gated("plugin",
|
||||
("plugin", CrateLevel, Gated(Stability::Unstable,
|
||||
"plugin",
|
||||
"compiler plugins are experimental \
|
||||
and possibly buggy",
|
||||
cfg_fn!(plugin))),
|
||||
|
||||
("no_std", CrateLevel, Ungated),
|
||||
("no_core", CrateLevel, Gated("no_core",
|
||||
("no_core", CrateLevel, Gated(Stability::Unstable,
|
||||
"no_core",
|
||||
"no_core is experimental",
|
||||
cfg_fn!(no_core))),
|
||||
("lang", Normal, Gated("lang_items",
|
||||
("lang", Normal, Gated(Stability::Unstable,
|
||||
"lang_items",
|
||||
"language items are subject to change",
|
||||
cfg_fn!(lang_items))),
|
||||
("linkage", Whitelisted, Gated("linkage",
|
||||
("linkage", Whitelisted, Gated(Stability::Unstable,
|
||||
"linkage",
|
||||
"the `linkage` attribute is experimental \
|
||||
and not portable across platforms",
|
||||
cfg_fn!(linkage))),
|
||||
("thread_local", Whitelisted, Gated("thread_local",
|
||||
("thread_local", Whitelisted, Gated(Stability::Unstable,
|
||||
"thread_local",
|
||||
"`#[thread_local]` is an experimental feature, and does \
|
||||
not currently handle destructors. There is no \
|
||||
corresponding `#[task_local]` mapping to the task \
|
||||
model",
|
||||
cfg_fn!(thread_local))),
|
||||
|
||||
("rustc_on_unimplemented", Normal, Gated("on_unimplemented",
|
||||
("rustc_on_unimplemented", Normal, Gated(Stability::Unstable,
|
||||
"on_unimplemented",
|
||||
"the `#[rustc_on_unimplemented]` attribute \
|
||||
is an experimental feature",
|
||||
cfg_fn!(on_unimplemented))),
|
||||
("allocator", Whitelisted, Gated("allocator",
|
||||
("allocator", Whitelisted, Gated(Stability::Unstable,
|
||||
"allocator",
|
||||
"the `#[allocator]` attribute is an experimental feature",
|
||||
cfg_fn!(allocator))),
|
||||
("needs_allocator", Normal, Gated("needs_allocator",
|
||||
("needs_allocator", Normal, Gated(Stability::Unstable,
|
||||
"needs_allocator",
|
||||
"the `#[needs_allocator]` \
|
||||
attribute is an experimental \
|
||||
feature",
|
||||
cfg_fn!(needs_allocator))),
|
||||
("panic_runtime", Whitelisted, Gated("panic_runtime",
|
||||
("panic_runtime", Whitelisted, Gated(Stability::Unstable,
|
||||
"panic_runtime",
|
||||
"the `#[panic_runtime]` attribute is \
|
||||
an experimental feature",
|
||||
cfg_fn!(panic_runtime))),
|
||||
("needs_panic_runtime", Whitelisted, Gated("needs_panic_runtime",
|
||||
("needs_panic_runtime", Whitelisted, Gated(Stability::Unstable,
|
||||
"needs_panic_runtime",
|
||||
"the `#[needs_panic_runtime]` \
|
||||
attribute is an experimental \
|
||||
feature",
|
||||
cfg_fn!(needs_panic_runtime))),
|
||||
("rustc_variance", Normal, Gated("rustc_attrs",
|
||||
("rustc_variance", Normal, Gated(Stability::Unstable,
|
||||
"rustc_attrs",
|
||||
"the `#[rustc_variance]` attribute \
|
||||
is just used for rustc unit tests \
|
||||
and will never be stable",
|
||||
cfg_fn!(rustc_attrs))),
|
||||
("rustc_error", Whitelisted, Gated("rustc_attrs",
|
||||
("rustc_error", Whitelisted, Gated(Stability::Unstable,
|
||||
"rustc_attrs",
|
||||
"the `#[rustc_error]` attribute \
|
||||
is just used for rustc unit tests \
|
||||
and will never be stable",
|
||||
cfg_fn!(rustc_attrs))),
|
||||
("rustc_if_this_changed", Whitelisted, Gated("rustc_attrs",
|
||||
("rustc_if_this_changed", Whitelisted, Gated(Stability::Unstable,
|
||||
"rustc_attrs",
|
||||
"the `#[rustc_if_this_changed]` attribute \
|
||||
is just used for rustc unit tests \
|
||||
and will never be stable",
|
||||
cfg_fn!(rustc_attrs))),
|
||||
("rustc_then_this_would_need", Whitelisted, Gated("rustc_attrs",
|
||||
("rustc_then_this_would_need", Whitelisted, Gated(Stability::Unstable,
|
||||
"rustc_attrs",
|
||||
"the `#[rustc_if_this_changed]` attribute \
|
||||
is just used for rustc unit tests \
|
||||
and will never be stable",
|
||||
cfg_fn!(rustc_attrs))),
|
||||
("rustc_dirty", Whitelisted, Gated("rustc_attrs",
|
||||
("rustc_dirty", Whitelisted, Gated(Stability::Unstable,
|
||||
"rustc_attrs",
|
||||
"the `#[rustc_dirty]` attribute \
|
||||
is just used for rustc unit tests \
|
||||
and will never be stable",
|
||||
cfg_fn!(rustc_attrs))),
|
||||
("rustc_clean", Whitelisted, Gated("rustc_attrs",
|
||||
("rustc_clean", Whitelisted, Gated(Stability::Unstable,
|
||||
"rustc_attrs",
|
||||
"the `#[rustc_clean]` attribute \
|
||||
is just used for rustc unit tests \
|
||||
and will never be stable",
|
||||
cfg_fn!(rustc_attrs))),
|
||||
("rustc_metadata_dirty", Whitelisted, Gated("rustc_attrs",
|
||||
("rustc_metadata_dirty", Whitelisted, Gated(Stability::Unstable,
|
||||
"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",
|
||||
("rustc_metadata_clean", Whitelisted, Gated(Stability::Unstable,
|
||||
"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",
|
||||
("rustc_partition_reused", Whitelisted, Gated(Stability::Unstable,
|
||||
"rustc_attrs",
|
||||
"this attribute \
|
||||
is just used for rustc unit tests \
|
||||
and will never be stable",
|
||||
cfg_fn!(rustc_attrs))),
|
||||
("rustc_partition_translated", Whitelisted, Gated("rustc_attrs",
|
||||
("rustc_partition_translated", Whitelisted, Gated(Stability::Unstable,
|
||||
"rustc_attrs",
|
||||
"this attribute \
|
||||
is just used for rustc unit tests \
|
||||
and will never be stable",
|
||||
cfg_fn!(rustc_attrs))),
|
||||
("rustc_symbol_name", Whitelisted, Gated("rustc_attrs",
|
||||
("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable,
|
||||
"rustc_attrs",
|
||||
"internal rustc attributes will never be stable",
|
||||
cfg_fn!(rustc_attrs))),
|
||||
("rustc_item_path", Whitelisted, Gated("rustc_attrs",
|
||||
("rustc_item_path", Whitelisted, Gated(Stability::Unstable,
|
||||
"rustc_attrs",
|
||||
"internal rustc attributes will never be stable",
|
||||
cfg_fn!(rustc_attrs))),
|
||||
("rustc_move_fragments", Normal, Gated("rustc_attrs",
|
||||
("rustc_move_fragments", Normal, Gated(Stability::Unstable,
|
||||
"rustc_attrs",
|
||||
"the `#[rustc_move_fragments]` attribute \
|
||||
is just used for rustc unit tests \
|
||||
and will never be stable",
|
||||
cfg_fn!(rustc_attrs))),
|
||||
("rustc_mir", Whitelisted, Gated("rustc_attrs",
|
||||
("rustc_mir", Whitelisted, Gated(Stability::Unstable,
|
||||
"rustc_attrs",
|
||||
"the `#[rustc_mir]` attribute \
|
||||
is just used for rustc unit tests \
|
||||
and will never be stable",
|
||||
cfg_fn!(rustc_attrs))),
|
||||
("rustc_inherit_overflow_checks", Whitelisted, Gated("rustc_attrs",
|
||||
("rustc_inherit_overflow_checks", Whitelisted, Gated(Stability::Unstable,
|
||||
"rustc_attrs",
|
||||
"the `#[rustc_inherit_overflow_checks]` \
|
||||
attribute is just used to control \
|
||||
overflow checking behavior of several \
|
||||
libcore functions that are inlined \
|
||||
across crates and will never be stable",
|
||||
cfg_fn!(rustc_attrs))),
|
||||
("compiler_builtins", Whitelisted, Gated("compiler_builtins",
|
||||
("compiler_builtins", Whitelisted, Gated(Stability::Unstable,
|
||||
"compiler_builtins",
|
||||
"the `#[compiler_builtins]` attribute is used to \
|
||||
identify the `compiler_builtins` crate which \
|
||||
contains compiler-rt intrinsics and will never be \
|
||||
stable",
|
||||
cfg_fn!(compiler_builtins))),
|
||||
|
||||
("allow_internal_unstable", Normal, Gated("allow_internal_unstable",
|
||||
("allow_internal_unstable", Normal, Gated(Stability::Unstable,
|
||||
"allow_internal_unstable",
|
||||
EXPLAIN_ALLOW_INTERNAL_UNSTABLE,
|
||||
cfg_fn!(allow_internal_unstable))),
|
||||
|
||||
("fundamental", Whitelisted, Gated("fundamental",
|
||||
("fundamental", Whitelisted, Gated(Stability::Unstable,
|
||||
"fundamental",
|
||||
"the `#[fundamental]` attribute \
|
||||
is an experimental feature",
|
||||
cfg_fn!(fundamental))),
|
||||
|
||||
("linked_from", Normal, Gated("linked_from",
|
||||
("linked_from", Normal, Gated(Stability::Unstable,
|
||||
"linked_from",
|
||||
"the `#[linked_from]` attribute \
|
||||
is an experimental feature",
|
||||
cfg_fn!(linked_from))),
|
||||
|
||||
("proc_macro_derive", Normal, Gated("proc_macro",
|
||||
("proc_macro_derive", Normal, Gated(Stability::Unstable,
|
||||
"proc_macro",
|
||||
"the `#[proc_macro_derive]` attribute \
|
||||
is an experimental feature",
|
||||
cfg_fn!(proc_macro))),
|
||||
|
||||
("rustc_copy_clone_marker", Whitelisted, Gated("rustc_attrs",
|
||||
("rustc_copy_clone_marker", Whitelisted, Gated(Stability::Unstable,
|
||||
"rustc_attrs",
|
||||
"internal implementation detail",
|
||||
cfg_fn!(rustc_attrs))),
|
||||
|
||||
|
@ -593,7 +631,8 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGat
|
|||
// FIXME: #14406 these are processed in trans, which happens after the
|
||||
// lint pass
|
||||
("cold", Whitelisted, Ungated),
|
||||
("naked", Whitelisted, Gated("naked_functions",
|
||||
("naked", Whitelisted, Gated(Stability::Unstable,
|
||||
"naked_functions",
|
||||
"the `#[naked]` attribute \
|
||||
is an experimental feature",
|
||||
cfg_fn!(naked_functions))),
|
||||
|
@ -604,31 +643,38 @@ 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("no_debug",
|
||||
("no_debug", Whitelisted, Gated(Stability::Unstable,
|
||||
"no_debug",
|
||||
"the `#[no_debug]` attribute \
|
||||
is an experimental feature",
|
||||
cfg_fn!(no_debug))),
|
||||
("omit_gdb_pretty_printer_section", Whitelisted, Gated("omit_gdb_pretty_printer_section",
|
||||
("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable,
|
||||
"omit_gdb_pretty_printer_section",
|
||||
"the `#[omit_gdb_pretty_printer_section]` \
|
||||
attribute is just used for the Rust test \
|
||||
suite",
|
||||
cfg_fn!(omit_gdb_pretty_printer_section))),
|
||||
("unsafe_destructor_blind_to_params",
|
||||
Normal,
|
||||
Gated("dropck_parametricity",
|
||||
Gated(Stability::Unstable,
|
||||
"dropck_parametricity",
|
||||
"unsafe_destructor_blind_to_params has unstable semantics \
|
||||
and may be removed in the future",
|
||||
cfg_fn!(dropck_parametricity))),
|
||||
("may_dangle",
|
||||
Normal,
|
||||
Gated("dropck_eyepatch",
|
||||
Gated(Stability::Unstable,
|
||||
"dropck_eyepatch",
|
||||
"may_dangle has unstable semantics and may be removed in the future",
|
||||
cfg_fn!(dropck_eyepatch))),
|
||||
("unwind", Whitelisted, Gated("unwind_attributes", "#[unwind] is experimental",
|
||||
("unwind", Whitelisted, Gated(Stability::Unstable,
|
||||
"unwind_attributes",
|
||||
"#[unwind] is experimental",
|
||||
cfg_fn!(unwind_attributes))),
|
||||
|
||||
// used in resolve
|
||||
("prelude_import", Whitelisted, Gated("prelude_import",
|
||||
("prelude_import", Whitelisted, Gated(Stability::Unstable,
|
||||
"prelude_import",
|
||||
"`#[prelude_import]` is for use by rustc only",
|
||||
cfg_fn!(prelude_import))),
|
||||
|
||||
|
@ -640,10 +686,12 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGat
|
|||
("unstable", Whitelisted, Ungated),
|
||||
("deprecated", Normal, Ungated),
|
||||
|
||||
("rustc_paren_sugar", Normal, Gated("unboxed_closures",
|
||||
("rustc_paren_sugar", Normal, Gated(Stability::Unstable,
|
||||
"unboxed_closures",
|
||||
"unboxed_closures are still evolving",
|
||||
cfg_fn!(unboxed_closures))),
|
||||
("rustc_reflect_like", Whitelisted, Gated("reflect",
|
||||
("rustc_reflect_like", Whitelisted, Gated(Stability::Unstable,
|
||||
"reflect",
|
||||
"defining reflective traits is still evolving",
|
||||
cfg_fn!(reflect))),
|
||||
|
||||
|
@ -726,7 +774,7 @@ impl<'a> Context<'a> {
|
|||
let name = &*attr.name();
|
||||
for &(n, ty, ref gateage) in KNOWN_ATTRIBUTES {
|
||||
if n == name {
|
||||
if let &Gated(ref name, ref desc, ref has_feature) = gateage {
|
||||
if let &Gated(_, ref name, ref desc, ref has_feature) = gateage {
|
||||
gate_feature_fn!(self, has_feature, attr.span, name, desc);
|
||||
}
|
||||
debug!("check_attribute: {:?} is known, {:?}, {:?}", name, ty, gateage);
|
||||
|
|
Loading…
Reference in New Issue