@@ -5,42 +5,36 @@ use chalk_ir::{
55 visit:: { TypeSuperVisitable , TypeVisitable , TypeVisitor } ,
66 DebruijnIndex ,
77} ;
8- use hir_def:: {
9- attr:: Attrs , data:: adt:: VariantData , visibility:: Visibility , AdtId , EnumVariantId , HasModule ,
10- ModuleId , VariantId ,
11- } ;
8+ use hir_def:: { visibility:: Visibility , AdtId , EnumVariantId , HasModule , ModuleId , VariantId } ;
129use rustc_hash:: FxHashSet ;
1310
1411use crate :: {
1512 consteval:: try_const_usize, db:: HirDatabase , Binders , Interner , Substitution , Ty , TyKind ,
1613} ;
1714
15+ // FIXME: Turn this into a query, it can be quite slow
1816/// Checks whether a type is visibly uninhabited from a particular module.
19- pub ( crate ) fn is_ty_uninhabited_from ( ty : & Ty , target_mod : ModuleId , db : & dyn HirDatabase ) -> bool {
17+ pub ( crate ) fn is_ty_uninhabited_from ( db : & dyn HirDatabase , ty : & Ty , target_mod : ModuleId ) -> bool {
18+ let _p = tracing:: span!( tracing:: Level :: INFO , "is_ty_uninhabited_from" , ?ty) ;
2019 let mut uninhabited_from =
2120 UninhabitedFrom { target_mod, db, max_depth : 500 , recursive_ty : FxHashSet :: default ( ) } ;
2221 let inhabitedness = ty. visit_with ( & mut uninhabited_from, DebruijnIndex :: INNERMOST ) ;
2322 inhabitedness == BREAK_VISIBLY_UNINHABITED
2423}
2524
25+ // FIXME: Turn this into a query, it can be quite slow
2626/// Checks whether a variant is visibly uninhabited from a particular module.
2727pub ( crate ) fn is_enum_variant_uninhabited_from (
28+ db : & dyn HirDatabase ,
2829 variant : EnumVariantId ,
2930 subst : & Substitution ,
3031 target_mod : ModuleId ,
31- db : & dyn HirDatabase ,
3232) -> bool {
33- let is_local = variant . module ( db . upcast ( ) ) . krate ( ) == target_mod . krate ( ) ;
33+ let _p = tracing :: span! ( tracing :: Level :: INFO , "is_enum_variant_uninhabited_from" , ) ;
3434
3535 let mut uninhabited_from =
3636 UninhabitedFrom { target_mod, db, max_depth : 500 , recursive_ty : FxHashSet :: default ( ) } ;
37- let inhabitedness = uninhabited_from. visit_variant (
38- variant. into ( ) ,
39- & db. enum_variant_data ( variant) . variant_data ,
40- subst,
41- & db. attrs ( variant. into ( ) ) ,
42- is_local,
43- ) ;
37+ let inhabitedness = uninhabited_from. visit_variant ( variant. into ( ) , subst) ;
4438 inhabitedness == BREAK_VISIBLY_UNINHABITED
4539}
4640
@@ -98,34 +92,18 @@ impl TypeVisitor<Interner> for UninhabitedFrom<'_> {
9892
9993impl UninhabitedFrom < ' _ > {
10094 fn visit_adt ( & mut self , adt : AdtId , subst : & Substitution ) -> ControlFlow < VisiblyUninhabited > {
101- let attrs = self . db . attrs ( adt. into ( ) ) ;
102- let adt_non_exhaustive = attrs. by_key ( "non_exhaustive" ) . exists ( ) ;
103- let is_local = adt. module ( self . db . upcast ( ) ) . krate ( ) == self . target_mod . krate ( ) ;
104- if adt_non_exhaustive && !is_local {
105- return CONTINUE_OPAQUELY_INHABITED ;
106- }
107-
10895 // An ADT is uninhabited iff all its variants uninhabited.
10996 match adt {
11097 // rustc: For now, `union`s are never considered uninhabited.
11198 AdtId :: UnionId ( _) => CONTINUE_OPAQUELY_INHABITED ,
112- AdtId :: StructId ( s) => {
113- let struct_data = self . db . struct_data ( s) ;
114- self . visit_variant ( s. into ( ) , & struct_data. variant_data , subst, & attrs, is_local)
115- }
99+ AdtId :: StructId ( s) => self . visit_variant ( s. into ( ) , subst) ,
116100 AdtId :: EnumId ( e) => {
117101 let enum_data = self . db . enum_data ( e) ;
118102
119103 for & ( variant, _) in enum_data. variants . iter ( ) {
120- let variant_inhabitedness = self . visit_variant (
121- variant. into ( ) ,
122- & self . db . enum_variant_data ( variant) . variant_data ,
123- subst,
124- & self . db . attrs ( variant. into ( ) ) ,
125- is_local,
126- ) ;
104+ let variant_inhabitedness = self . visit_variant ( variant. into ( ) , subst) ;
127105 match variant_inhabitedness {
128- Break ( VisiblyUninhabited ) => continue ,
106+ Break ( VisiblyUninhabited ) => ( ) ,
129107 Continue ( ( ) ) => return CONTINUE_OPAQUELY_INHABITED ,
130108 }
131109 }
@@ -137,34 +115,36 @@ impl UninhabitedFrom<'_> {
137115 fn visit_variant (
138116 & mut self ,
139117 variant : VariantId ,
140- variant_data : & VariantData ,
141118 subst : & Substitution ,
142- attrs : & Attrs ,
143- is_local : bool ,
144119 ) -> ControlFlow < VisiblyUninhabited > {
145- let non_exhaustive_field_list = attrs. by_key ( "non_exhaustive" ) . exists ( ) ;
146- if non_exhaustive_field_list && !is_local {
120+ let is_local = variant. krate ( self . db . upcast ( ) ) == self . target_mod . krate ( ) ;
121+ if !is_local && self . db . attrs ( variant. into ( ) ) . by_key ( "non_exhaustive" ) . exists ( ) {
122+ return CONTINUE_OPAQUELY_INHABITED ;
123+ }
124+
125+ let variant_data = self . db . variant_data ( variant) ;
126+ let fields = variant_data. fields ( ) ;
127+ if fields. is_empty ( ) {
147128 return CONTINUE_OPAQUELY_INHABITED ;
148129 }
149130
150131 let is_enum = matches ! ( variant, VariantId :: EnumVariantId ( ..) ) ;
151132 let field_tys = self . db . field_types ( variant) ;
152- let field_vis = self . db . field_visibilities ( variant) ;
133+ let field_vis = if is_enum { None } else { Some ( self . db . field_visibilities ( variant) ) } ;
153134
154- for ( fid, _) in variant_data . fields ( ) . iter ( ) {
155- self . visit_field ( field_vis[ fid] , & field_tys[ fid] , subst, is_enum ) ?;
135+ for ( fid, _) in fields. iter ( ) {
136+ self . visit_field ( field_vis. as_ref ( ) . map ( |it| it [ fid] ) , & field_tys[ fid] , subst) ?;
156137 }
157138 CONTINUE_OPAQUELY_INHABITED
158139 }
159140
160141 fn visit_field (
161142 & mut self ,
162- vis : Visibility ,
143+ vis : Option < Visibility > ,
163144 ty : & Binders < Ty > ,
164145 subst : & Substitution ,
165- is_enum : bool ,
166146 ) -> ControlFlow < VisiblyUninhabited > {
167- if is_enum || vis . is_visible_from ( self . db . upcast ( ) , self . target_mod ) {
147+ if vis . map_or ( true , |it| it . is_visible_from ( self . db . upcast ( ) , self . target_mod ) ) {
168148 let ty = ty. clone ( ) . substitute ( Interner , subst) ;
169149 ty. visit_with ( self , DebruijnIndex :: INNERMOST )
170150 } else {
0 commit comments