11//! Defines hir-level representation of structs, enums and unions
22
3- use std:: sync:: Arc ;
3+ use std:: { num :: NonZeroU32 , sync:: Arc } ;
44
55use base_db:: CrateId ;
66use either:: Either ;
@@ -14,6 +14,7 @@ use tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree};
1414
1515use crate :: {
1616 body:: { CfgExpander , LowerCtx } ,
17+ builtin_type:: { BuiltinInt , BuiltinUint } ,
1718 db:: DefDatabase ,
1819 intern:: Interned ,
1920 item_tree:: { AttrOwner , Field , Fields , ItemTree , ModItem , RawVisibilityId } ,
@@ -31,14 +32,15 @@ use cfg::CfgOptions;
3132pub struct StructData {
3233 pub name : Name ,
3334 pub variant_data : Arc < VariantData > ,
34- pub repr : Option < ReprKind > ,
35+ pub repr : Option < ReprData > ,
3536 pub visibility : RawVisibility ,
3637}
3738
3839#[ derive( Debug , Clone , PartialEq , Eq ) ]
3940pub struct EnumData {
4041 pub name : Name ,
4142 pub variants : Arena < EnumVariantData > ,
43+ pub repr : Option < ReprData > ,
4244 pub visibility : RawVisibility ,
4345}
4446
@@ -63,32 +65,80 @@ pub struct FieldData {
6365 pub visibility : RawVisibility ,
6466}
6567
66- #[ derive( Debug , Clone , PartialEq , Eq ) ]
68+ #[ derive( Copy , Debug , Clone , PartialEq , Eq ) ]
6769pub enum ReprKind {
68- Packed ,
69- Other ,
70+ C ,
71+ BuiltinInt { builtin : Either < BuiltinInt , BuiltinUint > , is_c : bool } ,
72+ Transparent ,
73+ Default ,
74+ }
75+
76+ #[ derive( Copy , Debug , Clone , PartialEq , Eq ) ]
77+ pub struct ReprData {
78+ pub kind : ReprKind ,
79+ pub packed : bool ,
80+ pub align : Option < NonZeroU32 > ,
7081}
7182
7283fn repr_from_value (
7384 db : & dyn DefDatabase ,
7485 krate : CrateId ,
7586 item_tree : & ItemTree ,
7687 of : AttrOwner ,
77- ) -> Option < ReprKind > {
88+ ) -> Option < ReprData > {
7889 item_tree. attrs ( db, krate, of) . by_key ( "repr" ) . tt_values ( ) . find_map ( parse_repr_tt)
7990}
8091
81- fn parse_repr_tt ( tt : & Subtree ) -> Option < ReprKind > {
92+ fn parse_repr_tt ( tt : & Subtree ) -> Option < ReprData > {
8293 match tt. delimiter {
8394 Some ( Delimiter { kind : DelimiterKind :: Parenthesis , .. } ) => { }
8495 _ => return None ,
8596 }
8697
87- let mut it = tt. token_trees . iter ( ) ;
88- match it. next ( ) ? {
89- TokenTree :: Leaf ( Leaf :: Ident ( ident) ) if ident. text == "packed" => Some ( ReprKind :: Packed ) ,
90- _ => Some ( ReprKind :: Other ) ,
98+ let mut data = ReprData { kind : ReprKind :: Default , packed : false , align : None } ;
99+
100+ let mut tts = tt. token_trees . iter ( ) . peekable ( ) ;
101+ while let Some ( tt) = tts. next ( ) {
102+ if let TokenTree :: Leaf ( Leaf :: Ident ( ident) ) = tt {
103+ match & * ident. text {
104+ "packed" => {
105+ data. packed = true ;
106+ if let Some ( TokenTree :: Subtree ( _) ) = tts. peek ( ) {
107+ tts. next ( ) ;
108+ }
109+ }
110+ "align" => {
111+ if let Some ( TokenTree :: Subtree ( tt) ) = tts. peek ( ) {
112+ tts. next ( ) ;
113+ if let Some ( TokenTree :: Leaf ( Leaf :: Literal ( lit) ) ) = tt. token_trees . first ( ) {
114+ if let Ok ( align) = lit. text . parse ( ) {
115+ data. align = Some ( align) ;
116+ }
117+ }
118+ }
119+ }
120+ "C" => {
121+ if let ReprKind :: BuiltinInt { is_c, .. } = & mut data. kind {
122+ * is_c = true ;
123+ } else {
124+ data. kind = ReprKind :: C ;
125+ }
126+ }
127+ "transparent" => data. kind = ReprKind :: Transparent ,
128+ repr => {
129+ let is_c = matches ! ( data. kind, ReprKind :: C ) ;
130+ if let Some ( builtin) = BuiltinInt :: from_suffix ( repr)
131+ . map ( Either :: Left )
132+ . or_else ( || BuiltinUint :: from_suffix ( repr) . map ( Either :: Right ) )
133+ {
134+ data. kind = ReprKind :: BuiltinInt { builtin, is_c } ;
135+ }
136+ }
137+ }
138+ }
91139 }
140+
141+ Some ( data)
92142}
93143
94144impl StructData {
@@ -108,6 +158,7 @@ impl StructData {
108158 visibility : item_tree[ strukt. visibility ] . clone ( ) ,
109159 } )
110160 }
161+
111162 pub ( crate ) fn union_data_query ( db : & dyn DefDatabase , id : UnionId ) -> Arc < StructData > {
112163 let loc = id. lookup ( db) ;
113164 let krate = loc. container . krate ;
@@ -133,6 +184,7 @@ impl EnumData {
133184 let krate = loc. container . krate ;
134185 let item_tree = loc. id . item_tree ( db) ;
135186 let cfg_options = db. crate_graph ( ) [ krate] . cfg_options . clone ( ) ;
187+ let repr = repr_from_value ( db, krate, & item_tree, ModItem :: from ( loc. id . value ) . into ( ) ) ;
136188
137189 let enum_ = & item_tree[ loc. id . value ] ;
138190 let mut variants = Arena :: new ( ) ;
@@ -158,6 +210,7 @@ impl EnumData {
158210 Arc :: new ( EnumData {
159211 name : enum_. name . clone ( ) ,
160212 variants,
213+ repr,
161214 visibility : item_tree[ enum_. visibility ] . clone ( ) ,
162215 } )
163216 }
0 commit comments