Skip to content

Instantly share code, notes, and snippets.

@gakonst
Created February 4, 2026 13:50
Show Gist options
  • Select an option

  • Save gakonst/1fe2acf67987b0fa834e29c318a9c05b to your computer and use it in GitHub Desktop.

Select an option

Save gakonst/1fe2acf67987b0fa834e29c318a9c05b to your computer and use it in GitHub Desktop.
Fix for foundry-rs/foundry#13316 - don't warn on valid vyper config keys
From e914c154a7f6f9f72c3e993f63ef5fa0109128e7 Mon Sep 17 00:00:00 2001
From: Georgios Konstantopoulos <me@gakonst.com>
Date: Wed, 4 Feb 2026 13:49:37 +0000
Subject: [PATCH] fix(config): don't warn on valid vyper config keys
Fixes #13316
The `collect_standalone_section_warnings` function determines allowed
keys by serializing `Config::default()` and extracting keys. However,
`VyperConfig` uses `#[serde(skip_serializing_if = "Option::is_none")]`
on all fields, so when serialized from default (all None values), the
resulting dict is empty - causing all valid vyper keys to be flagged
as unknown.
This adds explicit allowed key handling for the vyper section, similar
to how `compilation_restrictions` and `additional_compiler_profiles`
are handled via `get_array_item_allowed_keys`.
Amp-Thread-ID: https://ampcode.com/threads/T-019c2892-6c42-7603-a8ec-1bb314beb960
Co-authored-by: Amp <amp@ampcode.com>
---
crates/config/src/lib.rs | 10 +++++++
crates/config/src/providers/warnings.rs | 39 +++++++++++++++++++------
2 files changed, 40 insertions(+), 9 deletions(-)
diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs
index d2b957033..62ee79a7f 100644
--- a/crates/config/src/lib.rs
+++ b/crates/config/src/lib.rs
@@ -5240,6 +5240,16 @@ fn test_parse_vyper() {
}
);
+ // Valid vyper keys should not trigger warnings
+ assert!(
+ !config.warnings.iter().any(|w| matches!(
+ w,
+ crate::Warning::UnknownSectionKey { section, .. } if section == "vyper"
+ )),
+ "Valid vyper keys should not trigger warnings, got: {:?}",
+ config.warnings
+ );
+
Ok(())
});
}
diff --git a/crates/config/src/providers/warnings.rs b/crates/config/src/providers/warnings.rs
index d9fe76a00..e3fdb2621 100644
--- a/crates/config/src/providers/warnings.rs
+++ b/crates/config/src/providers/warnings.rs
@@ -24,6 +24,11 @@
const SETTINGS_OVERRIDES_KEYS: &[&str] =
&["name", "via_ir", "evm_version", "optimizer", "optimizer_runs", "bytecode_hash"];
+/// Allowed keys for VyperConfig.
+/// Note: VyperConfig uses `skip_serializing_if = "Option::is_none"` on all fields,
+/// so the default serialized dict is empty. We need to explicitly list allowed keys.
+const VYPER_KEYS: &[&str] = &["optimize", "path", "experimental_codegen"];
+
/// Reserved keys that should not trigger unknown key warnings.
const RESERVED_KEYS: &[&str] = &["extends"];
@@ -182,15 +187,22 @@ fn collect_standalone_section_warnings(
continue;
};
- // Get allowed keys for this section from the default config
- let Some(default_section_value) = default_dict.get(*section_name) else {
- continue;
- };
- let Some(default_section_dict) = default_section_value.as_dict() else {
- continue;
- };
-
- let allowed_keys: BTreeSet<String> = default_section_dict.keys().cloned().collect();
+ // Get allowed keys for this section
+ let allowed_keys: BTreeSet<String> =
+ if let Some(keys) = Self::get_standalone_section_allowed_keys(section_name) {
+ // Use explicit key list for sections with Option fields that use
+ // skip_serializing_if (which results in empty default serialization)
+ keys
+ } else {
+ // Fall back to extracting keys from the default config
+ let Some(default_section_value) = default_dict.get(*section_name) else {
+ continue;
+ };
+ let Some(default_section_dict) = default_section_value.as_dict() else {
+ continue;
+ };
+ default_section_dict.keys().cloned().collect()
+ };
for key in section_dict.keys() {
let is_not_allowed =
@@ -283,6 +295,15 @@ fn get_array_item_allowed_keys(section_name: &str) -> BTreeSet<String> {
_ => BTreeSet::new(),
}
}
+
+ /// Returns allowed keys for standalone sections that have Option fields with
+ /// `skip_serializing_if`, which causes the default serialization to be empty.
+ fn get_standalone_section_allowed_keys(section_name: &str) -> Option<BTreeSet<String>> {
+ match section_name {
+ "vyper" => Some(VYPER_KEYS.iter().map(|s| s.to_string()).collect()),
+ _ => None,
+ }
+ }
}
impl<P: Provider> Provider for WarningsProvider<P> {
--
2.43.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment