Skip to content

Commit ac2c5ff

Browse files
committedDec 16, 2015
Auto merge of #30206 - petrochenkov:newdepr, r=brson
Closes #29935 The attributes `deprecated` and `rustc_deprecated` are completely independent in this implementation and it leads to some noticeable code duplication. Representing `deprecated` as ``` Stability { level: Stable { since: "" }, feature: "", depr: Some(Deprecation), } ``` or, contrariwise, splitting rustc_deprecation from stability makes most of the duplication go away. I can do this refactoring, but before doing it I must be sure, that further divergence of `deprecated` and `rustc_deprecated` is certainly not a goal. cc @llogiq
2 parents 9ace0a4 + 67a9784 commit ac2c5ff

26 files changed

+1003
-137
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

+92-66
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use syntax::codemap::{Span, DUMMY_SP};
2525
use syntax::ast;
2626
use syntax::ast::{NodeId, Attribute};
2727
use syntax::feature_gate::{GateIssue, emit_feature_err};
28-
use syntax::attr::{self, Stability, AttrMetaMethods};
28+
use syntax::attr::{self, Stability, Deprecation, AttrMetaMethods};
2929
use util::nodemap::{DefIdMap, FnvHashSet, FnvHashMap};
3030

3131
use rustc_front::hir;
@@ -61,7 +61,8 @@ enum AnnotationKind {
6161
pub struct Index<'tcx> {
6262
/// This is mostly a cache, except the stabilities of local items
6363
/// are filled by the annotator.
64-
map: DefIdMap<Option<&'tcx Stability>>,
64+
stab_map: DefIdMap<Option<&'tcx Stability>>,
65+
depr_map: DefIdMap<Option<Deprecation>>,
6566

6667
/// Maps for each crate whether it is part of the staged API.
6768
staged_api: FnvHashMap<ast::CrateNum, bool>
@@ -71,7 +72,8 @@ pub struct Index<'tcx> {
7172
struct Annotator<'a, 'tcx: 'a> {
7273
tcx: &'a ty::ctxt<'tcx>,
7374
index: &'a mut Index<'tcx>,
74-
parent: Option<&'tcx Stability>,
75+
parent_stab: Option<&'tcx Stability>,
76+
parent_depr: Option<Deprecation>,
7577
access_levels: &'a AccessLevels,
7678
in_trait_impl: bool,
7779
in_enum: bool,
@@ -86,31 +88,35 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
8688
{
8789
if self.index.staged_api[&LOCAL_CRATE] && self.tcx.sess.features.borrow().staged_api {
8890
debug!("annotate(id = {:?}, attrs = {:?})", id, attrs);
91+
if let Some(..) = attr::find_deprecation(self.tcx.sess.diagnostic(), attrs, item_sp) {
92+
self.tcx.sess.span_err(item_sp, "`#[deprecated]` cannot be used in staged api, \
93+
use `#[rustc_deprecated]` instead");
94+
}
8995
if let Some(mut stab) = attr::find_stability(self.tcx.sess.diagnostic(),
9096
attrs, item_sp) {
9197
// Error if prohibited, or can't inherit anything from a container
9298
if kind == AnnotationKind::Prohibited ||
9399
(kind == AnnotationKind::Container &&
94100
stab.level.is_stable() &&
95-
stab.depr.is_none()) {
101+
stab.rustc_depr.is_none()) {
96102
self.tcx.sess.span_err(item_sp, "This stability annotation is useless");
97103
}
98104

99105
debug!("annotate: found {:?}", stab);
100106
// If parent is deprecated and we're not, inherit this by merging
101107
// deprecated_since and its reason.
102-
if let Some(parent_stab) = self.parent {
103-
if parent_stab.depr.is_some() && stab.depr.is_none() {
104-
stab.depr = parent_stab.depr.clone()
108+
if let Some(parent_stab) = self.parent_stab {
109+
if parent_stab.rustc_depr.is_some() && stab.rustc_depr.is_none() {
110+
stab.rustc_depr = parent_stab.rustc_depr.clone()
105111
}
106112
}
107113

108114
let stab = self.tcx.intern_stability(stab);
109115

110116
// Check if deprecated_since < stable_since. If it is,
111117
// this is *almost surely* an accident.
112-
if let (&Some(attr::Deprecation {since: ref dep_since, ..}),
113-
&attr::Stable {since: ref stab_since}) = (&stab.depr, &stab.level) {
118+
if let (&Some(attr::RustcDeprecation {since: ref dep_since, ..}),
119+
&attr::Stable {since: ref stab_since}) = (&stab.rustc_depr, &stab.level) {
114120
// Explicit version of iter::order::lt to handle parse errors properly
115121
for (dep_v, stab_v) in dep_since.split(".").zip(stab_since.split(".")) {
116122
if let (Ok(dep_v), Ok(stab_v)) = (dep_v.parse::<u64>(), stab_v.parse()) {
@@ -134,20 +140,20 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
134140
}
135141

136142
let def_id = self.tcx.map.local_def_id(id);
137-
self.index.map.insert(def_id, Some(stab));
143+
self.index.stab_map.insert(def_id, Some(stab));
138144

139-
let parent = replace(&mut self.parent, Some(stab));
145+
let orig_parent_stab = replace(&mut self.parent_stab, Some(stab));
140146
visit_children(self);
141-
self.parent = parent;
147+
self.parent_stab = orig_parent_stab;
142148
} else {
143-
debug!("annotate: not found, parent = {:?}", self.parent);
149+
debug!("annotate: not found, parent = {:?}", self.parent_stab);
144150
let mut is_error = kind == AnnotationKind::Required &&
145151
self.access_levels.is_reachable(id) &&
146152
!self.tcx.sess.opts.test;
147-
if let Some(stab) = self.parent {
153+
if let Some(stab) = self.parent_stab {
148154
if stab.level.is_unstable() {
149155
let def_id = self.tcx.map.local_def_id(id);
150-
self.index.map.insert(def_id, Some(stab));
156+
self.index.stab_map.insert(def_id, Some(stab));
151157
is_error = false;
152158
}
153159
}
@@ -167,7 +173,26 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
167173
outside of the standard library");
168174
}
169175
}
170-
visit_children(self);
176+
177+
if let Some(depr) = attr::find_deprecation(self.tcx.sess.diagnostic(), attrs, item_sp) {
178+
if kind == AnnotationKind::Prohibited {
179+
self.tcx.sess.span_err(item_sp, "This deprecation annotation is useless");
180+
}
181+
182+
// `Deprecation` is just two pointers, no need to intern it
183+
let def_id = self.tcx.map.local_def_id(id);
184+
self.index.depr_map.insert(def_id, Some(depr.clone()));
185+
186+
let orig_parent_depr = replace(&mut self.parent_depr, Some(depr));
187+
visit_children(self);
188+
self.parent_depr = orig_parent_depr;
189+
} else if let Some(depr) = self.parent_depr.clone() {
190+
let def_id = self.tcx.map.local_def_id(id);
191+
self.index.depr_map.insert(def_id, Some(depr));
192+
visit_children(self);
193+
} else {
194+
visit_children(self);
195+
}
171196
}
172197
}
173198
}
@@ -269,7 +294,8 @@ impl<'tcx> Index<'tcx> {
269294
let mut annotator = Annotator {
270295
tcx: tcx,
271296
index: self,
272-
parent: None,
297+
parent_stab: None,
298+
parent_depr: None,
273299
access_levels: access_levels,
274300
in_trait_impl: false,
275301
in_enum: false,
@@ -291,7 +317,8 @@ impl<'tcx> Index<'tcx> {
291317
staged_api.insert(LOCAL_CRATE, is_staged_api);
292318
Index {
293319
staged_api: staged_api,
294-
map: DefIdMap(),
320+
stab_map: DefIdMap(),
321+
depr_map: DefIdMap(),
295322
}
296323
}
297324
}
@@ -327,7 +354,11 @@ struct Checker<'a, 'tcx: 'a> {
327354
}
328355

329356
impl<'a, 'tcx> Checker<'a, 'tcx> {
330-
fn check(&mut self, id: DefId, span: Span, stab: &Option<&Stability>) {
357+
fn check(&mut self, id: DefId, span: Span,
358+
stab: &Option<&Stability>, _depr: &Option<Deprecation>) {
359+
if !is_staged_api(self.tcx, id) {
360+
return;
361+
}
331362
// Only the cross-crate scenario matters when checking unstable APIs
332363
let cross_crate = !id.is_local();
333364
if !cross_crate {
@@ -395,31 +426,31 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
395426
if item.span == DUMMY_SP && item.name.as_str() == "__test" { return }
396427

397428
check_item(self.tcx, item, true,
398-
&mut |id, sp, stab| self.check(id, sp, stab));
429+
&mut |id, sp, stab, depr| self.check(id, sp, stab, depr));
399430
intravisit::walk_item(self, item);
400431
}
401432

402433
fn visit_expr(&mut self, ex: &hir::Expr) {
403434
check_expr(self.tcx, ex,
404-
&mut |id, sp, stab| self.check(id, sp, stab));
435+
&mut |id, sp, stab, depr| self.check(id, sp, stab, depr));
405436
intravisit::walk_expr(self, ex);
406437
}
407438

408439
fn visit_path(&mut self, path: &hir::Path, id: ast::NodeId) {
409440
check_path(self.tcx, path, id,
410-
&mut |id, sp, stab| self.check(id, sp, stab));
441+
&mut |id, sp, stab, depr| self.check(id, sp, stab, depr));
411442
intravisit::walk_path(self, path)
412443
}
413444

414445
fn visit_path_list_item(&mut self, prefix: &hir::Path, item: &hir::PathListItem) {
415446
check_path_list_item(self.tcx, item,
416-
&mut |id, sp, stab| self.check(id, sp, stab));
447+
&mut |id, sp, stab, depr| self.check(id, sp, stab, depr));
417448
intravisit::walk_path_list_item(self, prefix, item)
418449
}
419450

420451
fn visit_pat(&mut self, pat: &hir::Pat) {
421452
check_pat(self.tcx, pat,
422-
&mut |id, sp, stab| self.check(id, sp, stab));
453+
&mut |id, sp, stab, depr| self.check(id, sp, stab, depr));
423454
intravisit::walk_pat(self, pat)
424455
}
425456

@@ -441,7 +472,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
441472

442473
/// Helper for discovering nodes to check for stability
443474
pub fn check_item(tcx: &ty::ctxt, item: &hir::Item, warn_about_defns: bool,
444-
cb: &mut FnMut(DefId, Span, &Option<&Stability>)) {
475+
cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option<Deprecation>)) {
445476
match item.node {
446477
hir::ItemExternCrate(_) => {
447478
// compiler-generated `extern crate` items have a dummy span.
@@ -478,7 +509,7 @@ pub fn check_item(tcx: &ty::ctxt, item: &hir::Item, warn_about_defns: bool,
478509

479510
/// Helper for discovering nodes to check for stability
480511
pub fn check_expr(tcx: &ty::ctxt, e: &hir::Expr,
481-
cb: &mut FnMut(DefId, Span, &Option<&Stability>)) {
512+
cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option<Deprecation>)) {
482513
let span;
483514
let id = match e.node {
484515
hir::ExprMethodCall(i, _, _) => {
@@ -539,7 +570,7 @@ pub fn check_expr(tcx: &ty::ctxt, e: &hir::Expr,
539570
}
540571

541572
pub fn check_path(tcx: &ty::ctxt, path: &hir::Path, id: ast::NodeId,
542-
cb: &mut FnMut(DefId, Span, &Option<&Stability>)) {
573+
cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option<Deprecation>)) {
543574
match tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
544575
Some(def::DefPrimTy(..)) => {}
545576
Some(def::DefSelfTy(..)) => {}
@@ -551,7 +582,7 @@ pub fn check_path(tcx: &ty::ctxt, path: &hir::Path, id: ast::NodeId,
551582
}
552583

553584
pub fn check_path_list_item(tcx: &ty::ctxt, item: &hir::PathListItem,
554-
cb: &mut FnMut(DefId, Span, &Option<&Stability>)) {
585+
cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option<Deprecation>)) {
555586
match tcx.def_map.borrow().get(&item.node.id()).map(|d| d.full_def()) {
556587
Some(def::DefPrimTy(..)) => {}
557588
Some(def) => {
@@ -562,7 +593,7 @@ pub fn check_path_list_item(tcx: &ty::ctxt, item: &hir::PathListItem,
562593
}
563594

564595
pub fn check_pat(tcx: &ty::ctxt, pat: &hir::Pat,
565-
cb: &mut FnMut(DefId, Span, &Option<&Stability>)) {
596+
cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option<Deprecation>)) {
566597
debug!("check_pat(pat = {:?})", pat);
567598
if is_internal(tcx, pat.span) { return; }
568599

@@ -591,21 +622,21 @@ pub fn check_pat(tcx: &ty::ctxt, pat: &hir::Pat,
591622
}
592623

593624
fn maybe_do_stability_check(tcx: &ty::ctxt, id: DefId, span: Span,
594-
cb: &mut FnMut(DefId, Span, &Option<&Stability>)) {
595-
if !is_staged_api(tcx, id) {
596-
debug!("maybe_do_stability_check: \
597-
skipping id={:?} since it is not staged_api", id);
598-
return;
599-
}
625+
cb: &mut FnMut(DefId, Span,
626+
&Option<&Stability>, &Option<Deprecation>)) {
600627
if is_internal(tcx, span) {
601628
debug!("maybe_do_stability_check: \
602629
skipping span={:?} since it is internal", span);
603630
return;
604631
}
605-
let ref stability = lookup(tcx, id);
632+
let (stability, deprecation) = if is_staged_api(tcx, id) {
633+
(lookup_stability(tcx, id), None)
634+
} else {
635+
(None, lookup_deprecation(tcx, id))
636+
};
606637
debug!("maybe_do_stability_check: \
607638
inspecting id={:?} span={:?} of stability={:?}", id, span, stability);
608-
cb(id, span, stability);
639+
cb(id, span, &stability, &deprecation);
609640
}
610641

611642
fn is_internal(tcx: &ty::ctxt, span: Span) -> bool {
@@ -627,47 +658,42 @@ fn is_staged_api(tcx: &ty::ctxt, id: DefId) -> bool {
627658

628659
/// Lookup the stability for a node, loading external crate
629660
/// metadata as necessary.
630-
pub fn lookup<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<&'tcx Stability> {
631-
if let Some(st) = tcx.stability.borrow().map.get(&id) {
661+
pub fn lookup_stability<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<&'tcx Stability> {
662+
if let Some(st) = tcx.stability.borrow().stab_map.get(&id) {
632663
return *st;
633664
}
634665

635-
let st = lookup_uncached(tcx, id);
636-
tcx.stability.borrow_mut().map.insert(id, st);
666+
let st = lookup_stability_uncached(tcx, id);
667+
tcx.stability.borrow_mut().stab_map.insert(id, st);
637668
st
638669
}
639670

640-
fn lookup_uncached<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<&'tcx Stability> {
641-
debug!("lookup(id={:?})", id);
642-
643-
// is this definition the implementation of a trait method?
644-
match tcx.trait_item_of_item(id) {
645-
Some(ty::MethodTraitItemId(trait_method_id)) if trait_method_id != id => {
646-
debug!("lookup: trait_method_id={:?}", trait_method_id);
647-
return lookup(tcx, trait_method_id)
648-
}
649-
_ => {}
671+
pub fn lookup_deprecation<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<Deprecation> {
672+
if let Some(depr) = tcx.stability.borrow().depr_map.get(&id) {
673+
return depr.clone();
650674
}
651675

652-
let item_stab = if id.is_local() {
676+
let depr = lookup_deprecation_uncached(tcx, id);
677+
tcx.stability.borrow_mut().depr_map.insert(id, depr.clone());
678+
depr
679+
}
680+
681+
fn lookup_stability_uncached<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<&'tcx Stability> {
682+
debug!("lookup(id={:?})", id);
683+
if id.is_local() {
653684
None // The stability cache is filled partially lazily
654685
} else {
655686
tcx.sess.cstore.stability(id).map(|st| tcx.intern_stability(st))
656-
};
657-
658-
item_stab.or_else(|| {
659-
if tcx.is_impl(id) {
660-
if let Some(trait_id) = tcx.trait_id_of_impl(id) {
661-
// FIXME (#18969): for the time being, simply use the
662-
// stability of the trait to determine the stability of any
663-
// unmarked impls for it. See FIXME above for more details.
687+
}
688+
}
664689

665-
debug!("lookup: trait_id={:?}", trait_id);
666-
return lookup(tcx, trait_id);
667-
}
668-
}
669-
None
670-
})
690+
fn lookup_deprecation_uncached<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<Deprecation> {
691+
debug!("lookup(id={:?})", id);
692+
if id.is_local() {
693+
None // The stability cache is filled partially lazily
694+
} else {
695+
tcx.sess.cstore.deprecation(id)
696+
}
671697
}
672698

673699
/// Given the list of enabled features that were not language features (i.e. that

0 commit comments

Comments
 (0)
Please sign in to comment.