Skip to content

Commit 929ad69

Browse files
committed
rewrite repr parser
1 parent b198946 commit 929ad69

File tree

2 files changed

+129
-203
lines changed

2 files changed

+129
-203
lines changed

compiler/rustc_attr_parsing/src/attributes/repr.rs

+128-202
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
use rustc_abi::Align;
2-
use rustc_ast::{IntTy, LitIntType, LitKind, MetaItemLit, UintTy};
2+
use rustc_ast::{IntTy, LitIntType, LitKind, UintTy};
33
use rustc_attr_data_structures::{AttributeKind, IntType, ReprAttr};
4-
use rustc_span::symbol::Ident;
54
use rustc_span::{Span, Symbol, sym};
65

76
use super::{CombineAttributeGroup, ConvertFn};
87
use crate::context::AttributeAcceptContext;
9-
use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, MetaItemParser};
8+
use crate::parser::{ArgParser, MetaItemListParser, MetaItemParser};
109
use crate::session_diagnostics;
1110
use crate::session_diagnostics::IncorrectReprFormatGenericCause;
1211

@@ -44,251 +43,178 @@ impl CombineAttributeGroup for ReprGroup {
4443
}
4544
}
4645

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+
}
5462

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,
6581
}
6682
}
6783

68-
fn parse_list_repr(
84+
fn parse_repr(
6985
cx: &AttributeAcceptContext<'_>,
70-
ident: Ident,
71-
list: &MetaItemListParser<'_>,
72-
param_span: Span,
86+
param: &MetaItemParser<'_>,
7387
) -> 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::*;
8789

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();
11693

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
12898
}
99+
(sym::align, ArgParser::List(l)) => parse_repr_align(cx, l, param.span(), AlignKind::Align),
129100

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),
152103

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)) => {
161105
cx.dcx().emit_err(session_diagnostics::IncorrectReprFormatGeneric {
162-
span: param_span,
106+
span: param.span(),
163107
// FIXME(jdonszelmann) can just be a string in the diag type
164108
repr_arg: &ident.to_string(),
165109
cause: IncorrectReprFormatGenericCause::from_lit_kind(
166-
param_span,
167-
&value.kind,
110+
param.span(),
111+
&l.value_as_lit().kind,
168112
ident.name.as_str(),
169113
),
170114
});
115+
None
171116
}
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)
177120
}
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)
183123
}
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()))
186133
}
187-
}
188-
}
189134

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(),
222138
name: ident.to_string(),
223139
});
224140
None
225141
}
226-
other if int_type_of_word(other).is_some() => {
142+
(sym::Rust | sym::C | sym::simd | sym::transparent | int_pat!(), ArgParser::List(_)) => {
227143
cx.dcx().emit_err(session_diagnostics::InvalidReprHintNoParen {
228-
span: param_span,
144+
span: param.span(),
229145
name: ident.to_string(),
230146
});
231147
None
232148
}
149+
233150
_ => {
234-
completely_unknown(cx, param_span);
151+
cx.dcx().emit_err(session_diagnostics::UnrecognizedReprHint { span: param.span() });
235152
None
236153
}
237154
}
238155
}
239156

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 });
262175
}
263176
}
264-
}
265-
}
266177

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+
};
270180

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+
}
273194

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+
}
288214
}
289215
}
290216

291-
pub(crate) fn parse_alignment(node: &LitKind) -> Result<Align, &'static str> {
217+
fn parse_alignment(node: &LitKind) -> Result<Align, &'static str> {
292218
if let LitKind::Int(literal, LitIntType::Unsuffixed) = node {
293219
// `Align::from_bytes` accepts 0 as an input, check is_power_of_two() first
294220
if literal.get().is_power_of_two() {

0 commit comments

Comments
 (0)