|
1 | 1 | use rustc_abi::Align;
|
2 |
| -use rustc_ast::{IntTy, LitIntType, LitKind, MetaItemLit, UintTy}; |
| 2 | +use rustc_ast::{IntTy, LitIntType, LitKind, UintTy}; |
3 | 3 | use rustc_attr_data_structures::{AttributeKind, IntType, ReprAttr};
|
4 |
| -use rustc_span::symbol::Ident; |
5 | 4 | use rustc_span::{Span, Symbol, sym};
|
6 | 5 |
|
7 | 6 | use super::{CombineAttributeGroup, ConvertFn};
|
8 | 7 | use crate::context::AttributeAcceptContext;
|
9 |
| -use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, MetaItemParser}; |
| 8 | +use crate::parser::{ArgParser, MetaItemListParser, MetaItemParser}; |
10 | 9 | use crate::session_diagnostics;
|
11 | 10 | use crate::session_diagnostics::IncorrectReprFormatGenericCause;
|
12 | 11 |
|
@@ -44,251 +43,178 @@ impl CombineAttributeGroup for ReprGroup {
|
44 | 43 | }
|
45 | 44 | }
|
46 | 45 |
|
47 |
| -fn parse_repr<'a, 'b>( |
48 |
| - cx: &AttributeAcceptContext<'_>, |
49 |
| - param: &'a MetaItemParser<'b>, |
50 |
| -) -> Option<ReprAttr> { |
51 |
| - // FIXME(jdonszelmann): invert the parsing here to match on the word first and then the |
52 |
| - // structure. |
53 |
| - let (ident, args) = param.word_or_empty(); |
| 46 | +macro_rules! int_pat { |
| 47 | + () => { |
| 48 | + sym::i8 |
| 49 | + | sym::u8 |
| 50 | + | sym::i16 |
| 51 | + | sym::u16 |
| 52 | + | sym::i32 |
| 53 | + | sym::u32 |
| 54 | + | sym::i64 |
| 55 | + | sym::u64 |
| 56 | + | sym::i128 |
| 57 | + | sym::u128 |
| 58 | + | sym::isize |
| 59 | + | sym::usize |
| 60 | + }; |
| 61 | +} |
54 | 62 |
|
55 |
| - if args.no_args() { |
56 |
| - parse_simple_repr(cx, ident, param.span()) |
57 |
| - } else if let Some(list) = args.list() { |
58 |
| - parse_list_repr(cx, ident, list, param.span()) |
59 |
| - } else if let Some(name_value) = args.name_value() { |
60 |
| - reject_name_value_repr(cx, ident, name_value.value_as_lit(), param.span()); |
61 |
| - None |
62 |
| - } else { |
63 |
| - completely_unknown(cx, param.span()); |
64 |
| - None |
| 63 | +// TODO: inline |
| 64 | +fn int_type_of_word(s: Symbol) -> Option<IntType> { |
| 65 | + use IntType::*; |
| 66 | + |
| 67 | + match s { |
| 68 | + sym::i8 => Some(SignedInt(IntTy::I8)), |
| 69 | + sym::u8 => Some(UnsignedInt(UintTy::U8)), |
| 70 | + sym::i16 => Some(SignedInt(IntTy::I16)), |
| 71 | + sym::u16 => Some(UnsignedInt(UintTy::U16)), |
| 72 | + sym::i32 => Some(SignedInt(IntTy::I32)), |
| 73 | + sym::u32 => Some(UnsignedInt(UintTy::U32)), |
| 74 | + sym::i64 => Some(SignedInt(IntTy::I64)), |
| 75 | + sym::u64 => Some(UnsignedInt(UintTy::U64)), |
| 76 | + sym::i128 => Some(SignedInt(IntTy::I128)), |
| 77 | + sym::u128 => Some(UnsignedInt(UintTy::U128)), |
| 78 | + sym::isize => Some(SignedInt(IntTy::Isize)), |
| 79 | + sym::usize => Some(UnsignedInt(UintTy::Usize)), |
| 80 | + _ => None, |
65 | 81 | }
|
66 | 82 | }
|
67 | 83 |
|
68 |
| -fn parse_list_repr( |
| 84 | +fn parse_repr( |
69 | 85 | cx: &AttributeAcceptContext<'_>,
|
70 |
| - ident: Ident, |
71 |
| - list: &MetaItemListParser<'_>, |
72 |
| - param_span: Span, |
| 86 | + param: &MetaItemParser<'_>, |
73 | 87 | ) -> Option<ReprAttr> {
|
74 |
| - if let Some(single) = list.single() { |
75 |
| - match single { |
76 |
| - MetaItemOrLitParser::MetaItemParser(meta) => { |
77 |
| - reject_not_literal_list(cx, ident, meta.span(), param_span); |
78 |
| - None |
79 |
| - } |
80 |
| - MetaItemOrLitParser::Lit(lit) => parse_singleton_list_repr(cx, ident, lit, param_span), |
81 |
| - } |
82 |
| - } else { |
83 |
| - reject_not_one_element_list(cx, ident, param_span); |
84 |
| - None |
85 |
| - } |
86 |
| -} |
| 88 | + use ReprAttr::*; |
87 | 89 |
|
88 |
| -fn reject_not_one_element_list(cx: &AttributeAcceptContext<'_>, ident: Ident, param_span: Span) { |
89 |
| - match ident.name { |
90 |
| - sym::align => { |
91 |
| - cx.dcx() |
92 |
| - .emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg { span: param_span }); |
93 |
| - } |
94 |
| - sym::packed => { |
95 |
| - cx.dcx().emit_err(session_diagnostics::IncorrectReprFormatPackedOneOrZeroArg { |
96 |
| - span: param_span, |
97 |
| - }); |
98 |
| - } |
99 |
| - sym::Rust | sym::C | sym::simd | sym::transparent => { |
100 |
| - cx.dcx().emit_err(session_diagnostics::InvalidReprHintNoParen { |
101 |
| - span: param_span, |
102 |
| - name: ident.to_string(), |
103 |
| - }); |
104 |
| - } |
105 |
| - other if int_type_of_word(other).is_some() => { |
106 |
| - cx.dcx().emit_err(session_diagnostics::InvalidReprHintNoParen { |
107 |
| - span: param_span, |
108 |
| - name: ident.to_string(), |
109 |
| - }); |
110 |
| - } |
111 |
| - _ => { |
112 |
| - completely_unknown(cx, param_span); |
113 |
| - } |
114 |
| - } |
115 |
| -} |
| 90 | + // FIXME(jdonszelmann): invert the parsing here to match on the word first and then the |
| 91 | + // structure. |
| 92 | + let (ident, args) = param.word_or_empty(); |
116 | 93 |
|
117 |
| -fn reject_not_literal_list( |
118 |
| - cx: &AttributeAcceptContext<'_>, |
119 |
| - ident: Ident, |
120 |
| - meta_span: Span, |
121 |
| - param_span: Span, |
122 |
| -) { |
123 |
| - match ident.name { |
124 |
| - sym::align => { |
125 |
| - cx.dcx().emit_err(session_diagnostics::IncorrectReprFormatExpectInteger { |
126 |
| - span: meta_span, |
127 |
| - }); |
| 94 | + match (ident.name, args) { |
| 95 | + (sym::align, ArgParser::NoArgs) => { |
| 96 | + cx.dcx().emit_err(session_diagnostics::InvalidReprAlignNeedArg { span: ident.span }); |
| 97 | + None |
128 | 98 | }
|
| 99 | + (sym::align, ArgParser::List(l)) => parse_repr_align(cx, l, param.span(), AlignKind::Align), |
129 | 100 |
|
130 |
| - sym::packed => { |
131 |
| - cx.dcx().emit_err(session_diagnostics::IncorrectReprFormatPackedExpectInteger { |
132 |
| - span: meta_span, |
133 |
| - }); |
134 |
| - } |
135 |
| - sym::Rust | sym::C | sym::simd | sym::transparent => { |
136 |
| - cx.dcx().emit_err(session_diagnostics::InvalidReprHintNoParen { |
137 |
| - span: param_span, |
138 |
| - name: ident.to_string(), |
139 |
| - }); |
140 |
| - } |
141 |
| - other if int_type_of_word(other).is_some() => { |
142 |
| - cx.dcx().emit_err(session_diagnostics::InvalidReprHintNoParen { |
143 |
| - span: param_span, |
144 |
| - name: ident.to_string(), |
145 |
| - }); |
146 |
| - } |
147 |
| - _ => { |
148 |
| - completely_unknown(cx, param_span); |
149 |
| - } |
150 |
| - } |
151 |
| -} |
| 101 | + (sym::packed, ArgParser::NoArgs) => Some(ReprPacked(Align::ONE)), |
| 102 | + (sym::packed, ArgParser::List(l)) => parse_repr_align(cx, l, param.span(), AlignKind::Packed), |
152 | 103 |
|
153 |
| -fn reject_name_value_repr( |
154 |
| - cx: &AttributeAcceptContext<'_>, |
155 |
| - ident: Ident, |
156 |
| - value: &MetaItemLit, |
157 |
| - param_span: Span, |
158 |
| -) { |
159 |
| - match ident.name { |
160 |
| - sym::align | sym::packed => { |
| 104 | + (sym::align | sym::packed, ArgParser::NameValue(l)) => { |
161 | 105 | cx.dcx().emit_err(session_diagnostics::IncorrectReprFormatGeneric {
|
162 |
| - span: param_span, |
| 106 | + span: param.span(), |
163 | 107 | // FIXME(jdonszelmann) can just be a string in the diag type
|
164 | 108 | repr_arg: &ident.to_string(),
|
165 | 109 | cause: IncorrectReprFormatGenericCause::from_lit_kind(
|
166 |
| - param_span, |
167 |
| - &value.kind, |
| 110 | + param.span(), |
| 111 | + &l.value_as_lit().kind, |
168 | 112 | ident.name.as_str(),
|
169 | 113 | ),
|
170 | 114 | });
|
| 115 | + None |
171 | 116 | }
|
172 |
| - sym::Rust | sym::C | sym::simd | sym::transparent => { |
173 |
| - cx.dcx().emit_err(session_diagnostics::InvalidReprHintNoValue { |
174 |
| - span: param_span, |
175 |
| - name: ident.to_string(), |
176 |
| - }); |
| 117 | + |
| 118 | + (sym::Rust, ArgParser::NoArgs) => { |
| 119 | + Some(ReprRust) |
177 | 120 | }
|
178 |
| - other if int_type_of_word(other).is_some() => { |
179 |
| - cx.dcx().emit_err(session_diagnostics::InvalidReprHintNoValue { |
180 |
| - span: param_span, |
181 |
| - name: ident.to_string(), |
182 |
| - }); |
| 121 | + (sym::C, ArgParser::NoArgs) => { |
| 122 | + Some(ReprC) |
183 | 123 | }
|
184 |
| - _ => { |
185 |
| - completely_unknown(cx, param_span); |
| 124 | + (sym::simd, ArgParser::NoArgs) => { |
| 125 | + Some(ReprSimd) |
| 126 | + } |
| 127 | + (sym::transparent, ArgParser::NoArgs) => { |
| 128 | + Some(ReprTransparent) |
| 129 | + } |
| 130 | + (i@int_pat!(), ArgParser::NoArgs) => { |
| 131 | + // int_pat!() should make sure it always parses |
| 132 | + Some(ReprInt(int_type_of_word(i).unwrap())) |
186 | 133 | }
|
187 |
| - } |
188 |
| -} |
189 | 134 |
|
190 |
| -fn parse_singleton_list_repr( |
191 |
| - cx: &AttributeAcceptContext<'_>, |
192 |
| - ident: Ident, |
193 |
| - lit: &MetaItemLit, |
194 |
| - param_span: Span, |
195 |
| -) -> Option<ReprAttr> { |
196 |
| - match ident.name { |
197 |
| - sym::align => match parse_alignment(&lit.kind) { |
198 |
| - Ok(literal) => Some(ReprAttr::ReprAlign(literal)), |
199 |
| - Err(message) => { |
200 |
| - cx.dcx().emit_err(session_diagnostics::InvalidReprGeneric { |
201 |
| - span: lit.span, |
202 |
| - repr_arg: ident.to_string(), |
203 |
| - error_part: message, |
204 |
| - }); |
205 |
| - None |
206 |
| - } |
207 |
| - }, |
208 |
| - sym::packed => match parse_alignment(&lit.kind) { |
209 |
| - Ok(literal) => Some(ReprAttr::ReprPacked(literal)), |
210 |
| - Err(message) => { |
211 |
| - cx.dcx().emit_err(session_diagnostics::InvalidReprGeneric { |
212 |
| - span: lit.span, |
213 |
| - repr_arg: ident.to_string(), |
214 |
| - error_part: message, |
215 |
| - }); |
216 |
| - None |
217 |
| - } |
218 |
| - }, |
219 |
| - sym::Rust | sym::C | sym::simd | sym::transparent => { |
220 |
| - cx.dcx().emit_err(session_diagnostics::InvalidReprHintNoParen { |
221 |
| - span: param_span, |
| 135 | + (sym::Rust | sym::C | sym::simd | sym::transparent | int_pat!(), ArgParser::NameValue(_)) => { |
| 136 | + cx.dcx().emit_err(session_diagnostics::InvalidReprHintNoValue { |
| 137 | + span: param.span(), |
222 | 138 | name: ident.to_string(),
|
223 | 139 | });
|
224 | 140 | None
|
225 | 141 | }
|
226 |
| - other if int_type_of_word(other).is_some() => { |
| 142 | + (sym::Rust | sym::C | sym::simd | sym::transparent | int_pat!(), ArgParser::List(_)) => { |
227 | 143 | cx.dcx().emit_err(session_diagnostics::InvalidReprHintNoParen {
|
228 |
| - span: param_span, |
| 144 | + span: param.span(), |
229 | 145 | name: ident.to_string(),
|
230 | 146 | });
|
231 | 147 | None
|
232 | 148 | }
|
| 149 | + |
233 | 150 | _ => {
|
234 |
| - completely_unknown(cx, param_span); |
| 151 | + cx.dcx().emit_err(session_diagnostics::UnrecognizedReprHint { span: param.span() }); |
235 | 152 | None
|
236 | 153 | }
|
237 | 154 | }
|
238 | 155 | }
|
239 | 156 |
|
240 |
| -fn parse_simple_repr( |
241 |
| - cx: &AttributeAcceptContext<'_>, |
242 |
| - ident: Ident, |
243 |
| - param_span: Span, |
244 |
| -) -> Option<ReprAttr> { |
245 |
| - use ReprAttr::*; |
246 |
| - match ident.name { |
247 |
| - sym::Rust => Some(ReprRust), |
248 |
| - sym::C => Some(ReprC), |
249 |
| - sym::packed => Some(ReprPacked(Align::ONE)), |
250 |
| - sym::simd => Some(ReprSimd), |
251 |
| - sym::transparent => Some(ReprTransparent), |
252 |
| - sym::align => { |
253 |
| - cx.dcx().emit_err(session_diagnostics::InvalidReprAlignNeedArg { span: ident.span }); |
254 |
| - None |
255 |
| - } |
256 |
| - other => { |
257 |
| - if let Some(int) = int_type_of_word(other) { |
258 |
| - Some(ReprInt(int)) |
259 |
| - } else { |
260 |
| - completely_unknown(cx, param_span); |
261 |
| - None |
| 157 | +enum AlignKind { |
| 158 | + Packed, |
| 159 | + Align |
| 160 | +} |
| 161 | + |
| 162 | +fn parse_repr_align(cx: &AttributeAcceptContext<'_>, list: &MetaItemListParser<'_>, param_span: Span, align_kind: AlignKind) -> Option<ReprAttr> { |
| 163 | + use AlignKind::*; |
| 164 | + |
| 165 | + let Some(align) = list.single() else { |
| 166 | + match align_kind { |
| 167 | + Packed => { |
| 168 | + cx.dcx().emit_err(session_diagnostics::IncorrectReprFormatPackedOneOrZeroArg { |
| 169 | + span: param_span, |
| 170 | + }); |
| 171 | + }, |
| 172 | + Align => { |
| 173 | + cx.dcx() |
| 174 | + .emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg { span: param_span }); |
262 | 175 | }
|
263 | 176 | }
|
264 |
| - } |
265 |
| -} |
266 | 177 |
|
267 |
| -fn completely_unknown(cx: &AttributeAcceptContext<'_>, param_span: Span) { |
268 |
| - cx.dcx().emit_err(session_diagnostics::UnrecognizedReprHint { span: param_span }); |
269 |
| -} |
| 178 | + return None |
| 179 | + }; |
270 | 180 |
|
271 |
| -fn int_type_of_word(s: Symbol) -> Option<IntType> { |
272 |
| - use IntType::*; |
| 181 | + let Some(lit) = align.lit() else { |
| 182 | + match align_kind { |
| 183 | + Packed => { |
| 184 | + cx.dcx().emit_err(session_diagnostics::IncorrectReprFormatPackedExpectInteger { |
| 185 | + span: align.span(), |
| 186 | + }); |
| 187 | + }, |
| 188 | + Align => { |
| 189 | + cx.dcx().emit_err(session_diagnostics::IncorrectReprFormatExpectInteger { |
| 190 | + span: align.span(), |
| 191 | + }); |
| 192 | + } |
| 193 | + } |
273 | 194 |
|
274 |
| - match s { |
275 |
| - sym::i8 => Some(SignedInt(IntTy::I8)), |
276 |
| - sym::u8 => Some(UnsignedInt(UintTy::U8)), |
277 |
| - sym::i16 => Some(SignedInt(IntTy::I16)), |
278 |
| - sym::u16 => Some(UnsignedInt(UintTy::U16)), |
279 |
| - sym::i32 => Some(SignedInt(IntTy::I32)), |
280 |
| - sym::u32 => Some(UnsignedInt(UintTy::U32)), |
281 |
| - sym::i64 => Some(SignedInt(IntTy::I64)), |
282 |
| - sym::u64 => Some(UnsignedInt(UintTy::U64)), |
283 |
| - sym::i128 => Some(SignedInt(IntTy::I128)), |
284 |
| - sym::u128 => Some(UnsignedInt(UintTy::U128)), |
285 |
| - sym::isize => Some(SignedInt(IntTy::Isize)), |
286 |
| - sym::usize => Some(UnsignedInt(UintTy::Usize)), |
287 |
| - _ => None, |
| 195 | + return None |
| 196 | + }; |
| 197 | + |
| 198 | + match parse_alignment(&lit.kind) { |
| 199 | + Ok(literal) => Some(match align_kind { |
| 200 | + AlignKind::Packed => ReprAttr::ReprPacked(literal), |
| 201 | + AlignKind::Align => ReprAttr::ReprAlign(literal), |
| 202 | + }), |
| 203 | + Err(message) => { |
| 204 | + cx.dcx().emit_err(session_diagnostics::InvalidReprGeneric { |
| 205 | + span: lit.span, |
| 206 | + repr_arg: match align_kind { |
| 207 | + Packed => "packed".to_string(), |
| 208 | + Align => "align".to_string(), |
| 209 | + }, |
| 210 | + error_part: message, |
| 211 | + }); |
| 212 | + None |
| 213 | + } |
288 | 214 | }
|
289 | 215 | }
|
290 | 216 |
|
291 |
| -pub(crate) fn parse_alignment(node: &LitKind) -> Result<Align, &'static str> { |
| 217 | +fn parse_alignment(node: &LitKind) -> Result<Align, &'static str> { |
292 | 218 | if let LitKind::Int(literal, LitIntType::Unsuffixed) = node {
|
293 | 219 | // `Align::from_bytes` accepts 0 as an input, check is_power_of_two() first
|
294 | 220 | if literal.get().is_power_of_two() {
|
|
0 commit comments