Skip to content

Commit 4a6b90b

Browse files
committed
generate a compiler error if cfg attributes disable all variants of enum
1 parent ca1760a commit 4a6b90b

File tree

1 file changed

+34
-2
lines changed

1 file changed

+34
-2
lines changed

pyo3-macros-backend/src/pyclass.rs

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,8 @@ fn impl_simple_enum(
883883
ensure_spanned!(variant.options.constructor.is_none(), variant.options.constructor.span() => "`constructor` can't be used on a simple enum variant");
884884
}
885885

886+
let variant_cfg_check = generate_cfg_check(&variants, cls);
887+
886888
let (default_repr, default_repr_slot) = {
887889
let variants_repr = variants.iter().map(|variant| {
888890
let variant_name = variant.ident;
@@ -897,7 +899,7 @@ fn impl_simple_enum(
897899
});
898900
let mut repr_impl: syn::ImplItemFn = syn::parse_quote! {
899901
fn __pyo3__repr__(&self) -> &'static str {
900-
match self {
902+
match *self {
901903
#(#variants_repr)*
902904
}
903905
}
@@ -920,7 +922,7 @@ fn impl_simple_enum(
920922
});
921923
let mut int_impl: syn::ImplItemFn = syn::parse_quote! {
922924
fn __pyo3__int__(&self) -> #repr_type {
923-
match self {
925+
match *self {
924926
#(#variants_to_int)*
925927
}
926928
}
@@ -955,6 +957,8 @@ fn impl_simple_enum(
955957
.impl_all(ctx)?;
956958

957959
Ok(quote! {
960+
#variant_cfg_check
961+
958962
#pytypeinfo
959963

960964
#pyclass_impls
@@ -2416,6 +2420,34 @@ fn define_inventory_class(inventory_class_name: &syn::Ident, ctx: &Ctx) -> Token
24162420
}
24172421
}
24182422

2423+
fn generate_cfg_check(variants: &[PyClassEnumUnitVariant<'_>], cls: &syn::Ident) -> TokenStream {
2424+
if variants.is_empty() {
2425+
return quote! {};
2426+
}
2427+
2428+
let mut conditions = Vec::new();
2429+
2430+
for variant in variants {
2431+
let cfg_attrs = &variant.cfg_attrs;
2432+
2433+
if cfg_attrs.is_empty() {
2434+
return quote! {};
2435+
}
2436+
2437+
for attr in cfg_attrs {
2438+
if let syn::Meta::List(meta) = &attr.meta {
2439+
let cfg_tokens = &meta.tokens;
2440+
conditions.push(quote! { not(#cfg_tokens) });
2441+
}
2442+
}
2443+
}
2444+
2445+
quote! {
2446+
#[cfg(all(#(#conditions),*))]
2447+
::core::compile_error!(concat!("All variants of enum `", stringify!(#cls), "` have been disabled by cfg attributes"));
2448+
}
2449+
}
2450+
24192451
const UNIQUE_GET: &str = "`get` may only be specified once";
24202452
const UNIQUE_SET: &str = "`set` may only be specified once";
24212453
const UNIQUE_NAME: &str = "`name` may only be specified once";

0 commit comments

Comments
 (0)