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

Implement #[deprecated] attribute (RFC 1270) #30206

Merged
merged 3 commits into from
Dec 16, 2015
Merged
Changes from 1 commit
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
Next Next commit
Implement #[deprecated] attribute (RFC 1270)
  • Loading branch information
petrochenkov committed Dec 12, 2015
commit e3ed7b0501a24f4def3aff775c6fbf9481e3c77e
2 changes: 2 additions & 0 deletions src/doc/reference.md
Original file line number Diff line number Diff line change
@@ -2390,6 +2390,8 @@ The currently implemented features of the reference compiler are:
* - `stmt_expr_attributes` - Allows attributes on expressions and
non-item statements.

* - `deprecated` - Allows using the `#[deprecated]` attribute.

If a feature is promoted to a language feature, then all existing programs will
start to receive compilation warnings about `#![feature]` directives which enabled
the new feature (because the directive is no longer necessary). However, if a
2 changes: 2 additions & 0 deletions src/librustc/middle/cstore.rs
Original file line number Diff line number Diff line change
@@ -135,6 +135,7 @@ pub enum FoundAst<'ast> {
pub trait CrateStore<'tcx> : Any {
// item info
fn stability(&self, def: DefId) -> Option<attr::Stability>;
fn deprecation(&self, def: DefId) -> Option<attr::Deprecation>;
fn closure_kind(&self, tcx: &ty::ctxt<'tcx>, def_id: DefId)
-> ty::ClosureKind;
fn closure_ty(&self, tcx: &ty::ctxt<'tcx>, def_id: DefId)
@@ -292,6 +293,7 @@ pub struct DummyCrateStore;
impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
// item info
fn stability(&self, def: DefId) -> Option<attr::Stability> { unimplemented!() }
fn deprecation(&self, def: DefId) -> Option<attr::Deprecation> { unimplemented!() }
fn closure_kind(&self, tcx: &ty::ctxt<'tcx>, def_id: DefId)
-> ty::ClosureKind { unimplemented!() }
fn closure_ty(&self, tcx: &ty::ctxt<'tcx>, def_id: DefId)
169 changes: 125 additions & 44 deletions src/librustc/middle/stability.rs

Large diffs are not rendered by default.

63 changes: 30 additions & 33 deletions src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
@@ -575,74 +575,71 @@ impl LateLintPass for MissingDebugImplementations {
declare_lint! {
DEPRECATED,
Warn,
"detects use of #[rustc_deprecated] items"
"detects use of `#[deprecated]` or `#[rustc_deprecated]` items"
Copy link
Contributor

Choose a reason for hiding this comment

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

The existence of #[rustc_deprecated] is an implementation detail. Can we change this string to 'detects use of deprecated items'?

}

/// Checks for use of items with `#[rustc_deprecated]` attributes
/// Checks for use of items with `#[deprecated]` or `#[rustc_deprecated]` attributes
#[derive(Copy, Clone)]
pub struct Stability;
pub struct Deprecated;

impl Stability {
fn lint(&self, cx: &LateContext, _id: DefId,
span: Span, stability: &Option<&attr::Stability>) {
impl Deprecated {
fn lint(&self, cx: &LateContext, _id: DefId, span: Span,
stability: &Option<&attr::Stability>, deprecation: &Option<attr::Deprecation>) {
// Deprecated attributes apply in-crate and cross-crate.
let (lint, label) = match *stability {
Some(&attr::Stability { depr: Some(_), .. }) =>
(DEPRECATED, "deprecated"),
_ => return
};

output(cx, span, stability, lint, label);
if let Some(&attr::Stability{rustc_depr: Some(attr::RustcDeprecation{ref reason, ..}), ..})
= *stability {
output(cx, DEPRECATED, span, Some(&reason))
} else if let Some(attr::Deprecation{ref note, ..}) = *deprecation {
output(cx, DEPRECATED, span, note.as_ref().map(|x| &**x))
}

fn output(cx: &LateContext, span: Span, stability: &Option<&attr::Stability>,
lint: &'static Lint, label: &'static str) {
let msg = match *stability {
Some(&attr::Stability {depr: Some(attr::Deprecation {ref reason, ..}), ..}) => {
format!("use of {} item: {}", label, reason)
}
_ => format!("use of {} item", label)
fn output(cx: &LateContext, lint: &'static Lint, span: Span, note: Option<&str>) {
let msg = if let Some(note) = note {
format!("use of deprecated item: {}", note)
} else {
format!("use of deprecated item")
};

cx.span_lint(lint, span, &msg[..]);
cx.span_lint(lint, span, &msg);
}
}
}

impl LintPass for Stability {
impl LintPass for Deprecated {
fn get_lints(&self) -> LintArray {
lint_array!(DEPRECATED)
}
}

impl LateLintPass for Stability {
impl LateLintPass for Deprecated {
fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
stability::check_item(cx.tcx, item, false,
&mut |id, sp, stab|
self.lint(cx, id, sp, &stab));
&mut |id, sp, stab, depr|
self.lint(cx, id, sp, &stab, &depr));
}

fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
stability::check_expr(cx.tcx, e,
&mut |id, sp, stab|
self.lint(cx, id, sp, &stab));
&mut |id, sp, stab, depr|
self.lint(cx, id, sp, &stab, &depr));
}

fn check_path(&mut self, cx: &LateContext, path: &hir::Path, id: ast::NodeId) {
stability::check_path(cx.tcx, path, id,
&mut |id, sp, stab|
self.lint(cx, id, sp, &stab));
&mut |id, sp, stab, depr|
self.lint(cx, id, sp, &stab, &depr));
}

fn check_path_list_item(&mut self, cx: &LateContext, item: &hir::PathListItem) {
stability::check_path_list_item(cx.tcx, item,
&mut |id, sp, stab|
self.lint(cx, id, sp, &stab));
&mut |id, sp, stab, depr|
self.lint(cx, id, sp, &stab, &depr));
}

fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) {
stability::check_pat(cx.tcx, pat,
&mut |id, sp, stab|
self.lint(cx, id, sp, &stab));
&mut |id, sp, stab, depr|
self.lint(cx, id, sp, &stab, &depr));
}
}

2 changes: 1 addition & 1 deletion src/librustc_lint/lib.rs
Original file line number Diff line number Diff line change
@@ -124,7 +124,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
UnusedAllocation,
MissingCopyImplementations,
UnstableFeatures,
Stability,
Deprecated,
UnconditionalRecursion,
InvalidNoMangleItems,
PluginAsLibrary,
2 changes: 2 additions & 0 deletions src/librustc_metadata/common.rs
Original file line number Diff line number Diff line change
@@ -237,6 +237,8 @@ pub const tag_impl_coerce_unsized_kind: usize = 0xa5;

pub const tag_items_data_item_constness: usize = 0xa6;

pub const tag_items_data_item_deprecation: usize = 0xa7;

pub const tag_rustc_version: usize = 0x10f;
pub fn rustc_version() -> String {
format!(
6 changes: 6 additions & 0 deletions src/librustc_metadata/csearch.rs
Original file line number Diff line number Diff line change
@@ -42,6 +42,12 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
decoder::get_stability(&*cdata, def.index)
}

fn deprecation(&self, def: DefId) -> Option<attr::Deprecation>
{
let cdata = self.get_crate_data(def.krate);
decoder::get_deprecation(&*cdata, def.index)
}

fn closure_kind(&self, _tcx: &ty::ctxt<'tcx>, def_id: DefId) -> ty::ClosureKind
{
assert!(!def_id.is_local());
8 changes: 8 additions & 0 deletions src/librustc_metadata/decoder.rs
Original file line number Diff line number Diff line change
@@ -526,6 +526,14 @@ pub fn get_stability(cdata: Cmd, id: DefIndex) -> Option<attr::Stability> {
})
}

pub fn get_deprecation(cdata: Cmd, id: DefIndex) -> Option<attr::Deprecation> {
let item = cdata.lookup_item(id);
reader::maybe_get_doc(item, tag_items_data_item_deprecation).map(|doc| {
let mut decoder = reader::Decoder::new(doc);
Decodable::decode(&mut decoder).unwrap()
})
}

pub fn get_repr_attrs(cdata: Cmd, id: DefIndex) -> Vec<attr::ReprAttr> {
let item = cdata.lookup_item(id);
match reader::maybe_get_doc(item, tag_items_data_item_repr).map(|doc| {
60 changes: 49 additions & 11 deletions src/librustc_metadata/encoder.rs
Original file line number Diff line number Diff line change
@@ -342,8 +342,10 @@ fn encode_enum_variant_info<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
encode_attributes(rbml_w, &attrs);
encode_repr_attrs(rbml_w, ecx, &attrs);

let stab = stability::lookup(ecx.tcx, vid);
let stab = stability::lookup_stability(ecx.tcx, vid);
let depr = stability::lookup_deprecation(ecx.tcx, vid);
encode_stability(rbml_w, stab);
encode_deprecation(rbml_w, depr);

encode_struct_fields(rbml_w, variant);

@@ -450,8 +452,10 @@ fn encode_info_for_mod(ecx: &EncodeContext,
encode_path(rbml_w, path.clone());
encode_visibility(rbml_w, vis);

let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(id));
let stab = stability::lookup_stability(ecx.tcx, ecx.tcx.map.local_def_id(id));
let depr = stability::lookup_deprecation(ecx.tcx, ecx.tcx.map.local_def_id(id));
encode_stability(rbml_w, stab);
encode_deprecation(rbml_w, depr);

// Encode the reexports of this module, if this module is public.
if vis == hir::Public {
@@ -538,8 +542,10 @@ fn encode_field<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
encode_bounds_and_type_for_item(rbml_w, ecx, index, id);
encode_def_id_and_key(ecx, rbml_w, field.did);

let stab = stability::lookup(ecx.tcx, field.did);
let stab = stability::lookup_stability(ecx.tcx, field.did);
let depr = stability::lookup_deprecation(ecx.tcx, field.did);
encode_stability(rbml_w, stab);
encode_deprecation(rbml_w, depr);

rbml_w.end_tag();
}
@@ -565,8 +571,10 @@ fn encode_info_for_struct_ctor<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
encode_symbol(ecx, rbml_w, ctor_id);
}

let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(ctor_id));
let stab = stability::lookup_stability(ecx.tcx, ecx.tcx.map.local_def_id(ctor_id));
let depr= stability::lookup_deprecation(ecx.tcx, ecx.tcx.map.local_def_id(ctor_id));
encode_stability(rbml_w, stab);
encode_deprecation(rbml_w, depr);

// indicate that this is a tuple struct ctor, because downstream users will normally want
// the tuple struct definition, but without this there is no way for them to tell that
@@ -700,8 +708,10 @@ fn encode_info_for_associated_const<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
encode_bounds_and_type_for_item(rbml_w, ecx, index,
ecx.local_id(associated_const.def_id));

let stab = stability::lookup(ecx.tcx, associated_const.def_id);
let stab = stability::lookup_stability(ecx.tcx, associated_const.def_id);
let depr = stability::lookup_deprecation(ecx.tcx, associated_const.def_id);
encode_stability(rbml_w, stab);
encode_deprecation(rbml_w, depr);

let elem = ast_map::PathName(associated_const.name);
encode_path(rbml_w, impl_path.chain(Some(elem)));
@@ -735,8 +745,10 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id));
encode_item_sort(rbml_w, 'r');

let stab = stability::lookup(ecx.tcx, m.def_id);
let stab = stability::lookup_stability(ecx.tcx, m.def_id);
let depr = stability::lookup_deprecation(ecx.tcx, m.def_id);
encode_stability(rbml_w, stab);
encode_deprecation(rbml_w, depr);

let m_node_id = ecx.local_id(m.def_id);
encode_bounds_and_type_for_item(rbml_w, ecx, index, m_node_id);
@@ -789,8 +801,10 @@ fn encode_info_for_associated_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id));
encode_item_sort(rbml_w, 't');

let stab = stability::lookup(ecx.tcx, associated_type.def_id);
let stab = stability::lookup_stability(ecx.tcx, associated_type.def_id);
let depr = stability::lookup_deprecation(ecx.tcx, associated_type.def_id);
encode_stability(rbml_w, stab);
encode_deprecation(rbml_w, depr);

let elem = ast_map::PathName(associated_type.name);
encode_path(rbml_w, impl_path.chain(Some(elem)));
@@ -891,6 +905,14 @@ fn encode_stability(rbml_w: &mut Encoder, stab_opt: Option<&attr::Stability>) {
});
}

fn encode_deprecation(rbml_w: &mut Encoder, depr_opt: Option<attr::Deprecation>) {
depr_opt.map(|depr| {
rbml_w.start_tag(tag_items_data_item_deprecation);
depr.encode(rbml_w).unwrap();
rbml_w.end_tag();
});
}

fn encode_xrefs<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
rbml_w: &mut Encoder,
xrefs: FnvHashMap<XRef<'tcx>, u32>)
@@ -931,7 +953,8 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
tcx.sess.codemap().span_to_string(item.span));

let def_id = ecx.tcx.map.local_def_id(item.id);
let stab = stability::lookup(tcx, ecx.tcx.map.local_def_id(item.id));
let stab = stability::lookup_stability(tcx, ecx.tcx.map.local_def_id(item.id));
let depr = stability::lookup_deprecation(tcx, ecx.tcx.map.local_def_id(item.id));

match item.node {
hir::ItemStatic(_, m, _) => {
@@ -949,6 +972,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
encode_path(rbml_w, path);
encode_visibility(rbml_w, vis);
encode_stability(rbml_w, stab);
encode_deprecation(rbml_w, depr);
encode_attributes(rbml_w, &item.attrs);
rbml_w.end_tag();
}
@@ -964,6 +988,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
encode_visibility(rbml_w, vis);
encode_stability(rbml_w, stab);
encode_deprecation(rbml_w, depr);
rbml_w.end_tag();
}
hir::ItemFn(ref decl, _, constness, _, ref generics, _) => {
@@ -986,6 +1011,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
encode_constness(rbml_w, constness);
encode_visibility(rbml_w, vis);
encode_stability(rbml_w, stab);
encode_deprecation(rbml_w, depr);
encode_method_argument_names(rbml_w, &**decl);
rbml_w.end_tag();
}
@@ -1015,6 +1041,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
}
encode_visibility(rbml_w, vis);
encode_stability(rbml_w, stab);
encode_deprecation(rbml_w, depr);
rbml_w.end_tag();
}
hir::ItemTy(..) => {
@@ -1027,6 +1054,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
encode_path(rbml_w, path);
encode_visibility(rbml_w, vis);
encode_stability(rbml_w, stab);
encode_deprecation(rbml_w, depr);
rbml_w.end_tag();
}
hir::ItemEnum(ref enum_definition, _) => {
@@ -1051,6 +1079,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,

encode_visibility(rbml_w, vis);
encode_stability(rbml_w, stab);
encode_deprecation(rbml_w, depr);
rbml_w.end_tag();

encode_enum_variant_info(ecx,
@@ -1077,6 +1106,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
encode_attributes(rbml_w, &item.attrs);
encode_path(rbml_w, path.clone());
encode_stability(rbml_w, stab);
encode_deprecation(rbml_w, depr);
encode_visibility(rbml_w, vis);
encode_repr_attrs(rbml_w, ecx, &item.attrs);

@@ -1167,6 +1197,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
}
encode_path(rbml_w, path.clone());
encode_stability(rbml_w, stab);
encode_deprecation(rbml_w, depr);
rbml_w.end_tag();

// Iterate down the trait items, emitting them. We rely on the
@@ -1236,6 +1267,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
encode_attributes(rbml_w, &item.attrs);
encode_visibility(rbml_w, vis);
encode_stability(rbml_w, stab);
encode_deprecation(rbml_w, depr);
for &method_def_id in tcx.trait_item_def_ids(def_id).iter() {
rbml_w.start_tag(tag_item_trait_item);
match method_def_id {
@@ -1274,8 +1306,10 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,

encode_parent_item(rbml_w, def_id);

let stab = stability::lookup(tcx, item_def_id.def_id());
let stab = stability::lookup_stability(tcx, item_def_id.def_id());
let depr = stability::lookup_deprecation(tcx, item_def_id.def_id());
encode_stability(rbml_w, stab);
encode_deprecation(rbml_w, depr);

let trait_item_type =
tcx.impl_or_trait_item(item_def_id.def_id());
@@ -1407,8 +1441,10 @@ fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
encode_inlined_item(ecx, rbml_w, InlinedItemRef::Foreign(nitem));
}
encode_attributes(rbml_w, &*nitem.attrs);
let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
let stab = stability::lookup_stability(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
let depr = stability::lookup_deprecation(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
encode_stability(rbml_w, stab);
encode_deprecation(rbml_w, depr);
encode_symbol(ecx, rbml_w, nitem.id);
encode_method_argument_names(rbml_w, &*fndecl);
}
@@ -1420,8 +1456,10 @@ fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
}
encode_bounds_and_type_for_item(rbml_w, ecx, index, nitem.id);
encode_attributes(rbml_w, &*nitem.attrs);
let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
let stab = stability::lookup_stability(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
let depr = stability::lookup_deprecation(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
encode_stability(rbml_w, stab);
encode_deprecation(rbml_w, depr);
encode_symbol(ecx, rbml_w, nitem.id);
encode_name(rbml_w, nitem.name);
}
Loading