diff --git a/confik-macros/src/lib.rs b/confik-macros/src/lib.rs index d85e707..c84fcc8 100644 --- a/confik-macros/src/lib.rs +++ b/confik-macros/src/lib.rs @@ -267,8 +267,13 @@ impl VariantImplementer { let string = ident.to_string(); + // A selected variant counts as data, even if it has no fields. quote_spanned! {var_impl.span() => - Self::#ident #bracketed_extract_us_fields => false #( | #contains_non_secret_data.map_err(|err| err.prepend(#string))? )* + Self::#ident #bracketed_extract_us_fields => { + #( #contains_non_secret_data.map_err(|err| err.prepend(#string))?; )* + + true + } } } } diff --git a/confik/CHANGELOG.md b/confik/CHANGELOG.md index cc28f73..eebe89d 100644 --- a/confik/CHANGELOG.md +++ b/confik/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- Preserve explicitly selected enum unit variants. +- Reject explicitly selected enum variants in `#[confik(secret)]` fields when the source does not allow secrets. - Upgrade `syn` dependency to `3`. - Minimum supported Rust version (MSRV) is now 1.88. diff --git a/confik/tests/defaulting_containers/mod.rs b/confik/tests/defaulting_containers/mod.rs index 8ae1053..740f977 100644 --- a/confik/tests/defaulting_containers/mod.rs +++ b/confik/tests/defaulting_containers/mod.rs @@ -69,6 +69,29 @@ mod struct_default_merge { } } +#[cfg(feature = "toml")] +mod enum_defaults { + use confik::{Configuration, TomlSource}; + + use crate::TargetEnum; + + #[test] + fn unit_enum_variant_overrides_field_default() { + #[derive(Configuration)] + struct Config { + #[confik(default = TargetEnum::First)] + value: TargetEnum, + } + + let config = Config::builder() + .override_with(TomlSource::new(r#"value = "Second""#)) + .try_build() + .expect("TOML deserialization should succeed"); + + assert_eq!(config.value, TargetEnum::Second); + } +} + #[derive(Debug, Configuration, PartialEq, Eq, Default)] struct Config { #[confik(default = 0)] diff --git a/confik/tests/secret/mod.rs b/confik/tests/secret/mod.rs index 2c5ff6a..09d2316 100644 --- a/confik/tests/secret/mod.rs +++ b/confik/tests/secret/mod.rs @@ -161,6 +161,30 @@ mod toml { ); } + #[test] + fn unit_enum_variant_rejected_from_non_secret_source() { + use confik::Error; + + use crate::TargetEnum; + + #[derive(Configuration)] + struct Config { + #[confik(secret)] + value: TargetEnum, + } + + let err = Config::builder() + .override_with(TomlSource::new(r#"value = "Second""#)) + .try_build() + .map(|config| config.value) + .expect_err("TOML must reject a secret unit enum variant"); + + assert_matches!( + err, + Error::UnexpectedSecret(path, _) if path.to_string().contains("`value`") + ); + } + /// This functions and all tests using are to catch the issue in FUT-5298 /// in which depending on ordering a non-secret `Source` may not be caught fn check_secret_error_seq_propagation(expected_path: &str)