Skip to content

Commit 2a7c7fa

Browse files
authored
Merge pull request #2613 from ahl/fix-untagged-plus-simple
"cannot infer type" from Deserialize derive macro with simple variants and untagged variants
2 parents e302e15 + 94fbc3d commit 2a7c7fa

File tree

2 files changed

+75
-1
lines changed

2 files changed

+75
-1
lines changed

serde_derive/src/de.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1737,7 +1737,6 @@ fn deserialize_untagged_enum_after(
17371737
quote!(__deserializer),
17381738
))
17391739
});
1740-
let attempts = first_attempt.into_iter().chain(attempts);
17411740
// TODO this message could be better by saving the errors from the failed
17421741
// attempts. The heuristic used by TOML was to count the number of fields
17431742
// processed before an error, and use the error that happened after the
@@ -1750,10 +1749,23 @@ fn deserialize_untagged_enum_after(
17501749
);
17511750
let fallthrough_msg = cattrs.expecting().unwrap_or(&fallthrough_msg);
17521751

1752+
// Ignore any error associated with non-untagged deserialization so that we
1753+
// can fall through to the untagged variants. This may be infallible so we
1754+
// need to provide the error type.
1755+
let first_attempt = first_attempt.map(|expr| {
1756+
quote! {
1757+
if let _serde::__private::Result::<_, __D::Error>::Ok(__ok) = (|| {
1758+
#expr
1759+
})() {
1760+
return _serde::__private::Ok(__ok);
1761+
}
1762+
}
1763+
});
17531764
quote_block! {
17541765
let __content = <_serde::__private::de::Content as _serde::Deserialize>::deserialize(__deserializer)?;
17551766
let __deserializer = _serde::__private::de::ContentRefDeserializer::<__D::Error>::new(&__content);
17561767

1768+
#first_attempt
17571769
#(
17581770
if let _serde::__private::Ok(__ok) = #attempts {
17591771
return _serde::__private::Ok(__ok);

test_suite/tests/test_annotations.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2380,6 +2380,68 @@ fn test_partially_untagged_enum_desugared() {
23802380
);
23812381
}
23822382

2383+
#[test]
2384+
fn test_partially_untagged_internally_tagged_enum() {
2385+
#[derive(Serialize, Deserialize, PartialEq, Debug)]
2386+
#[serde(tag = "t")]
2387+
enum Data {
2388+
A,
2389+
B,
2390+
#[serde(untagged)]
2391+
Var(u32),
2392+
}
2393+
2394+
let data = Data::A;
2395+
2396+
assert_de_tokens(
2397+
&data,
2398+
&[
2399+
Token::Map { len: None },
2400+
Token::Str("t"),
2401+
Token::Str("A"),
2402+
Token::MapEnd,
2403+
],
2404+
);
2405+
2406+
let data = Data::Var(42);
2407+
2408+
assert_de_tokens(&data, &[Token::U32(42)]);
2409+
2410+
// TODO test error output
2411+
}
2412+
2413+
#[test]
2414+
fn test_partially_untagged_adjacently_tagged_enum() {
2415+
#[derive(Serialize, Deserialize, PartialEq, Debug)]
2416+
#[serde(tag = "t", content = "c")]
2417+
enum Data {
2418+
A(u32),
2419+
B,
2420+
#[serde(untagged)]
2421+
Var(u32),
2422+
}
2423+
2424+
let data = Data::A(7);
2425+
2426+
assert_de_tokens(
2427+
&data,
2428+
&[
2429+
Token::Map { len: None },
2430+
Token::Str("t"),
2431+
Token::Str("A"),
2432+
Token::Str("c"),
2433+
Token::U32(7),
2434+
Token::MapEnd,
2435+
],
2436+
);
2437+
2438+
let data = Data::Var(42);
2439+
2440+
assert_de_tokens(&data, &[Token::U32(42)]);
2441+
2442+
// TODO test error output
2443+
}
2444+
23832445
#[test]
23842446
fn test_flatten_option() {
23852447
#[derive(Serialize, Deserialize, PartialEq, Debug)]

0 commit comments

Comments
 (0)