Parse repr attribute on enums

This commit is contained in:
David Tolnay 2020-05-10 22:08:20 -07:00
parent 0435a81842
commit ddf69e291b
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
3 changed files with 43 additions and 4 deletions

View File

@ -1,5 +1,7 @@
use crate::syntax::report::Errors;
use crate::syntax::Atom::{self, *};
use crate::syntax::{Derive, Doc};
use proc_macro2::Ident;
use syn::parse::{ParseStream, Parser as _};
use syn::{Attribute, Error, LitStr, Path, Result, Token};
@ -7,6 +9,7 @@ use syn::{Attribute, Error, LitStr, Path, Result, Token};
pub struct Parser<'a> {
pub doc: Option<&'a mut Doc>,
pub derives: Option<&'a mut Vec<Derive>>,
pub repr: Option<&'a mut Option<Atom>>,
}
pub(super) fn parse_doc(cx: &mut Errors, attrs: &[Attribute]) -> Doc {
@ -44,6 +47,16 @@ pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
}
Err(err) => return cx.push(err),
}
} else if attr.path.is_ident("repr") {
match attr.parse_args_with(parse_repr_attribute) {
Ok(attr) => {
if let Some(repr) = &mut parser.repr {
**repr = Some(attr);
continue;
}
}
Err(err) => return cx.push(err),
}
}
return cx.error(attr, "unsupported attribute");
}
@ -69,3 +82,18 @@ fn parse_derive_attribute(input: ParseStream) -> Result<Vec<Derive>> {
})
.collect()
}
fn parse_repr_attribute(input: ParseStream) -> Result<Atom> {
let begin = input.cursor();
let ident: Ident = input.parse()?;
if let Some(atom) = Atom::from(&ident) {
match atom {
U8 | U16 | U32 | U64 | Usize | I8 | I16 | I32 | I64 | Isize => return Ok(atom),
_ => {}
}
}
Err(Error::new_spanned(
begin.token_stream(),
"unrecognized repr",
))
}

View File

@ -20,9 +20,9 @@ pub struct Discriminant {
}
impl DiscriminantSet {
pub fn new() -> Self {
pub fn new(repr: Option<Atom>) -> Self {
DiscriminantSet {
repr: None,
repr,
values: BTreeSet::new(),
previous: None,
}

View File

@ -60,6 +60,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct) -> Result<Api> {
attrs::Parser {
doc: Some(&mut doc),
derives: Some(&mut derives),
..Default::default()
},
);
@ -103,10 +104,20 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum) -> Result<Api> {
));
}
let doc = attrs::parse_doc(cx, &item.attrs);
let mut doc = Doc::new();
let mut repr = None;
attrs::parse(
cx,
&item.attrs,
attrs::Parser {
doc: Some(&mut doc),
repr: Some(&mut repr),
..Default::default()
},
);
let mut variants = Vec::new();
let mut discriminants = DiscriminantSet::new();
let mut discriminants = DiscriminantSet::new(repr);
for variant in item.variants {
match variant.fields {
Fields::Unit => {}