1
1
//! Defines hir-level representation of structs, enums and unions
2
2
3
- use std:: sync:: Arc ;
3
+ use std:: { num :: NonZeroU32 , sync:: Arc } ;
4
4
5
5
use base_db:: CrateId ;
6
6
use either:: Either ;
@@ -14,6 +14,7 @@ use tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree};
14
14
15
15
use crate :: {
16
16
body:: { CfgExpander , LowerCtx } ,
17
+ builtin_type:: { BuiltinInt , BuiltinUint } ,
17
18
db:: DefDatabase ,
18
19
intern:: Interned ,
19
20
item_tree:: { AttrOwner , Field , Fields , ItemTree , ModItem , RawVisibilityId } ,
@@ -31,14 +32,15 @@ use cfg::CfgOptions;
31
32
pub struct StructData {
32
33
pub name : Name ,
33
34
pub variant_data : Arc < VariantData > ,
34
- pub repr : Option < ReprKind > ,
35
+ pub repr : Option < ReprData > ,
35
36
pub visibility : RawVisibility ,
36
37
}
37
38
38
39
#[ derive( Debug , Clone , PartialEq , Eq ) ]
39
40
pub struct EnumData {
40
41
pub name : Name ,
41
42
pub variants : Arena < EnumVariantData > ,
43
+ pub repr : Option < ReprData > ,
42
44
pub visibility : RawVisibility ,
43
45
}
44
46
@@ -63,32 +65,80 @@ pub struct FieldData {
63
65
pub visibility : RawVisibility ,
64
66
}
65
67
66
- #[ derive( Debug , Clone , PartialEq , Eq ) ]
68
+ #[ derive( Copy , Debug , Clone , PartialEq , Eq ) ]
67
69
pub 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 > ,
70
81
}
71
82
72
83
fn repr_from_value (
73
84
db : & dyn DefDatabase ,
74
85
krate : CrateId ,
75
86
item_tree : & ItemTree ,
76
87
of : AttrOwner ,
77
- ) -> Option < ReprKind > {
88
+ ) -> Option < ReprData > {
78
89
item_tree. attrs ( db, krate, of) . by_key ( "repr" ) . tt_values ( ) . find_map ( parse_repr_tt)
79
90
}
80
91
81
- fn parse_repr_tt ( tt : & Subtree ) -> Option < ReprKind > {
92
+ fn parse_repr_tt ( tt : & Subtree ) -> Option < ReprData > {
82
93
match tt. delimiter {
83
94
Some ( Delimiter { kind : DelimiterKind :: Parenthesis , .. } ) => { }
84
95
_ => return None ,
85
96
}
86
97
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
+ }
91
139
}
140
+
141
+ Some ( data)
92
142
}
93
143
94
144
impl StructData {
@@ -108,6 +158,7 @@ impl StructData {
108
158
visibility : item_tree[ strukt. visibility ] . clone ( ) ,
109
159
} )
110
160
}
161
+
111
162
pub ( crate ) fn union_data_query ( db : & dyn DefDatabase , id : UnionId ) -> Arc < StructData > {
112
163
let loc = id. lookup ( db) ;
113
164
let krate = loc. container . krate ;
@@ -133,6 +184,7 @@ impl EnumData {
133
184
let krate = loc. container . krate ;
134
185
let item_tree = loc. id . item_tree ( db) ;
135
186
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 ( ) ) ;
136
188
137
189
let enum_ = & item_tree[ loc. id . value ] ;
138
190
let mut variants = Arena :: new ( ) ;
@@ -158,6 +210,7 @@ impl EnumData {
158
210
Arc :: new ( EnumData {
159
211
name : enum_. name . clone ( ) ,
160
212
variants,
213
+ repr,
161
214
visibility : item_tree[ enum_. visibility ] . clone ( ) ,
162
215
} )
163
216
}
0 commit comments