Skip to content

Commit

Permalink
Avoid depending on syn's full feature flag
Browse files Browse the repository at this point in the history
This reduces clean build times by about a second (20%).
  • Loading branch information
meithecatte committed Jun 5, 2024
1 parent e01808b commit f3bb174
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 21 deletions.
6 changes: 5 additions & 1 deletion enumflags_derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ rust-version = "1.56"
[lib]
proc-macro = true

[dependencies.syn]
version = "^2.0"
features = ["parsing", "printing", "derive", "proc-macro"]
default-features = false

[dependencies]
syn = { version = "^2.0", features = ["full"] }
quote = "^1.0"
proc-macro2 = "^1.0"
35 changes: 23 additions & 12 deletions enumflags_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use syn::{
parse::{Parse, ParseStream},
parse_macro_input,
spanned::Spanned,
Expr, Ident, Item, ItemEnum, Token, Variant,
Expr, Ident, DeriveInput, Data, Token, Variant,
};

struct Flag<'a> {
Expand Down Expand Up @@ -58,14 +58,8 @@ pub fn bitflags_internal(
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let Parameters { default } = parse_macro_input!(attr as Parameters);
let mut ast = parse_macro_input!(input as Item);
let output = match ast {
Item::Enum(ref mut item_enum) => gen_enumflags(item_enum, default),
_ => Err(syn::Error::new_spanned(
&ast,
"#[bitflags] requires an enum",
)),
};
let mut ast = parse_macro_input!(input as DeriveInput);
let output = gen_enumflags(&mut ast, default);

output
.unwrap_or_else(|err| {
Expand Down Expand Up @@ -247,17 +241,29 @@ fn check_flag(type_name: &Ident, flag: &Flag, bits: u8) -> Result<Option<TokenSt
}
}

fn gen_enumflags(ast: &mut ItemEnum, default: Vec<Ident>) -> Result<TokenStream, syn::Error> {
fn gen_enumflags(ast: &mut DeriveInput, default: Vec<Ident>) -> Result<TokenStream, syn::Error> {
let ident = &ast.ident;

let span = Span::call_site();

let ast_variants = match &mut ast.data {
Data::Enum(ref mut data) => &mut data.variants,
Data::Struct(data) => {
return Err(syn::Error::new_spanned(&data.struct_token,
"expected enum for #[bitflags], found struct"));
}
Data::Union(data) => {
return Err(syn::Error::new_spanned(&data.union_token,
"expected enum for #[bitflags], found union"));
}
};

let repr = extract_repr(&ast.attrs)?
.ok_or_else(|| syn::Error::new_spanned(ident,
"repr attribute missing. Add #[repr(u64)] or a similar attribute to specify the size of the bitfield."))?;
let bits = type_bits(&repr)?;

let mut variants = collect_flags(ast.variants.iter_mut())?;
let mut variants = collect_flags(ast_variants.iter_mut())?;
let deferred = variants
.iter()
.flat_map(|variant| check_flag(ident, variant, bits).transpose())
Expand All @@ -273,7 +279,12 @@ fn gen_enumflags(ast: &mut ItemEnum, default: Vec<Ident>) -> Result<TokenStream,
}

let std = quote_spanned!(span => ::enumflags2::_internal::core);
let variant_names = ast.variants.iter().map(|v| &v.ident).collect::<Vec<_>>();
let ast_variants = match &ast.data {
Data::Enum(ref data) => &data.variants,
_ => unreachable!(),
};

let variant_names = ast_variants.iter().map(|v| &v.ident).collect::<Vec<_>>();

Ok(quote_spanned! {
span =>
Expand Down
15 changes: 7 additions & 8 deletions test_suite/ui/not_enum.stderr
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
error: #[bitflags] requires an enum
--> $DIR/not_enum.rs:2:1
error: expected enum for #[bitflags], found struct
--> ui/not_enum.rs:3:1
|
2 | / #[derive(Copy, Clone)]
3 | | struct Foo(u16);
| |________________^
3 | struct Foo(u16);
| ^^^^^^

error: #[bitflags] requires an enum
--> $DIR/not_enum.rs:6:1
error: expected one of: `struct`, `enum`, `union`
--> ui/not_enum.rs:6:1
|
6 | const WTF: u8 = 42;
| ^^^^^^^^^^^^^^^^^^^
| ^^^^^

0 comments on commit f3bb174

Please sign in to comment.