11//! Item signature IR definitions
22
3- use std:: ops:: Not as _;
3+ use std:: { cell :: LazyCell , ops:: Not as _} ;
44
55use bitflags:: bitflags;
66use cfg:: { CfgExpr , CfgOptions } ;
@@ -731,29 +731,26 @@ pub struct VariantFields {
731731 pub store : Arc < ExpressionStore > ,
732732 pub shape : FieldsShape ,
733733}
734+
735+ #[ salsa:: tracked]
734736impl VariantFields {
735- #[ inline ]
737+ #[ salsa :: tracked ( returns ( clone ) ) ]
736738 pub ( crate ) fn query (
737739 db : & dyn DefDatabase ,
738740 id : VariantId ,
739741 ) -> ( Arc < Self > , Arc < ExpressionStoreSourceMap > ) {
740- let ( shape, ( fields , store , source_map ) ) = match id {
742+ let ( shape, result ) = match id {
741743 VariantId :: EnumVariantId ( id) => {
742744 let loc = id. lookup ( db) ;
743745 let parent = loc. parent . lookup ( db) ;
744746 let source = loc. source ( db) ;
745747 let shape = adt_shape ( source. value . kind ( ) ) ;
746- let span_map = db. span_map ( source. file_id ) ;
747- let override_visibility = visibility_from_ast (
748- db,
749- source. value . parent_enum ( ) . visibility ( ) ,
750- & mut |range| span_map. span_for_range ( range) . ctx ,
751- ) ;
748+ let enum_vis = Some ( source. value . parent_enum ( ) . visibility ( ) ) ;
752749 let fields = lower_field_list (
753750 db,
754751 parent. container ,
755752 source. map ( |src| src. field_list ( ) ) ,
756- Some ( override_visibility ) ,
753+ enum_vis ,
757754 ) ;
758755 ( shape, fields)
759756 }
@@ -777,10 +774,29 @@ impl VariantFields {
777774 ( FieldsShape :: Record , fields)
778775 }
779776 } ;
777+ match result {
778+ Some ( ( fields, store, source_map) ) => (
779+ Arc :: new ( VariantFields { fields, store : Arc :: new ( store) , shape } ) ,
780+ Arc :: new ( source_map) ,
781+ ) ,
782+ None => (
783+ Arc :: new ( VariantFields {
784+ fields : Arena :: default ( ) ,
785+ store : ExpressionStore :: empty_singleton ( ) ,
786+ shape,
787+ } ) ,
788+ ExpressionStoreSourceMap :: empty_singleton ( ) ,
789+ ) ,
790+ }
791+ }
780792
781- ( Arc :: new ( VariantFields { fields, store : Arc :: new ( store) , shape } ) , Arc :: new ( source_map) )
793+ #[ salsa:: tracked( returns( deref) ) ]
794+ pub ( crate ) fn firewall ( db : & dyn DefDatabase , id : VariantId ) -> Arc < Self > {
795+ Self :: query ( db, id) . 0
782796 }
797+ }
783798
799+ impl VariantFields {
784800 pub fn len ( & self ) -> usize {
785801 self . fields . len ( )
786802 }
@@ -798,31 +814,24 @@ fn lower_field_list(
798814 db : & dyn DefDatabase ,
799815 module : ModuleId ,
800816 fields : InFile < Option < ast:: FieldList > > ,
801- override_visibility : Option < RawVisibility > ,
802- ) -> ( Arena < FieldData > , ExpressionStore , ExpressionStoreSourceMap ) {
817+ override_visibility : Option < Option < ast :: Visibility > > ,
818+ ) -> Option < ( Arena < FieldData > , ExpressionStore , ExpressionStoreSourceMap ) > {
803819 let file_id = fields. file_id ;
804- match fields. value {
805- Some ( ast:: FieldList :: RecordFieldList ( fields) ) => lower_fields (
820+ match fields. value ? {
821+ ast:: FieldList :: RecordFieldList ( fields) => lower_fields (
806822 db,
807823 module,
808824 InFile :: new ( file_id, fields. fields ( ) . map ( |field| ( field. ty ( ) , field) ) ) ,
809825 |_, field| as_name_opt ( field. name ( ) ) ,
810826 override_visibility,
811827 ) ,
812- Some ( ast:: FieldList :: TupleFieldList ( fields) ) => lower_fields (
828+ ast:: FieldList :: TupleFieldList ( fields) => lower_fields (
813829 db,
814830 module,
815831 InFile :: new ( file_id, fields. fields ( ) . map ( |field| ( field. ty ( ) , field) ) ) ,
816832 |idx, _| Name :: new_tuple_field ( idx) ,
817833 override_visibility,
818834 ) ,
819- None => lower_fields (
820- db,
821- module,
822- InFile :: new ( file_id, std:: iter:: empty :: < ( Option < ast:: Type > , ast:: RecordField ) > ( ) ) ,
823- |_, _| Name :: missing ( ) ,
824- None ,
825- ) ,
826835 }
827836}
828837
@@ -831,22 +840,34 @@ fn lower_fields<Field: ast::HasAttrs + ast::HasVisibility>(
831840 module : ModuleId ,
832841 fields : InFile < impl Iterator < Item = ( Option < ast:: Type > , Field ) > > ,
833842 mut field_name : impl FnMut ( usize , & Field ) -> Name ,
834- override_visibility : Option < RawVisibility > ,
835- ) -> ( Arena < FieldData > , ExpressionStore , ExpressionStoreSourceMap ) {
836- let mut arena = Arena :: new ( ) ;
843+ override_visibility : Option < Option < ast:: Visibility > > ,
844+ ) -> Option < ( Arena < FieldData > , ExpressionStore , ExpressionStoreSourceMap ) > {
837845 let cfg_options = module. krate . cfg_options ( db) ;
838846 let mut col = ExprCollector :: new ( db, module, fields. file_id ) ;
847+ let override_visibility = override_visibility. map ( |vis| {
848+ LazyCell :: new ( || {
849+ let span_map = db. span_map ( fields. file_id ) ;
850+ visibility_from_ast ( db, vis, & mut |range| span_map. span_for_range ( range) . ctx )
851+ } )
852+ } ) ;
853+
854+ let mut arena = Arena :: new ( ) ;
839855 let mut idx = 0 ;
856+ let mut has_fields = false ;
840857 for ( ty, field) in fields. value {
858+ has_fields = true ;
841859 match Attrs :: is_cfg_enabled_for ( db, & field, col. span_map ( ) , cfg_options) {
842860 Ok ( ( ) ) => {
843861 let type_ref =
844862 col. lower_type_ref_opt ( ty, & mut ExprCollector :: impl_trait_error_allocator) ;
845- let visibility = override_visibility. clone ( ) . unwrap_or_else ( || {
846- visibility_from_ast ( db, field. visibility ( ) , & mut |range| {
847- col. span_map ( ) . span_for_range ( range) . ctx
848- } )
849- } ) ;
863+ let visibility = override_visibility. as_ref ( ) . map_or_else (
864+ || {
865+ visibility_from_ast ( db, field. visibility ( ) , & mut |range| {
866+ col. span_map ( ) . span_for_range ( range) . ctx
867+ } )
868+ } ,
869+ |it| RawVisibility :: clone ( it) ,
870+ ) ;
850871 let is_unsafe = field
851872 . syntax ( )
852873 . children_with_tokens ( )
@@ -867,9 +888,12 @@ fn lower_fields<Field: ast::HasAttrs + ast::HasVisibility>(
867888 }
868889 }
869890 }
891+ if !has_fields {
892+ return None ;
893+ }
870894 let store = col. store . finish ( ) ;
871895 arena. shrink_to_fit ( ) ;
872- ( arena, store, col. source_map )
896+ Some ( ( arena, store, col. source_map ) )
873897}
874898
875899#[ derive( Debug , PartialEq , Eq ) ]
@@ -948,7 +972,7 @@ impl EnumVariants {
948972 self . variants . iter ( ) . all ( |& ( v, _, _) | {
949973 // The condition check order is slightly modified from rustc
950974 // to improve performance by early returning with relatively fast checks
951- let variant = & db . variant_fields ( v . into ( ) ) ;
975+ let variant = v . fields ( db ) ;
952976 if !variant. fields ( ) . is_empty ( ) {
953977 return false ;
954978 }
0 commit comments