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 description:
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"));
+}