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 ( ref ) ) ]
736738 pub ( crate ) fn query (
737739 db : & dyn DefDatabase ,
738740 id : VariantId ,
739- ) -> ( Arc < Self > , Arc < ExpressionStoreSourceMap > ) {
740- let ( shape, ( fields , store , source_map ) ) = match id {
741+ ) -> ( Self , Arc < ExpressionStoreSourceMap > ) {
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,23 @@ impl VariantFields {
777774 ( FieldsShape :: Record , fields)
778775 }
779776 } ;
780-
781- ( Arc :: new ( VariantFields { fields, store : Arc :: new ( store) , shape } ) , Arc :: new ( source_map) )
777+ match result {
778+ Some ( ( fields, store, source_map) ) => {
779+ ( VariantFields { fields, store : Arc :: new ( store) , shape } , Arc :: new ( source_map) )
780+ }
781+ None => (
782+ VariantFields {
783+ fields : Arena :: default ( ) ,
784+ store : ExpressionStore :: empty_singleton ( ) ,
785+ shape,
786+ } ,
787+ ExpressionStoreSourceMap :: empty_singleton ( ) ,
788+ ) ,
789+ }
782790 }
791+ }
783792
793+ impl VariantFields {
784794 pub fn len ( & self ) -> usize {
785795 self . fields . len ( )
786796 }
@@ -798,31 +808,24 @@ fn lower_field_list(
798808 db : & dyn DefDatabase ,
799809 module : ModuleId ,
800810 fields : InFile < Option < ast:: FieldList > > ,
801- override_visibility : Option < RawVisibility > ,
802- ) -> ( Arena < FieldData > , ExpressionStore , ExpressionStoreSourceMap ) {
811+ override_visibility : Option < Option < ast :: Visibility > > ,
812+ ) -> Option < ( Arena < FieldData > , ExpressionStore , ExpressionStoreSourceMap ) > {
803813 let file_id = fields. file_id ;
804- match fields. value {
805- Some ( ast:: FieldList :: RecordFieldList ( fields) ) => lower_fields (
814+ match fields. value ? {
815+ ast:: FieldList :: RecordFieldList ( fields) => lower_fields (
806816 db,
807817 module,
808818 InFile :: new ( file_id, fields. fields ( ) . map ( |field| ( field. ty ( ) , field) ) ) ,
809819 |_, field| as_name_opt ( field. name ( ) ) ,
810820 override_visibility,
811821 ) ,
812- Some ( ast:: FieldList :: TupleFieldList ( fields) ) => lower_fields (
822+ ast:: FieldList :: TupleFieldList ( fields) => lower_fields (
813823 db,
814824 module,
815825 InFile :: new ( file_id, fields. fields ( ) . map ( |field| ( field. ty ( ) , field) ) ) ,
816826 |idx, _| Name :: new_tuple_field ( idx) ,
817827 override_visibility,
818828 ) ,
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- ) ,
826829 }
827830}
828831
@@ -831,22 +834,34 @@ fn lower_fields<Field: ast::HasAttrs + ast::HasVisibility>(
831834 module : ModuleId ,
832835 fields : InFile < impl Iterator < Item = ( Option < ast:: Type > , Field ) > > ,
833836 mut field_name : impl FnMut ( usize , & Field ) -> Name ,
834- override_visibility : Option < RawVisibility > ,
835- ) -> ( Arena < FieldData > , ExpressionStore , ExpressionStoreSourceMap ) {
836- let mut arena = Arena :: new ( ) ;
837+ override_visibility : Option < Option < ast:: Visibility > > ,
838+ ) -> Option < ( Arena < FieldData > , ExpressionStore , ExpressionStoreSourceMap ) > {
837839 let cfg_options = module. krate . cfg_options ( db) ;
838840 let mut col = ExprCollector :: new ( db, module, fields. file_id ) ;
841+ let override_visibility = override_visibility. map ( |vis| {
842+ LazyCell :: new ( || {
843+ let span_map = db. span_map ( fields. file_id ) ;
844+ visibility_from_ast ( db, vis, & mut |range| span_map. span_for_range ( range) . ctx )
845+ } )
846+ } ) ;
847+
848+ let mut arena = Arena :: new ( ) ;
839849 let mut idx = 0 ;
850+ let mut has_fields = false ;
840851 for ( ty, field) in fields. value {
852+ has_fields = true ;
841853 match Attrs :: is_cfg_enabled_for ( db, & field, col. span_map ( ) , cfg_options) {
842854 Ok ( ( ) ) => {
843855 let type_ref =
844856 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- } ) ;
857+ let visibility = override_visibility. as_ref ( ) . map_or_else (
858+ || {
859+ visibility_from_ast ( db, field. visibility ( ) , & mut |range| {
860+ col. span_map ( ) . span_for_range ( range) . ctx
861+ } )
862+ } ,
863+ |it| RawVisibility :: clone ( it) ,
864+ ) ;
850865 let is_unsafe = field
851866 . syntax ( )
852867 . children_with_tokens ( )
@@ -867,9 +882,12 @@ fn lower_fields<Field: ast::HasAttrs + ast::HasVisibility>(
867882 }
868883 }
869884 }
885+ if !has_fields {
886+ return None ;
887+ }
870888 let store = col. store . finish ( ) ;
871889 arena. shrink_to_fit ( ) ;
872- ( arena, store, col. source_map )
890+ Some ( ( arena, store, col. source_map ) )
873891}
874892
875893#[ derive( Debug , PartialEq , Eq ) ]
@@ -948,7 +966,7 @@ impl EnumVariants {
948966 self . variants . iter ( ) . all ( |& ( v, _, _) | {
949967 // The condition check order is slightly modified from rustc
950968 // to improve performance by early returning with relatively fast checks
951- let variant = & db . variant_fields ( v . into ( ) ) ;
969+ let variant = v . fields ( db ) ;
952970 if !variant. fields ( ) . is_empty ( ) {
953971 return false ;
954972 }
0 commit comments