11//! Item signature IR definitions
22
3- use std:: { cell:: LazyCell , ops :: Not as _ } ;
3+ use std:: cell:: LazyCell ;
44
55use bitflags:: bitflags;
66use cfg:: { CfgExpr , CfgOptions } ;
@@ -19,8 +19,9 @@ use thin_vec::ThinVec;
1919use triomphe:: Arc ;
2020
2121use crate :: {
22- ConstId , EnumId , EnumVariantId , EnumVariantLoc , ExternBlockId , FunctionId , HasModule , ImplId ,
23- ItemContainerId , ModuleId , StaticId , StructId , TraitId , TypeAliasId , UnionId , VariantId ,
22+ ConstId , EnumId , EnumVariantId , EnumVariantLoc , ExternBlockId , FunctionId , FxIndexMap ,
23+ HasModule , ImplId , ItemContainerId , ModuleId , StaticId , StructId , TraitId , TypeAliasId ,
24+ UnionId , VariantId ,
2425 attrs:: AttrFlags ,
2526 db:: DefDatabase ,
2627 expr_store:: {
@@ -1055,7 +1056,7 @@ pub struct InactiveEnumVariantCode {
10551056
10561057#[ derive( Debug , Clone , PartialEq , Eq ) ]
10571058pub struct EnumVariants {
1058- pub variants : Box < [ ( EnumVariantId , Name , FieldsShape ) ] > ,
1059+ pub variants : FxIndexMap < Name , ( EnumVariantId , FieldsShape ) > ,
10591060}
10601061
10611062#[ salsa:: tracked]
@@ -1064,30 +1065,31 @@ impl EnumVariants {
10641065 pub ( crate ) fn of (
10651066 db : & dyn DefDatabase ,
10661067 e : EnumId ,
1067- ) -> ( EnumVariants , Option < ThinVec < InactiveEnumVariantCode > > ) {
1068+ ) -> ( EnumVariants , ThinVec < InactiveEnumVariantCode > ) {
10681069 let loc = e. lookup ( db) ;
10691070 let source = loc. source ( db) ;
10701071 let ast_id_map = db. ast_id_map ( source. file_id ) ;
10711072
10721073 let mut diagnostics = ThinVec :: new ( ) ;
10731074 let cfg_options = loc. container . krate ( db) . cfg_options ( db) ;
1074- let mut index = 0 ;
10751075 let Some ( variants) = source. value . variant_list ( ) else {
1076- return ( EnumVariants { variants : Box :: default ( ) } , None ) ;
1076+ return ( EnumVariants { variants : FxIndexMap :: default ( ) } , ThinVec :: new ( ) ) ;
10771077 } ;
1078- let variants = variants
1078+ let mut variants = variants
10791079 . variants ( )
10801080 . filter_map ( |variant| {
10811081 let ast_id = ast_id_map. ast_id ( & variant) ;
10821082 match AttrFlags :: is_cfg_enabled_for ( & variant, cfg_options) {
10831083 Ok ( ( ) ) => {
1084- let enum_variant =
1085- EnumVariantLoc { id : source. with_value ( ast_id) , parent : e, index }
1086- . intern ( db) ;
1087- index += 1 ;
10881084 let name = as_name_opt ( variant. name ( ) ) ;
1085+ let enum_variant = EnumVariantLoc {
1086+ id : source. with_value ( ast_id) ,
1087+ parent : e,
1088+ name : name. clone ( ) ,
1089+ }
1090+ . intern ( db) ;
10891091 let shape = adt_shape ( variant. kind ( ) ) ;
1090- Some ( ( enum_variant , name , shape) )
1092+ Some ( ( name , ( enum_variant , shape) ) )
10911093 }
10921094 Err ( cfg) => {
10931095 diagnostics. push ( InactiveEnumVariantCode {
@@ -1099,34 +1101,38 @@ impl EnumVariants {
10991101 }
11001102 }
11011103 } )
1102- . collect ( ) ;
1104+ . collect :: < FxIndexMap < _ , _ > > ( ) ;
1105+ variants. shrink_to_fit ( ) ;
1106+ diagnostics. shrink_to_fit ( ) ;
11031107
1104- ( EnumVariants { variants } , diagnostics. is_empty ( ) . not ( ) . then_some ( diagnostics ) )
1108+ ( EnumVariants { variants } , diagnostics)
11051109 }
11061110}
11071111
11081112impl EnumVariants {
11091113 pub fn variant ( & self , name : & Name ) -> Option < EnumVariantId > {
1110- self . variants . iter ( ) . find_map ( | ( v , n , _) | if n == name { Some ( * v ) } else { None } )
1114+ self . variants . get ( name ) . map ( | & ( id , _) | id )
11111115 }
11121116
11131117 pub fn variant_name_by_id ( & self , variant_id : EnumVariantId ) -> Option < Name > {
11141118 self . variants
11151119 . iter ( )
1116- . find_map ( |( id , name , _) | if * id == variant_id { Some ( name. clone ( ) ) } else { None } )
1120+ . find_map ( |( name , ( id , _) ) | if * id == variant_id { Some ( name. clone ( ) ) } else { None } )
11171121 }
11181122
11191123 // [Adopted from rustc](https://github.com/rust-lang/rust/blob/bd53aa3bf7a24a70d763182303bd75e5fc51a9af/compiler/rustc_middle/src/ty/adt.rs#L446-L448)
11201124 pub fn is_payload_free ( & self , db : & dyn DefDatabase ) -> bool {
1121- self . variants . iter ( ) . all ( |& ( v, _ , _ ) | {
1125+ self . variants . values ( ) . all ( |& ( v, shape ) | {
11221126 // The condition check order is slightly modified from rustc
11231127 // to improve performance by early returning with relatively fast checks
1124- let variant = v. fields ( db) ;
1125- if !variant. fields ( ) . is_empty ( ) {
1126- return false ;
1127- }
1128+
11281129 // The outer if condition is whether this variant has const ctor or not
1129- if !matches ! ( variant. shape, FieldsShape :: Unit ) {
1130+ if !matches ! ( shape, FieldsShape :: Unit ) {
1131+ let variant = v. fields ( db) ;
1132+ if !variant. fields ( ) . is_empty ( ) {
1133+ return false ;
1134+ }
1135+
11301136 let body = Body :: of ( db, v. into ( ) ) ;
11311137 // A variant with explicit discriminant
11321138 if !matches ! ( body[ body. root_expr( ) ] , crate :: hir:: Expr :: Missing ) {
0 commit comments