@@ -25,7 +25,7 @@ use syntax::codemap::{Span, DUMMY_SP};
25
25
use syntax:: ast;
26
26
use syntax:: ast:: { NodeId , Attribute } ;
27
27
use syntax:: feature_gate:: { GateIssue , emit_feature_err} ;
28
- use syntax:: attr:: { self , Stability , AttrMetaMethods } ;
28
+ use syntax:: attr:: { self , Stability , Deprecation , AttrMetaMethods } ;
29
29
use util:: nodemap:: { DefIdMap , FnvHashSet , FnvHashMap } ;
30
30
31
31
use rustc_front:: hir;
@@ -61,7 +61,8 @@ enum AnnotationKind {
61
61
pub struct Index < ' tcx > {
62
62
/// This is mostly a cache, except the stabilities of local items
63
63
/// are filled by the annotator.
64
- map : DefIdMap < Option < & ' tcx Stability > > ,
64
+ stab_map : DefIdMap < Option < & ' tcx Stability > > ,
65
+ depr_map : DefIdMap < Option < Deprecation > > ,
65
66
66
67
/// Maps for each crate whether it is part of the staged API.
67
68
staged_api : FnvHashMap < ast:: CrateNum , bool >
@@ -71,7 +72,8 @@ pub struct Index<'tcx> {
71
72
struct Annotator < ' a , ' tcx : ' a > {
72
73
tcx : & ' a ty:: ctxt < ' tcx > ,
73
74
index : & ' a mut Index < ' tcx > ,
74
- parent : Option < & ' tcx Stability > ,
75
+ parent_stab : Option < & ' tcx Stability > ,
76
+ parent_depr : Option < Deprecation > ,
75
77
access_levels : & ' a AccessLevels ,
76
78
in_trait_impl : bool ,
77
79
in_enum : bool ,
@@ -86,31 +88,35 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
86
88
{
87
89
if self . index . staged_api [ & LOCAL_CRATE ] && self . tcx . sess . features . borrow ( ) . staged_api {
88
90
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
+ }
89
95
if let Some ( mut stab) = attr:: find_stability ( self . tcx . sess . diagnostic ( ) ,
90
96
attrs, item_sp) {
91
97
// Error if prohibited, or can't inherit anything from a container
92
98
if kind == AnnotationKind :: Prohibited ||
93
99
( kind == AnnotationKind :: Container &&
94
100
stab. level . is_stable ( ) &&
95
- stab. depr . is_none ( ) ) {
101
+ stab. rustc_depr . is_none ( ) ) {
96
102
self . tcx . sess . span_err ( item_sp, "This stability annotation is useless" ) ;
97
103
}
98
104
99
105
debug ! ( "annotate: found {:?}" , stab) ;
100
106
// If parent is deprecated and we're not, inherit this by merging
101
107
// 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 ( )
105
111
}
106
112
}
107
113
108
114
let stab = self . tcx . intern_stability ( stab) ;
109
115
110
116
// Check if deprecated_since < stable_since. If it is,
111
117
// 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 ) {
114
120
// Explicit version of iter::order::lt to handle parse errors properly
115
121
for ( dep_v, stab_v) in dep_since. split ( "." ) . zip ( stab_since. split ( "." ) ) {
116
122
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> {
134
140
}
135
141
136
142
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) ) ;
138
144
139
- let parent = replace ( & mut self . parent , Some ( stab) ) ;
145
+ let orig_parent_stab = replace ( & mut self . parent_stab , Some ( stab) ) ;
140
146
visit_children ( self ) ;
141
- self . parent = parent ;
147
+ self . parent_stab = orig_parent_stab ;
142
148
} else {
143
- debug ! ( "annotate: not found, parent = {:?}" , self . parent ) ;
149
+ debug ! ( "annotate: not found, parent = {:?}" , self . parent_stab ) ;
144
150
let mut is_error = kind == AnnotationKind :: Required &&
145
151
self . access_levels . is_reachable ( id) &&
146
152
!self . tcx . sess . opts . test ;
147
- if let Some ( stab) = self . parent {
153
+ if let Some ( stab) = self . parent_stab {
148
154
if stab. level . is_unstable ( ) {
149
155
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) ) ;
151
157
is_error = false ;
152
158
}
153
159
}
@@ -167,7 +173,26 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
167
173
outside of the standard library") ;
168
174
}
169
175
}
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
+ }
171
196
}
172
197
}
173
198
}
@@ -269,7 +294,8 @@ impl<'tcx> Index<'tcx> {
269
294
let mut annotator = Annotator {
270
295
tcx : tcx,
271
296
index : self ,
272
- parent : None ,
297
+ parent_stab : None ,
298
+ parent_depr : None ,
273
299
access_levels : access_levels,
274
300
in_trait_impl : false ,
275
301
in_enum : false ,
@@ -291,7 +317,8 @@ impl<'tcx> Index<'tcx> {
291
317
staged_api. insert ( LOCAL_CRATE , is_staged_api) ;
292
318
Index {
293
319
staged_api : staged_api,
294
- map : DefIdMap ( ) ,
320
+ stab_map : DefIdMap ( ) ,
321
+ depr_map : DefIdMap ( ) ,
295
322
}
296
323
}
297
324
}
@@ -327,7 +354,11 @@ struct Checker<'a, 'tcx: 'a> {
327
354
}
328
355
329
356
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
+ }
331
362
// Only the cross-crate scenario matters when checking unstable APIs
332
363
let cross_crate = !id. is_local ( ) ;
333
364
if !cross_crate {
@@ -395,31 +426,31 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
395
426
if item. span == DUMMY_SP && item. name . as_str ( ) == "__test" { return }
396
427
397
428
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 ) ) ;
399
430
intravisit:: walk_item ( self , item) ;
400
431
}
401
432
402
433
fn visit_expr ( & mut self , ex : & hir:: Expr ) {
403
434
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 ) ) ;
405
436
intravisit:: walk_expr ( self , ex) ;
406
437
}
407
438
408
439
fn visit_path ( & mut self , path : & hir:: Path , id : ast:: NodeId ) {
409
440
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 ) ) ;
411
442
intravisit:: walk_path ( self , path)
412
443
}
413
444
414
445
fn visit_path_list_item ( & mut self , prefix : & hir:: Path , item : & hir:: PathListItem ) {
415
446
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 ) ) ;
417
448
intravisit:: walk_path_list_item ( self , prefix, item)
418
449
}
419
450
420
451
fn visit_pat ( & mut self , pat : & hir:: Pat ) {
421
452
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 ) ) ;
423
454
intravisit:: walk_pat ( self , pat)
424
455
}
425
456
@@ -441,7 +472,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
441
472
442
473
/// Helper for discovering nodes to check for stability
443
474
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 > ) ) {
445
476
match item. node {
446
477
hir:: ItemExternCrate ( _) => {
447
478
// 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,
478
509
479
510
/// Helper for discovering nodes to check for stability
480
511
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 > ) ) {
482
513
let span;
483
514
let id = match e. node {
484
515
hir:: ExprMethodCall ( i, _, _) => {
@@ -539,7 +570,7 @@ pub fn check_expr(tcx: &ty::ctxt, e: &hir::Expr,
539
570
}
540
571
541
572
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 > ) ) {
543
574
match tcx. def_map . borrow ( ) . get ( & id) . map ( |d| d. full_def ( ) ) {
544
575
Some ( def:: DefPrimTy ( ..) ) => { }
545
576
Some ( def:: DefSelfTy ( ..) ) => { }
@@ -551,7 +582,7 @@ pub fn check_path(tcx: &ty::ctxt, path: &hir::Path, id: ast::NodeId,
551
582
}
552
583
553
584
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 > ) ) {
555
586
match tcx. def_map . borrow ( ) . get ( & item. node . id ( ) ) . map ( |d| d. full_def ( ) ) {
556
587
Some ( def:: DefPrimTy ( ..) ) => { }
557
588
Some ( def) => {
@@ -562,7 +593,7 @@ pub fn check_path_list_item(tcx: &ty::ctxt, item: &hir::PathListItem,
562
593
}
563
594
564
595
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 > ) ) {
566
597
debug ! ( "check_pat(pat = {:?})" , pat) ;
567
598
if is_internal ( tcx, pat. span ) { return ; }
568
599
@@ -591,21 +622,21 @@ pub fn check_pat(tcx: &ty::ctxt, pat: &hir::Pat,
591
622
}
592
623
593
624
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 > ) ) {
600
627
if is_internal ( tcx, span) {
601
628
debug ! ( "maybe_do_stability_check: \
602
629
skipping span={:?} since it is internal", span) ;
603
630
return ;
604
631
}
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
+ } ;
606
637
debug ! ( "maybe_do_stability_check: \
607
638
inspecting id={:?} span={:?} of stability={:?}", id, span, stability) ;
608
- cb ( id, span, stability) ;
639
+ cb ( id, span, & stability, & deprecation ) ;
609
640
}
610
641
611
642
fn is_internal ( tcx : & ty:: ctxt , span : Span ) -> bool {
@@ -627,47 +658,42 @@ fn is_staged_api(tcx: &ty::ctxt, id: DefId) -> bool {
627
658
628
659
/// Lookup the stability for a node, loading external crate
629
660
/// 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) {
632
663
return * st;
633
664
}
634
665
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) ;
637
668
st
638
669
}
639
670
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 ( ) ;
650
674
}
651
675
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 ( ) {
653
684
None // The stability cache is filled partially lazily
654
685
} else {
655
686
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
+ }
664
689
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
+ }
671
697
}
672
698
673
699
/// Given the list of enabled features that were not language features (i.e. that
0 commit comments