Repository: TedDriggs/darling (rust)

Issue:
Skipped fields should not be offered as "Did you mean" suggestions
A field marked with `#[darling(skip)]` cannot be set by a meta item. However, its name is still offered as one of the valid alternates when handling unknown fields, which leads to the skipped field name incorrectly being offered.

Pull request:
Don't suggest skipped field names as "did you mean" options
Fixes #268

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d4dde04..55841d8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Changelog
 
+## Unreleased
+
+-  Don't suggest names of skipped fields in derived impls [#268](https://github.com/TedDriggs/darling/issues/268)
+
 ## v0.20.6 (February 14, 2024)
 
 -  Fix some missing syn invisible group handling in `FromMeta` impls [#263](https://github.com/TedDriggs/darling/pull/263)
diff --git a/core/src/codegen/field.rs b/core/src/codegen/field.rs
index 03467f0..c47cf43 100644
--- a/core/src/codegen/field.rs
+++ b/core/src/codegen/field.rs
@@ -29,8 +29,12 @@ pub struct Field<'a> {
 }
 
 impl<'a> Field<'a> {
-    pub fn as_name(&'a self) -> &'a str {
-        &self.name_in_attr
+    pub fn as_name(&'a self) -> Option<&'a str> {
+        if self.skip {
+            None
+        } else {
+            Some(&self.name_in_attr)
+        }
     }
 
     pub fn as_declaration(&'a self) -> Declaration<'a> {
diff --git a/core/src/codegen/variant_data.rs b/core/src/codegen/variant_data.rs
index 7c0063e..7df3345 100644
--- a/core/src/codegen/variant_data.rs
+++ b/core/src/codegen/variant_data.rs
@@ -41,13 +41,12 @@ impl<'a> FieldsGen<'a> {
         let handle_unknown = if self.allow_unknown_fields {
             quote!()
         } else {
+            let mut names = self.fields.iter().filter_map(Field::as_name).peekable();
             // We can't call `unknown_field_with_alts` with an empty slice, or else it fails to
             // infer the type of the slice item.
-            let err_fn = if arms.is_empty() {
+            let err_fn = if names.peek().is_none() {
                 quote!(unknown_field(__other))
             } else {
-                let names = self.fields.as_ref().map(Field::as_name);
-                let names = names.iter();
                 quote!(unknown_field_with_alts(__other, &[#(#names),*]))
             };
 


Test patch:
diff --git a/tests/suggestions.rs b/tests/suggestions.rs
index 5baf76c..862084f 100644
--- a/tests/suggestions.rs
+++ b/tests/suggestions.rs
@@ -9,6 +9,9 @@ use syn::parse_quote;
 struct Lorem {
     ipsum: String,
     dolor: Dolor,
+    // This field is included to make sure that skipped fields aren't suggested.
+    #[darling(skip)]
+    amet: bool,
 }
 
 #[derive(Debug, FromMeta)]
@@ -27,3 +30,15 @@ fn suggest_dolor() {
     assert_eq!(2, result.len());
     assert!(format!("{}", result).contains("Did you mean"));
 }
+
+#[test]
+fn dont_suggest_skipped_field() {
+    let input: syn::DeriveInput = parse_quote! {
+        #[suggest(ipsum = "Hello", dolor(sit), amt)]
+        pub struct Foo;
+    };
+
+    let result = Lorem::from_derive_input(&input).unwrap_err();
+    assert_eq!(1, result.len());
+    assert!(!format!("{}", result).contains("amet"));
+}