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