11//! Defines hir-level representation of structs, enums and unions
22
3- use std:: { num :: NonZeroU32 , sync:: Arc } ;
3+ use std:: sync:: Arc ;
44
55use base_db:: CrateId ;
66use either:: Either ;
@@ -18,6 +18,7 @@ use crate::{
1818 db:: DefDatabase ,
1919 intern:: Interned ,
2020 item_tree:: { AttrOwner , Field , FieldAstId , Fields , ItemTree , ModItem , RawVisibilityId } ,
21+ layout:: { Align , ReprFlags , ReprOptions } ,
2122 nameres:: diagnostics:: DefDiagnostic ,
2223 src:: HasChildSource ,
2324 src:: HasSource ,
@@ -34,15 +35,15 @@ use cfg::CfgOptions;
3435pub struct StructData {
3536 pub name : Name ,
3637 pub variant_data : Arc < VariantData > ,
37- pub repr : Option < ReprData > ,
38+ pub repr : Option < ReprOptions > ,
3839 pub visibility : RawVisibility ,
3940}
4041
4142#[ derive( Debug , Clone , PartialEq , Eq ) ]
4243pub struct EnumData {
4344 pub name : Name ,
4445 pub variants : Arena < EnumVariantData > ,
45- pub repr : Option < ReprData > ,
46+ pub repr : Option < ReprOptions > ,
4647 pub visibility : RawVisibility ,
4748}
4849
@@ -67,80 +68,74 @@ pub struct FieldData {
6768 pub visibility : RawVisibility ,
6869}
6970
70- #[ derive( Copy , Debug , Clone , PartialEq , Eq ) ]
71- pub enum ReprKind {
72- C ,
73- BuiltinInt { builtin : Either < BuiltinInt , BuiltinUint > , is_c : bool } ,
74- Transparent ,
75- Default ,
76- }
77-
78- #[ derive( Copy , Debug , Clone , PartialEq , Eq ) ]
79- pub struct ReprData {
80- pub kind : ReprKind ,
81- pub packed : bool ,
82- pub align : Option < NonZeroU32 > ,
83- }
84-
8571fn repr_from_value (
8672 db : & dyn DefDatabase ,
8773 krate : CrateId ,
8874 item_tree : & ItemTree ,
8975 of : AttrOwner ,
90- ) -> Option < ReprData > {
76+ ) -> Option < ReprOptions > {
9177 item_tree. attrs ( db, krate, of) . by_key ( "repr" ) . tt_values ( ) . find_map ( parse_repr_tt)
9278}
9379
94- fn parse_repr_tt ( tt : & Subtree ) -> Option < ReprData > {
80+ fn parse_repr_tt ( tt : & Subtree ) -> Option < ReprOptions > {
9581 match tt. delimiter {
9682 Some ( Delimiter { kind : DelimiterKind :: Parenthesis , .. } ) => { }
9783 _ => return None ,
9884 }
9985
100- let mut data = ReprData { kind : ReprKind :: Default , packed : false , align : None } ;
86+ let mut flags = ReprFlags :: empty ( ) ;
87+ let mut int = None ;
88+ let mut max_align: Option < Align > = None ;
89+ let mut min_pack: Option < Align > = None ;
10190
10291 let mut tts = tt. token_trees . iter ( ) . peekable ( ) ;
10392 while let Some ( tt) = tts. next ( ) {
10493 if let TokenTree :: Leaf ( Leaf :: Ident ( ident) ) = tt {
105- match & * ident. text {
94+ flags . insert ( match & * ident. text {
10695 "packed" => {
107- data. packed = true ;
108- if let Some ( TokenTree :: Subtree ( _) ) = tts. peek ( ) {
96+ let pack = if let Some ( TokenTree :: Subtree ( tt) ) = tts. peek ( ) {
10997 tts. next ( ) ;
110- }
98+ if let Some ( TokenTree :: Leaf ( Leaf :: Literal ( lit) ) ) = tt. token_trees . first ( ) {
99+ lit. text . parse ( ) . unwrap_or_default ( )
100+ } else {
101+ 0
102+ }
103+ } else {
104+ 0
105+ } ;
106+ let pack = Align :: from_bytes ( pack) . unwrap ( ) ;
107+ min_pack =
108+ Some ( if let Some ( min_pack) = min_pack { min_pack. min ( pack) } else { pack } ) ;
109+ ReprFlags :: empty ( )
111110 }
112111 "align" => {
113112 if let Some ( TokenTree :: Subtree ( tt) ) = tts. peek ( ) {
114113 tts. next ( ) ;
115114 if let Some ( TokenTree :: Leaf ( Leaf :: Literal ( lit) ) ) = tt. token_trees . first ( ) {
116115 if let Ok ( align) = lit. text . parse ( ) {
117- data. align = Some ( align) ;
116+ let align = Align :: from_bytes ( align) . ok ( ) ;
117+ max_align = max_align. max ( align) ;
118118 }
119119 }
120120 }
121+ ReprFlags :: empty ( )
121122 }
122- "C" => {
123- if let ReprKind :: BuiltinInt { is_c, .. } = & mut data. kind {
124- * is_c = true ;
125- } else {
126- data. kind = ReprKind :: C ;
127- }
128- }
129- "transparent" => data. kind = ReprKind :: Transparent ,
123+ "C" => ReprFlags :: IS_C ,
124+ "transparent" => ReprFlags :: IS_TRANSPARENT ,
130125 repr => {
131- let is_c = matches ! ( data. kind, ReprKind :: C ) ;
132126 if let Some ( builtin) = BuiltinInt :: from_suffix ( repr)
133127 . map ( Either :: Left )
134128 . or_else ( || BuiltinUint :: from_suffix ( repr) . map ( Either :: Right ) )
135129 {
136- data . kind = ReprKind :: BuiltinInt { builtin, is_c } ;
130+ int = Some ( builtin) ;
137131 }
132+ ReprFlags :: empty ( )
138133 }
139- }
134+ } )
140135 }
141136 }
142137
143- Some ( data )
138+ Some ( ReprOptions { int , align : max_align , pack : min_pack , flags } )
144139}
145140
146141impl StructData {
@@ -283,7 +278,7 @@ impl EnumData {
283278
284279 pub fn variant_body_type ( & self ) -> Either < BuiltinInt , BuiltinUint > {
285280 match self . repr {
286- Some ( ReprData { kind : ReprKind :: BuiltinInt { builtin, .. } , .. } ) => builtin,
281+ Some ( ReprOptions { int : Some ( builtin) , .. } ) => builtin,
287282 _ => Either :: Left ( BuiltinInt :: Isize ) ,
288283 }
289284 }
0 commit comments