4646use std:: assert_matches;
4747
4848use rustc_data_structures:: fx:: FxHashSet ;
49+ use rustc_hir:: def:: DefKind ;
4950use rustc_span:: def_id:: LocalModId ;
5051use rustc_type_ir:: TyKind :: * ;
5152use tracing:: instrument;
@@ -69,47 +70,53 @@ pub(crate) fn provide(providers: &mut Providers) {
6970/// Returns an `InhabitedPredicate` that is generic over type parameters and
7071/// requires calling [`InhabitedPredicate::instantiate`]
7172fn inhabited_predicate_adt ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> InhabitedPredicate < ' _ > {
72- if let Some ( def_id) = def_id. as_local ( ) {
73- tcx. ensure_ok ( ) . check_representability ( def_id) ;
73+ match tcx. def_kind ( def_id) {
74+ DefKind :: Enum => {
75+ if let Some ( def_id) = def_id. as_local ( ) {
76+ tcx. ensure_ok ( ) . check_representability ( def_id) ;
77+ }
78+ let adt = tcx. adt_def ( def_id) ;
79+ InhabitedPredicate :: any (
80+ tcx,
81+ adt. variants ( ) . iter ( ) . map ( |v| tcx. inhabited_predicate_adt ( v. def_id ) ) ,
82+ )
83+ }
84+ DefKind :: Struct => {
85+ if let Some ( def_id) = def_id. as_local ( ) {
86+ tcx. ensure_ok ( ) . check_representability ( def_id) ;
87+ }
88+ let adt = tcx. adt_def ( def_id) ;
89+ variant_inhabited_predicate ( tcx, adt. non_enum_variant ( ) )
90+ }
91+ DefKind :: Variant => {
92+ let adt = tcx. adt_def ( tcx. parent ( def_id) ) ;
93+ let variant = adt. variant_with_id ( def_id) ;
94+ variant_inhabited_predicate ( tcx, variant)
95+ }
96+ def_kind => bug ! ( "unexpected DefKind: {def_kind:?}" ) ,
7497 }
98+ }
7599
76- let adt = tcx. adt_def ( def_id) ;
77- InhabitedPredicate :: any (
100+ fn variant_inhabited_predicate < ' tcx > (
101+ tcx : TyCtxt < ' tcx > ,
102+ variant : & VariantDef ,
103+ ) -> InhabitedPredicate < ' tcx > {
104+ InhabitedPredicate :: all (
78105 tcx,
79- adt. variants ( ) . iter ( ) . map ( |variant| variant. inhabited_predicate ( tcx, adt) ) ,
106+ variant. fields . iter ( ) . map ( |field| {
107+ let pred = tcx
108+ . type_of ( field. did )
109+ . instantiate_identity ( )
110+ . skip_norm_wip ( )
111+ . inhabited_predicate ( tcx) ;
112+ match field. vis {
113+ Visibility :: Public => pred,
114+ Visibility :: Restricted ( from) => InhabitedPredicate :: NotInModule ( from) . or ( tcx, pred) ,
115+ }
116+ } ) ,
80117 )
81118}
82119
83- impl < ' tcx > VariantDef {
84- /// Calculates the forest of `DefId`s from which this variant is visibly uninhabited.
85- pub fn inhabited_predicate (
86- & self ,
87- tcx : TyCtxt < ' tcx > ,
88- adt : ty:: AdtDef < ' _ > ,
89- ) -> InhabitedPredicate < ' tcx > {
90- debug_assert ! ( !adt. is_union( ) ) ;
91- InhabitedPredicate :: all (
92- tcx,
93- self . fields . iter ( ) . map ( |field| {
94- let pred = tcx
95- . type_of ( field. did )
96- . instantiate_identity ( )
97- . skip_norm_wip ( )
98- . inhabited_predicate ( tcx) ;
99- if adt. is_enum ( ) {
100- return pred;
101- }
102- match field. vis {
103- Visibility :: Public => pred,
104- Visibility :: Restricted ( from) => {
105- InhabitedPredicate :: NotInModule ( from) . or ( tcx, pred)
106- }
107- }
108- } ) ,
109- )
110- }
111- }
112-
113120impl < ' tcx > Ty < ' tcx > {
114121 #[ instrument( level = "debug" , skip( tcx) , ret) ]
115122 pub fn inhabited_predicate ( self , tcx : TyCtxt < ' tcx > ) -> InhabitedPredicate < ' tcx > {
0 commit comments