44pub use self :: StabilityLevel :: * ;
55
66use crate :: lint:: { self , Lint , in_derive_expansion} ;
7+ use crate :: lint:: builtin:: BuiltinLintDiagnostics ;
78use crate :: hir:: { self , Item , Generics , StructField , Variant , HirId } ;
89use crate :: hir:: def:: { Res , DefKind } ;
910use crate :: hir:: def_id:: { CrateNum , CRATE_DEF_INDEX , DefId , LOCAL_CRATE } ;
1011use crate :: hir:: intravisit:: { self , Visitor , NestedVisitorMap } ;
1112use crate :: ty:: query:: Providers ;
1213use crate :: middle:: privacy:: AccessLevels ;
1314use crate :: session:: { DiagnosticMessageId , Session } ;
15+ use errors:: DiagnosticBuilder ;
1416use syntax:: symbol:: { Symbol , sym} ;
1517use syntax_pos:: { Span , MultiSpan } ;
16- use syntax:: ast:: Attribute ;
18+ use syntax:: ast:: { Attribute , CRATE_NODE_ID } ;
1719use syntax:: errors:: Applicability ;
1820use syntax:: feature_gate:: { GateIssue , emit_feature_err} ;
19- use syntax:: attr:: { self , Stability , Deprecation } ;
21+ use syntax:: attr:: { self , Stability , Deprecation , RustcDeprecation } ;
2022use crate :: ty:: { self , TyCtxt } ;
2123use crate :: util:: nodemap:: { FxHashSet , FxHashMap } ;
2224
@@ -477,6 +479,36 @@ pub fn provide(providers: &mut Providers<'_>) {
477479 } ;
478480}
479481
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+
480512/// Checks whether an item marked with `deprecated(since="X")` is currently
481513/// deprecated (i.e., whether X is not greater than the current rustc version).
482514pub fn deprecation_in_effect ( since : & str ) -> bool {
@@ -501,6 +533,79 @@ pub fn deprecation_in_effect(since: &str) -> bool {
501533 }
502534}
503535
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+
504609struct Checker < ' tcx > {
505610 tcx : TyCtxt < ' tcx > ,
506611}
@@ -563,38 +668,6 @@ impl<'tcx> TyCtxt<'tcx> {
563668 /// deprecated. If the item is indeed deprecated, we will emit a deprecation lint attached to
564669 /// `id`.
565670 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-
598671 // Deprecated attributes apply in-crate and cross-crate.
599672 if let Some ( id) = id {
600673 if let Some ( depr_entry) = self . lookup_deprecation_entry ( def_id) {
@@ -604,14 +677,9 @@ impl<'tcx> TyCtxt<'tcx> {
604677 . map_or ( false , |parent_depr| parent_depr. same_origin ( & depr_entry) ) ;
605678
606679 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) ;
615683 }
616684 } ;
617685 }
@@ -631,27 +699,11 @@ impl<'tcx> TyCtxt<'tcx> {
631699 if let Some ( id) = id {
632700 if let Some ( stability) = stability {
633701 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+ ) ;
655707 }
656708 }
657709 }
@@ -715,34 +767,8 @@ impl<'tcx> TyCtxt<'tcx> {
715767 pub fn check_stability ( self , def_id : DefId , id : Option < HirId > , span : Span ) {
716768 match self . eval_stability ( def_id, id, span) {
717769 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) ,
746772 EvalResult :: Unmarked => {
747773 // The API could be uncallable for other reasons, for example when a private module
748774 // was referenced.
0 commit comments