@@ -5,8 +5,8 @@ use std::mem::replace;
55use std:: num:: NonZero ;
66
77use rustc_attr_parsing:: {
8- self as attr, AllowedThroughUnstableModules , ConstStability , DeprecatedSince , Stability ,
9- StabilityLevel , StableSince , UnstableReason , VERSION_PLACEHOLDER ,
8+ self as attr, ConstStability , DeprecatedSince , Stability , StabilityLevel , StableSince ,
9+ UnstableReason , VERSION_PLACEHOLDER ,
1010} ;
1111use rustc_data_structures:: fx:: FxIndexMap ;
1212use rustc_data_structures:: unord:: { ExtendUnord , UnordMap , UnordSet } ;
@@ -880,91 +880,87 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
880880
881881 if item_is_allowed {
882882 // The item itself is allowed; check whether the path there is also allowed.
883- let is_allowed_through_unstable_modules: Option < AllowedThroughUnstableModules > =
883+ let is_allowed_through_unstable_modules: Option < Symbol > =
884884 self . tcx . lookup_stability ( def_id) . and_then ( |stab| match stab. level {
885885 StabilityLevel :: Stable { allowed_through_unstable_modules, .. } => {
886886 allowed_through_unstable_modules
887887 }
888888 _ => None ,
889889 } ) ;
890890
891- if is_allowed_through_unstable_modules. is_none ( ) {
892- // Check parent modules stability as well if the item the path refers to is itself
893- // stable. We only emit warnings for unstable path segments if the item is stable
894- // or allowed because stability is often inherited, so the most common case is that
895- // both the segments and the item are unstable behind the same feature flag.
896- //
897- // We check here rather than in `visit_path_segment` to prevent visiting the last
898- // path segment twice
899- //
900- // We include special cases via #[rustc_allowed_through_unstable_modules] for items
901- // that were accidentally stabilized through unstable paths before this check was
902- // added, such as `core::intrinsics::transmute`
903- let parents = path. segments . iter ( ) . rev ( ) . skip ( 1 ) ;
904- for path_segment in parents {
905- if let Some ( def_id) = path_segment. res . opt_def_id ( ) {
906- // use `None` for id to prevent deprecation check
907- self . tcx . check_stability_allow_unstable (
908- def_id,
909- None ,
910- path. span ,
911- None ,
912- if is_unstable_reexport ( self . tcx , id) {
913- AllowUnstable :: Yes
914- } else {
915- AllowUnstable :: No
916- } ,
917- ) ;
918- }
919- }
920- } else if let Some ( AllowedThroughUnstableModules :: WithDeprecation ( deprecation) ) =
921- is_allowed_through_unstable_modules
922- {
923- // Similar to above, but we cannot use `check_stability_allow_unstable` as that would
924- // immediately show the stability error. We just want to know the result and disaplay
925- // our own kind of error.
926- let parents = path. segments . iter ( ) . rev ( ) . skip ( 1 ) ;
927- for path_segment in parents {
928- if let Some ( def_id) = path_segment. res . opt_def_id ( ) {
929- // use `None` for id to prevent deprecation check
930- let eval_result = self . tcx . eval_stability_allow_unstable (
931- def_id,
932- None ,
933- path. span ,
934- None ,
935- if is_unstable_reexport ( self . tcx , id) {
936- AllowUnstable :: Yes
937- } else {
938- AllowUnstable :: No
939- } ,
940- ) ;
941- let is_allowed = matches ! ( eval_result, EvalResult :: Allow ) ;
942- if !is_allowed {
943- // Calculating message for lint involves calling `self.def_path_str`,
944- // which will by default invoke the expensive `visible_parent_map` query.
945- // Skip all that work if the lint is allowed anyway.
946- if self . tcx . lint_level_at_node ( DEPRECATED , id) . 0
947- == lint:: Level :: Allow
948- {
949- return ;
950- }
951- // Show a deprecation message.
952- let def_path =
953- with_no_trimmed_paths ! ( self . tcx. def_path_str( def_id) ) ;
954- let def_kind = self . tcx . def_descr ( def_id) ;
955- let diag = Deprecated {
956- sub : None ,
957- kind : def_kind. to_owned ( ) ,
958- path : def_path,
959- note : Some ( deprecation) ,
960- since_kind : lint:: DeprecatedSinceKind :: InEffect ,
961- } ;
962- self . tcx . emit_node_span_lint (
963- DEPRECATED ,
964- id,
965- method_span. unwrap_or ( path. span ) ,
966- diag,
891+ // Check parent modules stability as well if the item the path refers to is itself
892+ // stable. We only emit errors for unstable path segments if the item is stable
893+ // or allowed because stability is often inherited, so the most common case is that
894+ // both the segments and the item are unstable behind the same feature flag.
895+ //
896+ // We check here rather than in `visit_path_segment` to prevent visiting the last
897+ // path segment twice
898+ //
899+ // We include special cases via #[rustc_allowed_through_unstable_modules] for items
900+ // that were accidentally stabilized through unstable paths before this check was
901+ // added, such as `core::intrinsics::transmute`
902+ let parents = path. segments . iter ( ) . rev ( ) . skip ( 1 ) ;
903+ for path_segment in parents {
904+ if let Some ( def_id) = path_segment. res . opt_def_id ( ) {
905+ match is_allowed_through_unstable_modules {
906+ None => {
907+ // Emit a hard stability error if this path is not stable.
908+
909+ // use `None` for id to prevent deprecation check
910+ self . tcx . check_stability_allow_unstable (
911+ def_id,
912+ None ,
913+ path. span ,
914+ None ,
915+ if is_unstable_reexport ( self . tcx , id) {
916+ AllowUnstable :: Yes
917+ } else {
918+ AllowUnstable :: No
919+ } ,
920+ ) ;
921+ }
922+ Some ( deprecation) => {
923+ // Call the stability check directly so that we can control which
924+ // diagnostic is emitted.
925+ let eval_result = self . tcx . eval_stability_allow_unstable (
926+ def_id,
927+ None ,
928+ path. span ,
929+ None ,
930+ if is_unstable_reexport ( self . tcx , id) {
931+ AllowUnstable :: Yes
932+ } else {
933+ AllowUnstable :: No
934+ } ,
967935 ) ;
936+ let is_allowed = matches ! ( eval_result, EvalResult :: Allow ) ;
937+ if !is_allowed {
938+ // Calculating message for lint involves calling `self.def_path_str`,
939+ // which will by default invoke the expensive `visible_parent_map` query.
940+ // Skip all that work if the lint is allowed anyway.
941+ if self . tcx . lint_level_at_node ( DEPRECATED , id) . 0
942+ == lint:: Level :: Allow
943+ {
944+ return ;
945+ }
946+ // Show a deprecation message.
947+ let def_path =
948+ with_no_trimmed_paths ! ( self . tcx. def_path_str( def_id) ) ;
949+ let def_kind = self . tcx . def_descr ( def_id) ;
950+ let diag = Deprecated {
951+ sub : None ,
952+ kind : def_kind. to_owned ( ) ,
953+ path : def_path,
954+ note : Some ( deprecation) ,
955+ since_kind : lint:: DeprecatedSinceKind :: InEffect ,
956+ } ;
957+ self . tcx . emit_node_span_lint (
958+ DEPRECATED ,
959+ id,
960+ method_span. unwrap_or ( path. span ) ,
961+ diag,
962+ ) ;
963+ }
968964 }
969965 }
970966 }
0 commit comments