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 ( clone ) ) ]
736
738
pub ( crate ) fn query (
737
739
db : & dyn DefDatabase ,
738
740
id : VariantId ,
739
741
) -> ( Arc < Self > , Arc < ExpressionStoreSourceMap > ) {
740
- let ( shape, ( fields , store , source_map ) ) = match id {
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,29 @@ impl VariantFields {
777
774
( FieldsShape :: Record , fields)
778
775
}
779
776
} ;
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
+ }
780
792
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
782
796
}
797
+ }
783
798
799
+ impl VariantFields {
784
800
pub fn len ( & self ) -> usize {
785
801
self . fields . len ( )
786
802
}
@@ -798,31 +814,24 @@ fn lower_field_list(
798
814
db : & dyn DefDatabase ,
799
815
module : ModuleId ,
800
816
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 ) > {
803
819
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 (
806
822
db,
807
823
module,
808
824
InFile :: new ( file_id, fields. fields ( ) . map ( |field| ( field. ty ( ) , field) ) ) ,
809
825
|_, field| as_name_opt ( field. name ( ) ) ,
810
826
override_visibility,
811
827
) ,
812
- Some ( ast:: FieldList :: TupleFieldList ( fields) ) => lower_fields (
828
+ ast:: FieldList :: TupleFieldList ( fields) => lower_fields (
813
829
db,
814
830
module,
815
831
InFile :: new ( file_id, fields. fields ( ) . map ( |field| ( field. ty ( ) , field) ) ) ,
816
832
|idx, _| Name :: new_tuple_field ( idx) ,
817
833
override_visibility,
818
834
) ,
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
835
}
827
836
}
828
837
@@ -831,22 +840,34 @@ fn lower_fields<Field: ast::HasAttrs + ast::HasVisibility>(
831
840
module : ModuleId ,
832
841
fields : InFile < impl Iterator < Item = ( Option < ast:: Type > , Field ) > > ,
833
842
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 ) > {
837
845
let cfg_options = module. krate . cfg_options ( db) ;
838
846
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 ( ) ;
839
855
let mut idx = 0 ;
856
+ let mut has_fields = false ;
840
857
for ( ty, field) in fields. value {
858
+ has_fields = true ;
841
859
match Attrs :: is_cfg_enabled_for ( db, & field, col. span_map ( ) , cfg_options) {
842
860
Ok ( ( ) ) => {
843
861
let type_ref =
844
862
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
+ ) ;
850
871
let is_unsafe = field
851
872
. syntax ( )
852
873
. children_with_tokens ( )
@@ -867,9 +888,12 @@ fn lower_fields<Field: ast::HasAttrs + ast::HasVisibility>(
867
888
}
868
889
}
869
890
}
891
+ if !has_fields {
892
+ return None ;
893
+ }
870
894
let store = col. store . finish ( ) ;
871
895
arena. shrink_to_fit ( ) ;
872
- ( arena, store, col. source_map )
896
+ Some ( ( arena, store, col. source_map ) )
873
897
}
874
898
875
899
#[ derive( Debug , PartialEq , Eq ) ]
@@ -948,7 +972,7 @@ impl EnumVariants {
948
972
self . variants . iter ( ) . all ( |& ( v, _, _) | {
949
973
// The condition check order is slightly modified from rustc
950
974
// to improve performance by early returning with relatively fast checks
951
- let variant = & db . variant_fields ( v . into ( ) ) ;
975
+ let variant = v . fields ( db ) ;
952
976
if !variant. fields ( ) . is_empty ( ) {
953
977
return false ;
954
978
}
0 commit comments