Skip to content

Commit e3ed7b0

Browse files
committed
Implement #[deprecated] attribute (RFC 1270)
1 parent 45a73c8 commit e3ed7b0

20 files changed

+899
-110
lines changed

src/doc/reference.md

+2
Original file line numberDiff line numberDiff line change
@@ -2390,6 +2390,8 @@ The currently implemented features of the reference compiler are:
23902390
* - `stmt_expr_attributes` - Allows attributes on expressions and
23912391
non-item statements.
23922392

2393+
* - `deprecated` - Allows using the `#[deprecated]` attribute.
2394+
23932395
If a feature is promoted to a language feature, then all existing programs will
23942396
start to receive compilation warnings about `#![feature]` directives which enabled
23952397
the new feature (because the directive is no longer necessary). However, if a

src/librustc/middle/cstore.rs

+2
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ pub enum FoundAst<'ast> {
135135
pub trait CrateStore<'tcx> : Any {
136136
// item info
137137
fn stability(&self, def: DefId) -> Option<attr::Stability>;
138+
fn deprecation(&self, def: DefId) -> Option<attr::Deprecation>;
138139
fn closure_kind(&self, tcx: &ty::ctxt<'tcx>, def_id: DefId)
139140
-> ty::ClosureKind;
140141
fn closure_ty(&self, tcx: &ty::ctxt<'tcx>, def_id: DefId)
@@ -292,6 +293,7 @@ pub struct DummyCrateStore;
292293
impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
293294
// item info
294295
fn stability(&self, def: DefId) -> Option<attr::Stability> { unimplemented!() }
296+
fn deprecation(&self, def: DefId) -> Option<attr::Deprecation> { unimplemented!() }
295297
fn closure_kind(&self, tcx: &ty::ctxt<'tcx>, def_id: DefId)
296298
-> ty::ClosureKind { unimplemented!() }
297299
fn closure_ty(&self, tcx: &ty::ctxt<'tcx>, def_id: DefId)

src/librustc/middle/stability.rs

+125-44
Large diffs are not rendered by default.

src/librustc_lint/builtin.rs

+30-33
Original file line numberDiff line numberDiff line change
@@ -575,74 +575,71 @@ impl LateLintPass for MissingDebugImplementations {
575575
declare_lint! {
576576
DEPRECATED,
577577
Warn,
578-
"detects use of #[rustc_deprecated] items"
578+
"detects use of `#[deprecated]` or `#[rustc_deprecated]` items"
579579
}
580580

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

585-
impl Stability {
586-
fn lint(&self, cx: &LateContext, _id: DefId,
587-
span: Span, stability: &Option<&attr::Stability>) {
585+
impl Deprecated {
586+
fn lint(&self, cx: &LateContext, _id: DefId, span: Span,
587+
stability: &Option<&attr::Stability>, deprecation: &Option<attr::Deprecation>) {
588588
// Deprecated attributes apply in-crate and cross-crate.
589-
let (lint, label) = match *stability {
590-
Some(&attr::Stability { depr: Some(_), .. }) =>
591-
(DEPRECATED, "deprecated"),
592-
_ => return
593-
};
594-
595-
output(cx, span, stability, lint, label);
589+
if let Some(&attr::Stability{rustc_depr: Some(attr::RustcDeprecation{ref reason, ..}), ..})
590+
= *stability {
591+
output(cx, DEPRECATED, span, Some(&reason))
592+
} else if let Some(attr::Deprecation{ref note, ..}) = *deprecation {
593+
output(cx, DEPRECATED, span, note.as_ref().map(|x| &**x))
594+
}
596595

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

606-
cx.span_lint(lint, span, &msg[..]);
603+
cx.span_lint(lint, span, &msg);
607604
}
608605
}
609606
}
610607

611-
impl LintPass for Stability {
608+
impl LintPass for Deprecated {
612609
fn get_lints(&self) -> LintArray {
613610
lint_array!(DEPRECATED)
614611
}
615612
}
616613

617-
impl LateLintPass for Stability {
614+
impl LateLintPass for Deprecated {
618615
fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
619616
stability::check_item(cx.tcx, item, false,
620-
&mut |id, sp, stab|
621-
self.lint(cx, id, sp, &stab));
617+
&mut |id, sp, stab, depr|
618+
self.lint(cx, id, sp, &stab, &depr));
622619
}
623620

624621
fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
625622
stability::check_expr(cx.tcx, e,
626-
&mut |id, sp, stab|
627-
self.lint(cx, id, sp, &stab));
623+
&mut |id, sp, stab, depr|
624+
self.lint(cx, id, sp, &stab, &depr));
628625
}
629626

630627
fn check_path(&mut self, cx: &LateContext, path: &hir::Path, id: ast::NodeId) {
631628
stability::check_path(cx.tcx, path, id,
632-
&mut |id, sp, stab|
633-
self.lint(cx, id, sp, &stab));
629+
&mut |id, sp, stab, depr|
630+
self.lint(cx, id, sp, &stab, &depr));
634631
}
635632

636633
fn check_path_list_item(&mut self, cx: &LateContext, item: &hir::PathListItem) {
637634
stability::check_path_list_item(cx.tcx, item,
638-
&mut |id, sp, stab|
639-
self.lint(cx, id, sp, &stab));
635+
&mut |id, sp, stab, depr|
636+
self.lint(cx, id, sp, &stab, &depr));
640637
}
641638

642639
fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) {
643640
stability::check_pat(cx.tcx, pat,
644-
&mut |id, sp, stab|
645-
self.lint(cx, id, sp, &stab));
641+
&mut |id, sp, stab, depr|
642+
self.lint(cx, id, sp, &stab, &depr));
646643
}
647644
}
648645

src/librustc_lint/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
124124
UnusedAllocation,
125125
MissingCopyImplementations,
126126
UnstableFeatures,
127-
Stability,
127+
Deprecated,
128128
UnconditionalRecursion,
129129
InvalidNoMangleItems,
130130
PluginAsLibrary,

src/librustc_metadata/common.rs

+2
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,8 @@ pub const tag_impl_coerce_unsized_kind: usize = 0xa5;
237237

238238
pub const tag_items_data_item_constness: usize = 0xa6;
239239

240+
pub const tag_items_data_item_deprecation: usize = 0xa7;
241+
240242
pub const tag_rustc_version: usize = 0x10f;
241243
pub fn rustc_version() -> String {
242244
format!(

src/librustc_metadata/csearch.rs

+6
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
4242
decoder::get_stability(&*cdata, def.index)
4343
}
4444

45+
fn deprecation(&self, def: DefId) -> Option<attr::Deprecation>
46+
{
47+
let cdata = self.get_crate_data(def.krate);
48+
decoder::get_deprecation(&*cdata, def.index)
49+
}
50+
4551
fn closure_kind(&self, _tcx: &ty::ctxt<'tcx>, def_id: DefId) -> ty::ClosureKind
4652
{
4753
assert!(!def_id.is_local());

src/librustc_metadata/decoder.rs

+8
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,14 @@ pub fn get_stability(cdata: Cmd, id: DefIndex) -> Option<attr::Stability> {
526526
})
527527
}
528528

529+
pub fn get_deprecation(cdata: Cmd, id: DefIndex) -> Option<attr::Deprecation> {
530+
let item = cdata.lookup_item(id);
531+
reader::maybe_get_doc(item, tag_items_data_item_deprecation).map(|doc| {
532+
let mut decoder = reader::Decoder::new(doc);
533+
Decodable::decode(&mut decoder).unwrap()
534+
})
535+
}
536+
529537
pub fn get_repr_attrs(cdata: Cmd, id: DefIndex) -> Vec<attr::ReprAttr> {
530538
let item = cdata.lookup_item(id);
531539
match reader::maybe_get_doc(item, tag_items_data_item_repr).map(|doc| {

src/librustc_metadata/encoder.rs

+49-11
Original file line numberDiff line numberDiff line change
@@ -342,8 +342,10 @@ fn encode_enum_variant_info<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
342342
encode_attributes(rbml_w, &attrs);
343343
encode_repr_attrs(rbml_w, ecx, &attrs);
344344

345-
let stab = stability::lookup(ecx.tcx, vid);
345+
let stab = stability::lookup_stability(ecx.tcx, vid);
346+
let depr = stability::lookup_deprecation(ecx.tcx, vid);
346347
encode_stability(rbml_w, stab);
348+
encode_deprecation(rbml_w, depr);
347349

348350
encode_struct_fields(rbml_w, variant);
349351

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

453-
let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(id));
455+
let stab = stability::lookup_stability(ecx.tcx, ecx.tcx.map.local_def_id(id));
456+
let depr = stability::lookup_deprecation(ecx.tcx, ecx.tcx.map.local_def_id(id));
454457
encode_stability(rbml_w, stab);
458+
encode_deprecation(rbml_w, depr);
455459

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

541-
let stab = stability::lookup(ecx.tcx, field.did);
545+
let stab = stability::lookup_stability(ecx.tcx, field.did);
546+
let depr = stability::lookup_deprecation(ecx.tcx, field.did);
542547
encode_stability(rbml_w, stab);
548+
encode_deprecation(rbml_w, depr);
543549

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

568-
let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(ctor_id));
574+
let stab = stability::lookup_stability(ecx.tcx, ecx.tcx.map.local_def_id(ctor_id));
575+
let depr= stability::lookup_deprecation(ecx.tcx, ecx.tcx.map.local_def_id(ctor_id));
569576
encode_stability(rbml_w, stab);
577+
encode_deprecation(rbml_w, depr);
570578

571579
// indicate that this is a tuple struct ctor, because downstream users will normally want
572580
// 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>,
700708
encode_bounds_and_type_for_item(rbml_w, ecx, index,
701709
ecx.local_id(associated_const.def_id));
702710

703-
let stab = stability::lookup(ecx.tcx, associated_const.def_id);
711+
let stab = stability::lookup_stability(ecx.tcx, associated_const.def_id);
712+
let depr = stability::lookup_deprecation(ecx.tcx, associated_const.def_id);
704713
encode_stability(rbml_w, stab);
714+
encode_deprecation(rbml_w, depr);
705715

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

738-
let stab = stability::lookup(ecx.tcx, m.def_id);
748+
let stab = stability::lookup_stability(ecx.tcx, m.def_id);
749+
let depr = stability::lookup_deprecation(ecx.tcx, m.def_id);
739750
encode_stability(rbml_w, stab);
751+
encode_deprecation(rbml_w, depr);
740752

741753
let m_node_id = ecx.local_id(m.def_id);
742754
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>,
789801
encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id));
790802
encode_item_sort(rbml_w, 't');
791803

792-
let stab = stability::lookup(ecx.tcx, associated_type.def_id);
804+
let stab = stability::lookup_stability(ecx.tcx, associated_type.def_id);
805+
let depr = stability::lookup_deprecation(ecx.tcx, associated_type.def_id);
793806
encode_stability(rbml_w, stab);
807+
encode_deprecation(rbml_w, depr);
794808

795809
let elem = ast_map::PathName(associated_type.name);
796810
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>) {
891905
});
892906
}
893907

908+
fn encode_deprecation(rbml_w: &mut Encoder, depr_opt: Option<attr::Deprecation>) {
909+
depr_opt.map(|depr| {
910+
rbml_w.start_tag(tag_items_data_item_deprecation);
911+
depr.encode(rbml_w).unwrap();
912+
rbml_w.end_tag();
913+
});
914+
}
915+
894916
fn encode_xrefs<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
895917
rbml_w: &mut Encoder,
896918
xrefs: FnvHashMap<XRef<'tcx>, u32>)
@@ -931,7 +953,8 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
931953
tcx.sess.codemap().span_to_string(item.span));
932954

933955
let def_id = ecx.tcx.map.local_def_id(item.id);
934-
let stab = stability::lookup(tcx, ecx.tcx.map.local_def_id(item.id));
956+
let stab = stability::lookup_stability(tcx, ecx.tcx.map.local_def_id(item.id));
957+
let depr = stability::lookup_deprecation(tcx, ecx.tcx.map.local_def_id(item.id));
935958

936959
match item.node {
937960
hir::ItemStatic(_, m, _) => {
@@ -949,6 +972,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
949972
encode_path(rbml_w, path);
950973
encode_visibility(rbml_w, vis);
951974
encode_stability(rbml_w, stab);
975+
encode_deprecation(rbml_w, depr);
952976
encode_attributes(rbml_w, &item.attrs);
953977
rbml_w.end_tag();
954978
}
@@ -964,6 +988,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
964988
encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
965989
encode_visibility(rbml_w, vis);
966990
encode_stability(rbml_w, stab);
991+
encode_deprecation(rbml_w, depr);
967992
rbml_w.end_tag();
968993
}
969994
hir::ItemFn(ref decl, _, constness, _, ref generics, _) => {
@@ -986,6 +1011,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
9861011
encode_constness(rbml_w, constness);
9871012
encode_visibility(rbml_w, vis);
9881013
encode_stability(rbml_w, stab);
1014+
encode_deprecation(rbml_w, depr);
9891015
encode_method_argument_names(rbml_w, &**decl);
9901016
rbml_w.end_tag();
9911017
}
@@ -1015,6 +1041,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
10151041
}
10161042
encode_visibility(rbml_w, vis);
10171043
encode_stability(rbml_w, stab);
1044+
encode_deprecation(rbml_w, depr);
10181045
rbml_w.end_tag();
10191046
}
10201047
hir::ItemTy(..) => {
@@ -1027,6 +1054,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
10271054
encode_path(rbml_w, path);
10281055
encode_visibility(rbml_w, vis);
10291056
encode_stability(rbml_w, stab);
1057+
encode_deprecation(rbml_w, depr);
10301058
rbml_w.end_tag();
10311059
}
10321060
hir::ItemEnum(ref enum_definition, _) => {
@@ -1051,6 +1079,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
10511079

10521080
encode_visibility(rbml_w, vis);
10531081
encode_stability(rbml_w, stab);
1082+
encode_deprecation(rbml_w, depr);
10541083
rbml_w.end_tag();
10551084

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

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

11721203
// 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>,
12361267
encode_attributes(rbml_w, &item.attrs);
12371268
encode_visibility(rbml_w, vis);
12381269
encode_stability(rbml_w, stab);
1270+
encode_deprecation(rbml_w, depr);
12391271
for &method_def_id in tcx.trait_item_def_ids(def_id).iter() {
12401272
rbml_w.start_tag(tag_item_trait_item);
12411273
match method_def_id {
@@ -1274,8 +1306,10 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
12741306

12751307
encode_parent_item(rbml_w, def_id);
12761308

1277-
let stab = stability::lookup(tcx, item_def_id.def_id());
1309+
let stab = stability::lookup_stability(tcx, item_def_id.def_id());
1310+
let depr = stability::lookup_deprecation(tcx, item_def_id.def_id());
12781311
encode_stability(rbml_w, stab);
1312+
encode_deprecation(rbml_w, depr);
12791313

12801314
let trait_item_type =
12811315
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>,
14071441
encode_inlined_item(ecx, rbml_w, InlinedItemRef::Foreign(nitem));
14081442
}
14091443
encode_attributes(rbml_w, &*nitem.attrs);
1410-
let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
1444+
let stab = stability::lookup_stability(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
1445+
let depr = stability::lookup_deprecation(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
14111446
encode_stability(rbml_w, stab);
1447+
encode_deprecation(rbml_w, depr);
14121448
encode_symbol(ecx, rbml_w, nitem.id);
14131449
encode_method_argument_names(rbml_w, &*fndecl);
14141450
}
@@ -1420,8 +1456,10 @@ fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
14201456
}
14211457
encode_bounds_and_type_for_item(rbml_w, ecx, index, nitem.id);
14221458
encode_attributes(rbml_w, &*nitem.attrs);
1423-
let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
1459+
let stab = stability::lookup_stability(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
1460+
let depr = stability::lookup_deprecation(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
14241461
encode_stability(rbml_w, stab);
1462+
encode_deprecation(rbml_w, depr);
14251463
encode_symbol(ecx, rbml_w, nitem.id);
14261464
encode_name(rbml_w, nitem.name);
14271465
}

0 commit comments

Comments
 (0)