Repository: serde-rs/serde
File: serde_derive/src/internals/attr.rs (Rust)

Code before:
                            if let Some(ser) = ser {
                                match RenameRule::from_str(&ser.value()) {
                                    Ok(rename_rule) => {
                                        rename_all_fields_ser_rule.set(&meta.path, rename_rule);
                                    }
                                    Err(err) => cx.error_spanned_by(ser, err),
                                }
                            }
                            if let Some(de) = de {
                                match RenameRule::from_str(&de.value()) {
                                    Ok(rename_rule) => {
                                        rename_all_fields_de_rule.set(&meta.path, rename_rule);
                                    }
                                    Err(err) => {
                                        if !one_name {
                                            cx.error_spanned_by(de, err);
                                        }
                                    }
                                }
                            }
                        }
                        syn::Data::Struct(syn::DataStruct { struct_token, .. }) => {
                            let msg = "#[serde(rename_all_fields)] can only be used on enums";
                            cx.error_spanned_by(struct_token, msg);
                        }
                        syn::Data::Union(syn::DataUnion { union_token, .. }) => {
                            let msg = "#[serde(rename_all_fields)] can only be used on enums";
                            cx.error_spanned_by(union_token, msg);
                        }
                    }
                } else if meta.path == TRANSPARENT {
                    // #[serde(transparent)]
                    transparent.set_true(meta.path);
                } else if meta.path == DENY_UNKNOWN_FIELDS {
                    // #[serde(deny_unknown_fields)]
                    deny_unknown_fields.set_true(meta.path);
                } else if meta.path == DEFAULT {
                    if meta.input.peek(Token![=]) {
                        // #[serde(default = "...")]
                        if let Some(path) = parse_lit_into_expr_path(cx, DEFAULT, &meta)? {
                            match &item.data {
                                syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
                                    syn::Fields::Named(_) => {
                                        default.set(&meta.path, Default::Path(path));
                                    }
                                    syn::Fields::Unnamed(_) | syn::Fields::Unit => {
                                        let msg = "#[serde(default = \"...\")] can only be used on structs with named fields";
                                        cx.error_spanned_by(fields, msg);
                                    }
                                },
                                syn::Data::Enum(syn::DataEnum { enum_token, .. }) => {

Review comment (suggestion):
Returning a success from the `parse_nested_meta` closure in this case, without having parsed the rest of the `rename_all_fields` attribute, is going to cause bogus "expected ','" errors:

```console
error: #[serde(rename_all_fields)] can only be used on enums
 --> src/main.rs:5:1
  |
5 | struct Struct {}
  | ^^^^^^

error: expected `,`
 --> src/main.rs:4:27
  |
4 | #[serde(rename_all_fields = "asdf")]
  |                           ^
```

The whole attribute needs to be parsed before you validate it.

Code after:
                        syn::Data::Enum(_) => {
                            if let Some(ser) = ser {
                                match RenameRule::from_str(&ser.value()) {
                                    Ok(rename_rule) => {
                                        rename_all_fields_ser_rule.set(&meta.path, rename_rule);
                                    }
                                    Err(err) => cx.error_spanned_by(ser, err),
                                }
                            }
                            if let Some(de) = de {
                                match RenameRule::from_str(&de.value()) {
                                    Ok(rename_rule) => {
                                        rename_all_fields_de_rule.set(&meta.path, rename_rule);
                                    }
                                    Err(err) => {
                                        if !one_name {
                                            cx.error_spanned_by(de, err);
                                        }
                                    }
                                }
                            }
                        }
                        syn::Data::Struct(_) => {
                            let msg = "#[serde(rename_all_fields)] can only be used on enums";
                            cx.error_spanned_by(&meta.path, msg);
                        }
                        syn::Data::Union(_) => {
                            let msg = "#[serde(rename_all_fields)] can only be used on enums";
                            cx.error_spanned_by(&meta.path, msg);
                        }
                    }
                } else if meta.path == TRANSPARENT {
                    // #[serde(transparent)]
                    transparent.set_true(meta.path);
                } else if meta.path == DENY_UNKNOWN_FIELDS {
                    // #[serde(deny_unknown_fields)]
                    deny_unknown_fields.set_true(meta.path);
                } else if meta.path == DEFAULT {
                    if meta.input.peek(Token![=]) {
                        // #[serde(default = "...")]
                        if let Some(path) = parse_lit_into_expr_path(cx, DEFAULT, &meta)? {
                            match &item.data {
                                syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
                                    syn::Fields::Named(_) => {
                                        default.set(&meta.path, Default::Path(path));
                                    }
                                    syn::Fields::Unnamed(_) | syn::Fields::Unit => {
                                        let msg = "#[serde(default = \"...\")] can only be used on structs with named fields";
                                        cx.error_spanned_by(fields, msg);
                                    }
                                },