support enums with more than 256 variants in derive macro (#4370)

* support enums with more than 256 variants in derive macro

This addresses #4361.  Technically, we now support up to 2^32 variants, which is
the maximum for the canonical ABI.  In practice, though, the derived code for
enums with even just 2^16 variants takes a prohibitively long time to compile.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

* simplify `LowerExpander::expand_variant` code

Signed-off-by: Joel Dice <joel.dice@fermyon.com>
This commit is contained in:
Joel Dice
2022-07-05 09:36:43 -06:00
committed by GitHub
parent 7320db98d1
commit 5542c4ef26
6 changed files with 190 additions and 28 deletions

View File

@@ -0,0 +1,15 @@
[package]
name = "component-macro-test"
authors = ["The Wasmtime Project Developers"]
license = "Apache-2.0 WITH LLVM-exception"
version = "0.1.0"
edition = "2021"
publish = false
[lib]
proc-macro = true
[dependencies]
proc-macro2 = "1.0"
quote = "1.0"
syn = { version = "1.0", features = ["full"] }

View File

@@ -0,0 +1,34 @@
use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::parse_macro_input;
#[proc_macro_attribute]
pub fn add_variants(
attr: proc_macro::TokenStream,
item: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
expand_variants(
&parse_macro_input!(attr as syn::LitInt),
parse_macro_input!(item as syn::ItemEnum),
)
.unwrap_or_else(syn::Error::into_compile_error)
.into()
}
fn expand_variants(count: &syn::LitInt, mut ty: syn::ItemEnum) -> syn::Result<TokenStream> {
let count = count
.base10_digits()
.parse::<usize>()
.map_err(|_| syn::Error::new(count.span(), "expected unsigned integer"))?;
ty.variants = (0..count)
.map(|index| syn::Variant {
attrs: Vec::new(),
ident: syn::Ident::new(&format!("V{}", index), Span::call_site()),
fields: syn::Fields::Unit,
discriminant: None,
})
.collect();
Ok(quote!(#ty))
}