@@ -25,7 +25,7 @@ use syntax::codemap::{Span, DUMMY_SP};
2525use syntax:: ast;
2626use syntax:: ast:: { NodeId , Attribute } ;
2727use syntax:: feature_gate:: { GateIssue , emit_feature_err} ;
28- use syntax:: attr:: { self , Stability , AttrMetaMethods } ;
28+ use syntax:: attr:: { self , Stability , Deprecation , AttrMetaMethods } ;
2929use util:: nodemap:: { DefIdMap , FnvHashSet , FnvHashMap } ;
3030
3131use rustc_front:: hir;
@@ -61,7 +61,8 @@ enum AnnotationKind {
6161pub 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> {
7172struct 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
329356impl < ' 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
443474pub 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
480511pub 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
541572pub 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
553584pub 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
564595pub 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
593624fn 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
611642fn 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