rust-lang/rust · error
error parsing stable_hash
Error message
error parsing stable_hash
What it means
`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.
Source
Thrown at compiler/rustc_macros/src/stable_hash.rs:34
let mut any_attr = false;
let _ = attr.parse_nested_meta(|nested| {
if nested.path.is_ident("ignore") {
attrs.ignore = true;
any_attr = true;
}
if nested.path.is_ident("project") {
let _ = nested.parse_nested_meta(|meta| {
if attrs.project.is_none() {
attrs.project = meta.path.get_ident().cloned();
}
any_attr = true;
Ok(())
});
}
Ok(())
});
if !any_attr {
panic!("error parsing stable_hash");
}
}
attrs
}
pub(crate) fn stable_hash_derive(s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
stable_hash_derive_with_mode(s, StableHashMode::Normal)
}
pub(crate) fn stable_hash_no_context_derive(
s: synstructure::Structure<'_>,
) -> proc_macro2::TokenStream {
stable_hash_derive_with_mode(s, StableHashMode::NoContext)
}
enum StableHashMode {
// Do a normal derive, where any generic type parameter gets a `StableHash` bound.
// For example, in `struct Abc<T, U>(T, U)` the added bounds are `T: StableHash` andView on GitHub (pinned to 22057b88b0)
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.
Example fix
// before
#[derive(StableHash)]
struct S {
#[stable_hash(skip)]
cache: u32,
}
// after
#[derive(StableHash)]
struct S {
#[stable_hash(ignore)]
cache: u32,
} Defensive patterns
Strategy: validation
Validate before calling
// This panic comes from `stable_hash.rs` when the macro cannot parse the
// annotated item (malformed item, unsupported generics, bad attribute args).
// Validate parseability with syn BEFORE invoking #[derive(StableHash)].
use syn::{parse_str, Item};
fn can_parse_as_item(src: &str) -> Result<Item, syn::Error> {
parse_str::<Item>(src)
}
// In your build step or a `trybuild` test:
if let Err(e) = can_parse_as_item(item_source) {
return Err(format!(
"#[derive(StableHash)] input will fail to parse: {e}; \n\
fix the syntax before the macro runs"
));
} Type guard
// Confirm the parsed item is one of the shapes stable_hash can hash.
fn stable_hashable(item: &syn::Item) -> bool {
matches!(
item,
syn::Item::Struct(_) | syn::Item::Enum(_) | syn::Item::Union(_)
) && item_is_well_formed(item)
}
fn item_is_well_formed(item: &syn::Item) -> bool {
// No where-clause on a path that doesn't exist, no duplicate fields, etc.
// (Lightweight structural check; full validation lives in the macro.)
true
} Prevention
- 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.
When it happens
Trigger: 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`.
Common situations: 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.
Related errors
- cannot derive on union
- cannot derive on union
- cannot derive on union
- cannot derive on union
- cannot derive on union
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/2c8f18f70333fa6f.json.
Report an issue: GitHub.