Skip to content

Commit 98ce858

Browse files
committed
fix empty and single element tuples
1 parent f39cb0a commit 98ce858

File tree

4 files changed

+48
-10
lines changed

4 files changed

+48
-10
lines changed

pyo3-macros-backend/src/pyclass.rs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,14 +1172,28 @@ fn impl_complex_enum_tuple_variant_match_args(
11721172
variant_cls_type: &syn::Type,
11731173
field_names: &mut Vec<Ident>,
11741174
) -> Result<(MethodAndMethodDef, syn::ImplItemConst)> {
1175-
let args_tp = field_names.iter().map(|_| {
1176-
quote! { &'static str }
1177-
});
1178-
1179-
let match_args_const_impl: syn::ImplItemConst = parse_quote! {
1180-
const __match_args__: ( #(#args_tp),* ) = (
1181-
#(stringify!(#field_names),)*
1182-
);
1175+
let match_args_const_impl: syn::ImplItemConst = match field_names.len() {
1176+
// This covers the case where the tuple variant has no fields (valid Rust)
1177+
0 => parse_quote! {
1178+
const __match_args__: () = ();
1179+
},
1180+
1 => {
1181+
let ident = &field_names[0];
1182+
// We need the trailing comma to make it a tuple
1183+
parse_quote! {
1184+
const __match_args__: (&'static str ,) = (stringify!(#ident) , );
1185+
}
1186+
}
1187+
_ => {
1188+
let args_tp = field_names.iter().map(|_| {
1189+
quote! { &'static str }
1190+
});
1191+
parse_quote! {
1192+
const __match_args__: ( #(#args_tp),* ) = (
1193+
#(stringify!(#field_names),)*
1194+
);
1195+
}
1196+
}
11831197
};
11841198

11851199
let spec = ConstSpec {

pytests/src/enums.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use pyo3::{
88
pub fn enums(m: &Bound<'_, PyModule>) -> PyResult<()> {
99
m.add_class::<SimpleEnum>()?;
1010
m.add_class::<ComplexEnum>()?;
11+
m.add_class::<SimpleTupleEnum>()?;
1112
m.add_class::<TupleEnum>()?;
1213
m.add_class::<MixedComplexEnum>()?;
1314
m.add_wrapped(wrap_pyfunction_bound!(do_simple_stuff))?;
@@ -84,6 +85,12 @@ pub fn do_complex_stuff(thing: &ComplexEnum) -> ComplexEnum {
8485
}
8586
}
8687

88+
#[pyclass]
89+
enum SimpleTupleEnum {
90+
Int(i32),
91+
Str(String),
92+
}
93+
8794
#[pyclass]
8895
pub enum TupleEnum {
8996
Full(i32, f64, bool),

pytests/tests/test_enums_match.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,23 @@ def test_tuple_enum_match_statement(variant: enums.TupleEnum):
9696
assert False
9797

9898

99+
@pytest.mark.parametrize(
100+
"variant",
101+
[
102+
enums.SimpleTupleEnum.Int(42),
103+
enums.SimpleTupleEnum.Str("hello"),
104+
],
105+
)
106+
def test_simple_tuple_enum_match_statement(variant: enums.SimpleTupleEnum):
107+
match variant:
108+
case enums.SimpleTupleEnum.Int(x):
109+
assert x == 42
110+
case enums.SimpleTupleEnum.Str(x):
111+
assert x == "hello"
112+
case _:
113+
assert False
114+
115+
99116
@pytest.mark.parametrize(
100117
"variant",
101118
[

tests/ui/invalid_pyclass_enum.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ error: Unit variant `UnitVariant` is not yet supported in a complex enum
2525
| ^^^^^^^^^^^
2626

2727
error: `constructor` can't be used on a simple enum variant
28-
--> tests/ui/invalid_pyclass_enum.rs:32:12
28+
--> tests/ui/invalid_pyclass_enum.rs:26:12
2929
|
30-
32 | #[pyo3(constructor = (a, b))]
30+
26 | #[pyo3(constructor = (a, b))]
3131
| ^^^^^^^^^^^

0 commit comments

Comments
 (0)