1
1
//! Defines hir-level representation of structs, enums and unions
2
2
3
- use std:: { num :: NonZeroU32 , sync:: Arc } ;
3
+ use std:: sync:: Arc ;
4
4
5
5
use base_db:: CrateId ;
6
6
use either:: Either ;
@@ -18,6 +18,7 @@ use crate::{
18
18
db:: DefDatabase ,
19
19
intern:: Interned ,
20
20
item_tree:: { AttrOwner , Field , FieldAstId , Fields , ItemTree , ModItem , RawVisibilityId } ,
21
+ layout:: { Align , ReprFlags , ReprOptions } ,
21
22
nameres:: diagnostics:: DefDiagnostic ,
22
23
src:: HasChildSource ,
23
24
src:: HasSource ,
@@ -34,15 +35,15 @@ use cfg::CfgOptions;
34
35
pub struct StructData {
35
36
pub name : Name ,
36
37
pub variant_data : Arc < VariantData > ,
37
- pub repr : Option < ReprData > ,
38
+ pub repr : Option < ReprOptions > ,
38
39
pub visibility : RawVisibility ,
39
40
}
40
41
41
42
#[ derive( Debug , Clone , PartialEq , Eq ) ]
42
43
pub struct EnumData {
43
44
pub name : Name ,
44
45
pub variants : Arena < EnumVariantData > ,
45
- pub repr : Option < ReprData > ,
46
+ pub repr : Option < ReprOptions > ,
46
47
pub visibility : RawVisibility ,
47
48
}
48
49
@@ -67,80 +68,74 @@ pub struct FieldData {
67
68
pub visibility : RawVisibility ,
68
69
}
69
70
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
-
85
71
fn repr_from_value (
86
72
db : & dyn DefDatabase ,
87
73
krate : CrateId ,
88
74
item_tree : & ItemTree ,
89
75
of : AttrOwner ,
90
- ) -> Option < ReprData > {
76
+ ) -> Option < ReprOptions > {
91
77
item_tree. attrs ( db, krate, of) . by_key ( "repr" ) . tt_values ( ) . find_map ( parse_repr_tt)
92
78
}
93
79
94
- fn parse_repr_tt ( tt : & Subtree ) -> Option < ReprData > {
80
+ fn parse_repr_tt ( tt : & Subtree ) -> Option < ReprOptions > {
95
81
match tt. delimiter {
96
82
Some ( Delimiter { kind : DelimiterKind :: Parenthesis , .. } ) => { }
97
83
_ => return None ,
98
84
}
99
85
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 ;
101
90
102
91
let mut tts = tt. token_trees . iter ( ) . peekable ( ) ;
103
92
while let Some ( tt) = tts. next ( ) {
104
93
if let TokenTree :: Leaf ( Leaf :: Ident ( ident) ) = tt {
105
- match & * ident. text {
94
+ flags . insert ( match & * ident. text {
106
95
"packed" => {
107
- data. packed = true ;
108
- if let Some ( TokenTree :: Subtree ( _) ) = tts. peek ( ) {
96
+ let pack = if let Some ( TokenTree :: Subtree ( tt) ) = tts. peek ( ) {
109
97
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 ( )
111
110
}
112
111
"align" => {
113
112
if let Some ( TokenTree :: Subtree ( tt) ) = tts. peek ( ) {
114
113
tts. next ( ) ;
115
114
if let Some ( TokenTree :: Leaf ( Leaf :: Literal ( lit) ) ) = tt. token_trees . first ( ) {
116
115
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) ;
118
118
}
119
119
}
120
120
}
121
+ ReprFlags :: empty ( )
121
122
}
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 ,
130
125
repr => {
131
- let is_c = matches ! ( data. kind, ReprKind :: C ) ;
132
126
if let Some ( builtin) = BuiltinInt :: from_suffix ( repr)
133
127
. map ( Either :: Left )
134
128
. or_else ( || BuiltinUint :: from_suffix ( repr) . map ( Either :: Right ) )
135
129
{
136
- data . kind = ReprKind :: BuiltinInt { builtin, is_c } ;
130
+ int = Some ( builtin) ;
137
131
}
132
+ ReprFlags :: empty ( )
138
133
}
139
- }
134
+ } )
140
135
}
141
136
}
142
137
143
- Some ( data )
138
+ Some ( ReprOptions { int , align : max_align , pack : min_pack , flags } )
144
139
}
145
140
146
141
impl StructData {
@@ -283,7 +278,7 @@ impl EnumData {
283
278
284
279
pub fn variant_body_type ( & self ) -> Either < BuiltinInt , BuiltinUint > {
285
280
match self . repr {
286
- Some ( ReprData { kind : ReprKind :: BuiltinInt { builtin, .. } , .. } ) => builtin,
281
+ Some ( ReprOptions { int : Some ( builtin) , .. } ) => builtin,
287
282
_ => Either :: Left ( BuiltinInt :: Isize ) ,
288
283
}
289
284
}
0 commit comments