diff --git a/cynic-codegen/src/enum_derive/mod.rs b/cynic-codegen/src/enum_derive/mod.rs index e85f0221..445e2e0e 100644 --- a/cynic-codegen/src/enum_derive/mod.rs +++ b/cynic-codegen/src/enum_derive/mod.rs @@ -191,9 +191,11 @@ fn join_variants<'a>( rename_all: RenameAll, enum_span: &Span, ) -> Result)>, TokenStream> { + let mut has_fallback = false; let mut map = BTreeMap::new(); for variant in variants { if *variant.fallback { + has_fallback = true; // We can't join up a fallback as it has no corresponding GQL value. // We handle them separately. continue; @@ -237,7 +239,7 @@ fn join_variants<'a>( _ => (), } } - if !missing_variants.is_empty() { + if !has_fallback && !missing_variants.is_empty() { let missing_variants_string = missing_variants.join(", "); errors.extend( syn::Error::new( @@ -253,7 +255,7 @@ fn join_variants<'a>( Ok(map .into_iter() - .map(|(_, (a, b))| (a.unwrap(), b.unwrap())) + .filter_map(|(_, (a, b))| Some((a?, b.unwrap()))) .collect()) } diff --git a/cynic/tests/enum-fallbacks.rs b/cynic/tests/enum-fallbacks.rs index 8a0dad97..48e73084 100644 --- a/cynic/tests/enum-fallbacks.rs +++ b/cynic/tests/enum-fallbacks.rs @@ -20,6 +20,14 @@ enum PostStateStringFallback { Unknown(String), } +#[derive(Enum, Debug, PartialEq)] +#[cynic(graphql_type = "PostState", schema_path = "tests/test-schema.graphql")] +enum PostStateNonexhaustiveFallback { + Posted, + #[cynic(fallback)] + Unknown(String), +} + #[allow(non_snake_case, non_camel_case_types)] mod schema { cynic::use_schema!("tests/test-schema.graphql"); @@ -46,3 +54,16 @@ fn test_string_fallback() { assert_eq!(val, serde_json::Value::String("BLAH".into())); } + +#[test] +fn test_nonexhaustive_fallback() { + assert_eq!( + PostStateNonexhaustiveFallback::deserialize(json!("DRAFT")).unwrap(), + PostStateNonexhaustiveFallback::Unknown("DRAFT".to_string()) + ); + + let val = + serde_json::to_value(PostStateNonexhaustiveFallback::Unknown("DRAFT".to_string())).unwrap(); + + assert_eq!(val, serde_json::Value::String("DRAFT".into())); +}