4
4
pub use self :: StabilityLevel :: * ;
5
5
6
6
use crate :: lint:: { self , Lint , in_derive_expansion} ;
7
+ use crate :: lint:: builtin:: BuiltinLintDiagnostics ;
7
8
use crate :: hir:: { self , Item , Generics , StructField , Variant , HirId } ;
8
9
use crate :: hir:: def:: { Res , DefKind } ;
9
10
use crate :: hir:: def_id:: { CrateNum , CRATE_DEF_INDEX , DefId , LOCAL_CRATE } ;
10
11
use crate :: hir:: intravisit:: { self , Visitor , NestedVisitorMap } ;
11
12
use crate :: ty:: query:: Providers ;
12
13
use crate :: middle:: privacy:: AccessLevels ;
13
14
use crate :: session:: { DiagnosticMessageId , Session } ;
15
+ use errors:: DiagnosticBuilder ;
14
16
use syntax:: symbol:: { Symbol , sym} ;
15
17
use syntax_pos:: { Span , MultiSpan } ;
16
- use syntax:: ast:: Attribute ;
18
+ use syntax:: ast:: { Attribute , CRATE_NODE_ID } ;
17
19
use syntax:: errors:: Applicability ;
18
20
use syntax:: feature_gate:: { GateIssue , emit_feature_err} ;
19
- use syntax:: attr:: { self , Stability , Deprecation } ;
21
+ use syntax:: attr:: { self , Stability , Deprecation , RustcDeprecation } ;
20
22
use crate :: ty:: { self , TyCtxt } ;
21
23
use crate :: util:: nodemap:: { FxHashSet , FxHashMap } ;
22
24
@@ -477,6 +479,36 @@ pub fn provide(providers: &mut Providers<'_>) {
477
479
} ;
478
480
}
479
481
482
+ pub fn report_unstable (
483
+ sess : & Session , feature : Symbol , reason : Option < Symbol > , issue : u32 , span : Span
484
+ ) {
485
+ let msg = match reason {
486
+ Some ( r) => format ! ( "use of unstable library feature '{}': {}" , feature, r) ,
487
+ None => format ! ( "use of unstable library feature '{}'" , & feature)
488
+ } ;
489
+
490
+ let msp: MultiSpan = span. into ( ) ;
491
+ let cm = & sess. parse_sess . source_map ( ) ;
492
+ let span_key = msp. primary_span ( ) . and_then ( |sp : Span |
493
+ if !sp. is_dummy ( ) {
494
+ let file = cm. lookup_char_pos ( sp. lo ( ) ) . file ;
495
+ if file. name . is_macros ( ) {
496
+ None
497
+ } else {
498
+ Some ( span)
499
+ }
500
+ } else {
501
+ None
502
+ }
503
+ ) ;
504
+
505
+ let error_id = ( DiagnosticMessageId :: StabilityId ( issue) , span_key, msg. clone ( ) ) ;
506
+ let fresh = sess. one_time_diagnostics . borrow_mut ( ) . insert ( error_id) ;
507
+ if fresh {
508
+ emit_feature_err ( & sess. parse_sess , feature, span, GateIssue :: Library ( Some ( issue) ) , & msg) ;
509
+ }
510
+ }
511
+
480
512
/// Checks whether an item marked with `deprecated(since="X")` is currently
481
513
/// deprecated (i.e., whether X is not greater than the current rustc version).
482
514
pub fn deprecation_in_effect ( since : & str ) -> bool {
@@ -501,6 +533,79 @@ pub fn deprecation_in_effect(since: &str) -> bool {
501
533
}
502
534
}
503
535
536
+ pub fn deprecation_suggestion (
537
+ diag : & mut DiagnosticBuilder < ' _ > , suggestion : Option < Symbol > , span : Span
538
+ ) {
539
+ if let Some ( suggestion) = suggestion {
540
+ diag. span_suggestion (
541
+ span,
542
+ "replace the use of the deprecated item" ,
543
+ suggestion. to_string ( ) ,
544
+ Applicability :: MachineApplicable ,
545
+ ) ;
546
+ }
547
+ }
548
+
549
+ fn deprecation_message_common ( message : String , reason : Option < Symbol > ) -> String {
550
+ match reason {
551
+ Some ( reason) => format ! ( "{}: {}" , message, reason) ,
552
+ None => message,
553
+ }
554
+ }
555
+
556
+ pub fn deprecation_message ( depr : & Deprecation , path : & str ) -> ( String , & ' static Lint ) {
557
+ let message = format ! ( "use of deprecated item '{}'" , path) ;
558
+ ( deprecation_message_common ( message, depr. note ) , lint:: builtin:: DEPRECATED )
559
+ }
560
+
561
+ pub fn rustc_deprecation_message ( depr : & RustcDeprecation , path : & str ) -> ( String , & ' static Lint ) {
562
+ let ( message, lint) = if deprecation_in_effect ( & depr. since . as_str ( ) ) {
563
+ ( format ! ( "use of deprecated item '{}'" , path) , lint:: builtin:: DEPRECATED )
564
+ } else {
565
+ ( format ! ( "use of item '{}' that will be deprecated in future version {}" , path, depr. since) ,
566
+ lint:: builtin:: DEPRECATED_IN_FUTURE )
567
+ } ;
568
+ ( deprecation_message_common ( message, Some ( depr. reason ) ) , lint)
569
+ }
570
+
571
+ pub fn early_report_deprecation (
572
+ sess : & Session ,
573
+ message : & str ,
574
+ suggestion : Option < Symbol > ,
575
+ lint : & ' static Lint ,
576
+ span : Span ,
577
+ ) {
578
+ if in_derive_expansion ( span) {
579
+ return ;
580
+ }
581
+
582
+ let diag = BuiltinLintDiagnostics :: DeprecatedMacro ( suggestion, span) ;
583
+ sess. buffer_lint_with_diagnostic ( lint, CRATE_NODE_ID , span, message, diag) ;
584
+ }
585
+
586
+ fn late_report_deprecation (
587
+ tcx : TyCtxt < ' _ > ,
588
+ message : & str ,
589
+ suggestion : Option < Symbol > ,
590
+ lint : & ' static Lint ,
591
+ span : Span ,
592
+ def_id : DefId ,
593
+ hir_id : HirId ,
594
+ ) {
595
+ if in_derive_expansion ( span) {
596
+ return ;
597
+ }
598
+
599
+ let mut diag = tcx. struct_span_lint_hir ( lint, hir_id, span, message) ;
600
+ if let hir:: Node :: Expr ( _) = tcx. hir ( ) . get ( hir_id) {
601
+ deprecation_suggestion ( & mut diag, suggestion, span) ;
602
+ }
603
+ diag. emit ( ) ;
604
+ if hir_id == hir:: DUMMY_HIR_ID {
605
+ span_bug ! ( span, "emitted a {} lint with dummy HIR id: {:?}" , lint. name, def_id) ;
606
+ }
607
+ }
608
+
504
609
struct Checker < ' tcx > {
505
610
tcx : TyCtxt < ' tcx > ,
506
611
}
@@ -563,38 +668,6 @@ impl<'tcx> TyCtxt<'tcx> {
563
668
/// deprecated. If the item is indeed deprecated, we will emit a deprecation lint attached to
564
669
/// `id`.
565
670
pub fn eval_stability ( self , def_id : DefId , id : Option < HirId > , span : Span ) -> EvalResult {
566
- let lint_deprecated = |def_id : DefId ,
567
- id : HirId ,
568
- note : Option < Symbol > ,
569
- suggestion : Option < Symbol > ,
570
- message : & str ,
571
- lint : & ' static Lint | {
572
- if in_derive_expansion ( span) {
573
- return ;
574
- }
575
- let msg = if let Some ( note) = note {
576
- format ! ( "{}: {}" , message, note)
577
- } else {
578
- format ! ( "{}" , message)
579
- } ;
580
-
581
- let mut diag = self . struct_span_lint_hir ( lint, id, span, & msg) ;
582
- if let Some ( suggestion) = suggestion {
583
- if let hir:: Node :: Expr ( _) = self . hir ( ) . get ( id) {
584
- diag. span_suggestion (
585
- span,
586
- "replace the use of the deprecated item" ,
587
- suggestion. to_string ( ) ,
588
- Applicability :: MachineApplicable ,
589
- ) ;
590
- }
591
- }
592
- diag. emit ( ) ;
593
- if id == hir:: DUMMY_HIR_ID {
594
- span_bug ! ( span, "emitted a {} lint with dummy HIR id: {:?}" , lint. name, def_id) ;
595
- }
596
- } ;
597
-
598
671
// Deprecated attributes apply in-crate and cross-crate.
599
672
if let Some ( id) = id {
600
673
if let Some ( depr_entry) = self . lookup_deprecation_entry ( def_id) {
@@ -604,14 +677,9 @@ impl<'tcx> TyCtxt<'tcx> {
604
677
. map_or ( false , |parent_depr| parent_depr. same_origin ( & depr_entry) ) ;
605
678
606
679
if !skip {
607
- let path = self . def_path_str ( def_id) ;
608
- let message = format ! ( "use of deprecated item '{}'" , path) ;
609
- lint_deprecated ( def_id,
610
- id,
611
- depr_entry. attr . note ,
612
- None ,
613
- & message,
614
- lint:: builtin:: DEPRECATED ) ;
680
+ let ( message, lint) =
681
+ deprecation_message ( & depr_entry. attr , & self . def_path_str ( def_id) ) ;
682
+ late_report_deprecation ( self , & message, None , lint, span, def_id, id) ;
615
683
}
616
684
} ;
617
685
}
@@ -631,27 +699,11 @@ impl<'tcx> TyCtxt<'tcx> {
631
699
if let Some ( id) = id {
632
700
if let Some ( stability) = stability {
633
701
if let Some ( depr) = & stability. rustc_depr {
634
- let path = self . def_path_str ( def_id) ;
635
- if deprecation_in_effect ( & depr. since . as_str ( ) ) {
636
- let message = format ! ( "use of deprecated item '{}'" , path) ;
637
- lint_deprecated ( def_id,
638
- id,
639
- Some ( depr. reason ) ,
640
- depr. suggestion ,
641
- & message,
642
- lint:: builtin:: DEPRECATED ) ;
643
- } else {
644
- let message = format ! ( "use of item '{}' \
645
- that will be deprecated in future version {}",
646
- path,
647
- depr. since) ;
648
- lint_deprecated ( def_id,
649
- id,
650
- Some ( depr. reason ) ,
651
- depr. suggestion ,
652
- & message,
653
- lint:: builtin:: DEPRECATED_IN_FUTURE ) ;
654
- }
702
+ let ( message, lint) =
703
+ rustc_deprecation_message ( depr, & self . def_path_str ( def_id) ) ;
704
+ late_report_deprecation (
705
+ self , & message, depr. suggestion , lint, span, def_id, id
706
+ ) ;
655
707
}
656
708
}
657
709
}
@@ -715,34 +767,8 @@ impl<'tcx> TyCtxt<'tcx> {
715
767
pub fn check_stability ( self , def_id : DefId , id : Option < HirId > , span : Span ) {
716
768
match self . eval_stability ( def_id, id, span) {
717
769
EvalResult :: Allow => { }
718
- EvalResult :: Deny { feature, reason, issue } => {
719
- let msg = match reason {
720
- Some ( r) => format ! ( "use of unstable library feature '{}': {}" , feature, r) ,
721
- None => format ! ( "use of unstable library feature '{}'" , & feature)
722
- } ;
723
-
724
- let msp: MultiSpan = span. into ( ) ;
725
- let cm = & self . sess . parse_sess . source_map ( ) ;
726
- let span_key = msp. primary_span ( ) . and_then ( |sp : Span |
727
- if !sp. is_dummy ( ) {
728
- let file = cm. lookup_char_pos ( sp. lo ( ) ) . file ;
729
- if file. name . is_macros ( ) {
730
- None
731
- } else {
732
- Some ( span)
733
- }
734
- } else {
735
- None
736
- }
737
- ) ;
738
-
739
- let error_id = ( DiagnosticMessageId :: StabilityId ( issue) , span_key, msg. clone ( ) ) ;
740
- let fresh = self . sess . one_time_diagnostics . borrow_mut ( ) . insert ( error_id) ;
741
- if fresh {
742
- emit_feature_err ( & self . sess . parse_sess , feature, span,
743
- GateIssue :: Library ( Some ( issue) ) , & msg) ;
744
- }
745
- }
770
+ EvalResult :: Deny { feature, reason, issue } =>
771
+ report_unstable ( self . sess , feature, reason, issue, span) ,
746
772
EvalResult :: Unmarked => {
747
773
// The API could be uncallable for other reasons, for example when a private module
748
774
// was referenced.
0 commit comments