1
1
//! Item signature IR definitions
2
2
3
- use std:: ops:: Not as _;
3
+ use std:: { cell :: LazyCell , ops:: Not as _} ;
4
4
5
5
use bitflags:: bitflags;
6
6
use cfg:: { CfgExpr , CfgOptions } ;
@@ -731,29 +731,26 @@ pub struct VariantFields {
731
731
pub store : Arc < ExpressionStore > ,
732
732
pub shape : FieldsShape ,
733
733
}
734
+
735
+ #[ salsa:: tracked]
734
736
impl VariantFields {
735
- #[ inline ]
737
+ #[ salsa :: tracked ( returns ( ref ) ) ]
736
738
pub ( crate ) fn query (
737
739
db : & dyn DefDatabase ,
738
740
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 {
741
743
VariantId :: EnumVariantId ( id) => {
742
744
let loc = id. lookup ( db) ;
743
745
let parent = loc. parent . lookup ( db) ;
744
746
let source = loc. source ( db) ;
745
747
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 ( ) ) ;
752
749
let fields = lower_field_list (
753
750
db,
754
751
parent. container ,
755
752
source. map ( |src| src. field_list ( ) ) ,
756
- Some ( override_visibility ) ,
753
+ enum_vis ,
757
754
) ;
758
755
( shape, fields)
759
756
}
@@ -777,10 +774,23 @@ impl VariantFields {
777
774
( FieldsShape :: Record , fields)
778
775
}
779
776
} ;
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
+ }
782
790
}
791
+ }
783
792
793
+ impl VariantFields {
784
794
pub fn len ( & self ) -> usize {
785
795
self . fields . len ( )
786
796
}
@@ -798,31 +808,24 @@ fn lower_field_list(
798
808
db : & dyn DefDatabase ,
799
809
module : ModuleId ,
800
810
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 ) > {
803
813
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 (
806
816
db,
807
817
module,
808
818
InFile :: new ( file_id, fields. fields ( ) . map ( |field| ( field. ty ( ) , field) ) ) ,
809
819
|_, field| as_name_opt ( field. name ( ) ) ,
810
820
override_visibility,
811
821
) ,
812
- Some ( ast:: FieldList :: TupleFieldList ( fields) ) => lower_fields (
822
+ ast:: FieldList :: TupleFieldList ( fields) => lower_fields (
813
823
db,
814
824
module,
815
825
InFile :: new ( file_id, fields. fields ( ) . map ( |field| ( field. ty ( ) , field) ) ) ,
816
826
|idx, _| Name :: new_tuple_field ( idx) ,
817
827
override_visibility,
818
828
) ,
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
- ) ,
826
829
}
827
830
}
828
831
@@ -831,22 +834,34 @@ fn lower_fields<Field: ast::HasAttrs + ast::HasVisibility>(
831
834
module : ModuleId ,
832
835
fields : InFile < impl Iterator < Item = ( Option < ast:: Type > , Field ) > > ,
833
836
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 ) > {
837
839
let cfg_options = module. krate . cfg_options ( db) ;
838
840
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 ( ) ;
839
849
let mut idx = 0 ;
850
+ let mut has_fields = false ;
840
851
for ( ty, field) in fields. value {
852
+ has_fields = true ;
841
853
match Attrs :: is_cfg_enabled_for ( db, & field, col. span_map ( ) , cfg_options) {
842
854
Ok ( ( ) ) => {
843
855
let type_ref =
844
856
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
+ ) ;
850
865
let is_unsafe = field
851
866
. syntax ( )
852
867
. children_with_tokens ( )
@@ -867,9 +882,12 @@ fn lower_fields<Field: ast::HasAttrs + ast::HasVisibility>(
867
882
}
868
883
}
869
884
}
885
+ if !has_fields {
886
+ return None ;
887
+ }
870
888
let store = col. store . finish ( ) ;
871
889
arena. shrink_to_fit ( ) ;
872
- ( arena, store, col. source_map )
890
+ Some ( ( arena, store, col. source_map ) )
873
891
}
874
892
875
893
#[ derive( Debug , PartialEq , Eq ) ]
@@ -948,7 +966,7 @@ impl EnumVariants {
948
966
self . variants . iter ( ) . all ( |& ( v, _, _) | {
949
967
// The condition check order is slightly modified from rustc
950
968
// to improve performance by early returning with relatively fast checks
951
- let variant = & db . variant_fields ( v . into ( ) ) ;
969
+ let variant = v . fields ( db ) ;
952
970
if !variant. fields ( ) . is_empty ( ) {
953
971
return false ;
954
972
}
0 commit comments