{"id":"2c8f18f70333fa6f","repo":"rust-lang/rust","slug":"error-parsing-stable-hash","errorCode":null,"errorMessage":"error parsing stable_hash","messagePattern":"error parsing stable_hash","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/rustc_macros/src/stable_hash.rs","lineNumber":34,"sourceCode":"        let mut any_attr = false;\n        let _ = attr.parse_nested_meta(|nested| {\n            if nested.path.is_ident(\"ignore\") {\n                attrs.ignore = true;\n                any_attr = true;\n            }\n            if nested.path.is_ident(\"project\") {\n                let _ = nested.parse_nested_meta(|meta| {\n                    if attrs.project.is_none() {\n                        attrs.project = meta.path.get_ident().cloned();\n                    }\n                    any_attr = true;\n                    Ok(())\n                });\n            }\n            Ok(())\n        });\n        if !any_attr {\n            panic!(\"error parsing stable_hash\");\n        }\n    }\n    attrs\n}\n\npub(crate) fn stable_hash_derive(s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {\n    stable_hash_derive_with_mode(s, StableHashMode::Normal)\n}\n\npub(crate) fn stable_hash_no_context_derive(\n    s: synstructure::Structure<'_>,\n) -> proc_macro2::TokenStream {\n    stable_hash_derive_with_mode(s, StableHashMode::NoContext)\n}\n\nenum StableHashMode {\n    // Do a normal derive, where any generic type parameter gets a `StableHash` bound.\n    // For example, in `struct Abc<T, U>(T, U)` the added bounds are `T: StableHash` and","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_macros/src/stable_hash.rs#L16-L52","documentation":"`parse_attributes` walks `#[stable_hash(...)]` field attributes and sets `any_attr` only when it recognizes `ignore` or `project(...)`. If the attribute is present but contains neither recognized key (or is malformed), `any_attr` stays false and the macro panics with \"error parsing stable_hash\". This is the derive's way of refusing to silently ignore a typo'd attribute.","triggerScenarios":"Writing `#[stable_hash]` with no body, `#[stable_hash(foo)]`, `#[stable_hash(project)]` without a following `(ident)` sub-meta, or any `#[stable_hash(...)]` whose nested tokens do not match `ignore` or `project(...)` on a field of a type deriving `StableHash`/`StableHashNoContext`.","commonSituations":"Misspelling the attribute key (e.g. `ignored` instead of `ignore`). Forgetting the required inner ident for `project` (e.g. `#[stable_hash(project)]`). Renaming the attribute in a rustc upgrade without updating call sites. Copying an attribute shape from another derive that uses different keys.","solutions":["Use exactly `#[stable_hash(ignore)]` to skip a field, or `#[stable_hash(project(field_name))]` to hash a projection, matching the keys parsed at stable_hash.rs:17-30.","Remove the attribute entirely if neither ignore nor projection is intended so the field is hashed normally.","Check the macro source to confirm the current accepted keys before re-adding the attribute after a rustc version bump."],"exampleFix":"// before\n#[derive(StableHash)]\nstruct S {\n    #[stable_hash(skip)]\n    cache: u32,\n}\n\n// after\n#[derive(StableHash)]\nstruct S {\n    #[stable_hash(ignore)]\n    cache: u32,\n}","handlingStrategy":"validation","validationCode":"// This panic comes from `stable_hash.rs` when the macro cannot parse the\n// annotated item (malformed item, unsupported generics, bad attribute args).\n// Validate parseability with syn BEFORE invoking #[derive(StableHash)].\nuse syn::{parse_str, Item};\n\nfn can_parse_as_item(src: &str) -> Result<Item, syn::Error> {\n    parse_str::<Item>(src)\n}\n\n// In your build step or a `trybuild` test:\nif let Err(e) = can_parse_as_item(item_source) {\n    return Err(format!(\n        \"#[derive(StableHash)] input will fail to parse: {e}; \\n\\\n         fix the syntax before the macro runs\"\n    ));\n }","typeGuard":"// Confirm the parsed item is one of the shapes stable_hash can hash.\nfn stable_hashable(item: &syn::Item) -> bool {\n    matches!(\n        item,\n        syn::Item::Struct(_) | syn::Item::Enum(_) | syn::Item::Union(_)\n    ) && item_is_well_formed(item)\n}\n\nfn item_is_well_formed(item: &syn::Item) -> bool {\n    // No where-clause on a path that doesn't exist, no duplicate fields, etc.\n    // (Lightweight structural check; full validation lives in the macro.)\n    true\n}","tryCatchPattern":null,"preventionTips":["Keep the syntax of items annotated with #[derive(StableHash)] minimal — avoid exotic generics, macro-generated bodies, or unresolved paths.","Run `cargo expand` on a suspicious item; if expansion fails, the stable_hash derive will too.","Add a trybuild compile-fail test for any input shape you suspect the macro rejects.","When a derive fails to parse, fix the source rather than re-running — the panic is deterministic."],"tags":["rustc-macros","derive","stable-hash","attributes"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}