@@ -20,11 +20,16 @@ use rustc_hir::{FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant};
20
20
use rustc_middle:: hir:: nested_filter;
21
21
use rustc_middle:: middle:: lib_features:: { FeatureStability , LibFeatures } ;
22
22
use rustc_middle:: middle:: privacy:: EffectiveVisibilities ;
23
- use rustc_middle:: middle:: stability:: { AllowUnstable , DeprecationEntry , Index } ;
23
+ use rustc_middle:: middle:: stability:: {
24
+ AllowUnstable , Deprecated , DeprecationEntry , EvalResult , Index ,
25
+ } ;
24
26
use rustc_middle:: query:: Providers ;
25
27
use rustc_middle:: ty:: TyCtxt ;
28
+ use rustc_middle:: ty:: print:: with_no_trimmed_paths;
26
29
use rustc_session:: lint;
27
- use rustc_session:: lint:: builtin:: { INEFFECTIVE_UNSTABLE_TRAIT_IMPL , USELESS_DEPRECATED } ;
30
+ use rustc_session:: lint:: builtin:: {
31
+ DEPRECATED , INEFFECTIVE_UNSTABLE_TRAIT_IMPL , USELESS_DEPRECATED ,
32
+ } ;
28
33
use rustc_span:: { Span , Symbol , sym} ;
29
34
use tracing:: { debug, info} ;
30
35
@@ -844,42 +849,93 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
844
849
} ,
845
850
) ;
846
851
847
- let is_allowed_through_unstable_modules = |def_id| {
848
- self . tcx . lookup_stability ( def_id) . is_some_and ( |stab| match stab. level {
849
- StabilityLevel :: Stable { allowed_through_unstable_modules, .. } => {
850
- allowed_through_unstable_modules
852
+ if item_is_allowed {
853
+ // The item itself is allowed; check whether the path there is also allowed.
854
+ let is_allowed_through_unstable_modules: Option < Option < Symbol > > =
855
+ self . tcx . lookup_stability ( def_id) . and_then ( |stab| match stab. level {
856
+ StabilityLevel :: Stable { allowed_through_unstable_modules, .. } => {
857
+ allowed_through_unstable_modules
858
+ }
859
+ _ => None ,
860
+ } ) ;
861
+
862
+ if is_allowed_through_unstable_modules. is_none ( ) {
863
+ // Check parent modules stability as well if the item the path refers to is itself
864
+ // stable. We only emit warnings for unstable path segments if the item is stable
865
+ // or allowed because stability is often inherited, so the most common case is that
866
+ // both the segments and the item are unstable behind the same feature flag.
867
+ //
868
+ // We check here rather than in `visit_path_segment` to prevent visiting the last
869
+ // path segment twice
870
+ //
871
+ // We include special cases via #[rustc_allowed_through_unstable_modules] for items
872
+ // that were accidentally stabilized through unstable paths before this check was
873
+ // added, such as `core::intrinsics::transmute`
874
+ let parents = path. segments . iter ( ) . rev ( ) . skip ( 1 ) ;
875
+ for path_segment in parents {
876
+ if let Some ( def_id) = path_segment. res . opt_def_id ( ) {
877
+ // use `None` for id to prevent deprecation check
878
+ self . tcx . check_stability_allow_unstable (
879
+ def_id,
880
+ None ,
881
+ path. span ,
882
+ None ,
883
+ if is_unstable_reexport ( self . tcx , id) {
884
+ AllowUnstable :: Yes
885
+ } else {
886
+ AllowUnstable :: No
887
+ } ,
888
+ ) ;
889
+ }
851
890
}
852
- _ => false ,
853
- } )
854
- } ;
855
-
856
- if item_is_allowed && !is_allowed_through_unstable_modules ( def_id) {
857
- // Check parent modules stability as well if the item the path refers to is itself
858
- // stable. We only emit warnings for unstable path segments if the item is stable
859
- // or allowed because stability is often inherited, so the most common case is that
860
- // both the segments and the item are unstable behind the same feature flag.
861
- //
862
- // We check here rather than in `visit_path_segment` to prevent visiting the last
863
- // path segment twice
864
- //
865
- // We include special cases via #[rustc_allowed_through_unstable_modules] for items
866
- // that were accidentally stabilized through unstable paths before this check was
867
- // added, such as `core::intrinsics::transmute`
868
- let parents = path. segments . iter ( ) . rev ( ) . skip ( 1 ) ;
869
- for path_segment in parents {
870
- if let Some ( def_id) = path_segment. res . opt_def_id ( ) {
871
- // use `None` for id to prevent deprecation check
872
- self . tcx . check_stability_allow_unstable (
873
- def_id,
874
- None ,
875
- path. span ,
876
- None ,
877
- if is_unstable_reexport ( self . tcx , id) {
878
- AllowUnstable :: Yes
879
- } else {
880
- AllowUnstable :: No
881
- } ,
882
- ) ;
891
+ } else if let Some ( Some ( deprecation) ) = is_allowed_through_unstable_modules {
892
+ // Similar to above, but we cannot use `check_stability_allow_unstable` as that would
893
+ // immediately show the stability error. We just want to know the result and disaplay
894
+ // our own kind of error.
895
+ let parents = path. segments . iter ( ) . rev ( ) . skip ( 1 ) ;
896
+ for path_segment in parents {
897
+ if let Some ( def_id) = path_segment. res . opt_def_id ( ) {
898
+ // use `None` for id to prevent deprecation check
899
+ let eval_result = self . tcx . eval_stability_allow_unstable (
900
+ def_id,
901
+ None ,
902
+ path. span ,
903
+ None ,
904
+ if is_unstable_reexport ( self . tcx , id) {
905
+ AllowUnstable :: Yes
906
+ } else {
907
+ AllowUnstable :: No
908
+ } ,
909
+ ) ;
910
+ let is_allowed = matches ! ( eval_result, EvalResult :: Allow ) ;
911
+ if !is_allowed {
912
+ // Calculating message for lint involves calling `self.def_path_str`,
913
+ // which will by default invoke the expensive `visible_parent_map` query.
914
+ // Skip all that work if the lint is allowed anyway.
915
+ if self . tcx . lint_level_at_node ( DEPRECATED , id) . 0
916
+ == lint:: Level :: Allow
917
+ {
918
+ return ;
919
+ }
920
+ // Show a deprecation message.
921
+ let def_path =
922
+ with_no_trimmed_paths ! ( self . tcx. def_path_str( def_id) ) ;
923
+ let def_kind = self . tcx . def_descr ( def_id) ;
924
+ let diag = Deprecated {
925
+ sub : None ,
926
+ kind : def_kind. to_owned ( ) ,
927
+ path : def_path,
928
+ note : Some ( deprecation) ,
929
+ since_kind : lint:: DeprecatedSinceKind :: InEffect ,
930
+ } ;
931
+ self . tcx . emit_node_span_lint (
932
+ DEPRECATED ,
933
+ id,
934
+ method_span. unwrap_or ( path. span ) ,
935
+ diag,
936
+ ) ;
937
+ }
938
+ }
883
939
}
884
940
}
885
941
}
0 commit comments