linera-io/linera-protocol · error · syn::Error
#[derive(StableEnum)] does not yet support generic enums
Error message
#[derive(StableEnum)] does not yet support generic enums
What it means
`#[derive(StableEnum)]` generates serde Serialize/Deserialize impls keyed by per-variant tags computed from variant names; generic enums are explicitly unsupported because the tag scheme has no representation for type parameters. `reject_generics` fails compilation for any enum with type/lifetime parameters or a where clause.
Source
Thrown at linera-sdk-derive/src/stable_enum.rs:89
.iter()
.find(|(_, t, _): &&(String, u32, &Variant)| *t == tag)
{
return Err(Error::new(
variant.span(),
format!(
"Keccak-256 tag collision between variants `{other_name}` and `{name}` \
(tag = {tag:#010x}). Rename one of the variants."
),
));
}
out.push((name, tag, variant));
}
Ok(out)
}
fn reject_generics(input: &ItemEnum) -> Result<()> {
if !input.generics.params.is_empty() || input.generics.where_clause.is_some() {
return Err(Error::new(
input.generics.span(),
"#[derive(StableEnum)] does not yet support generic enums",
));
}
Ok(())
}
/// Emits the combined `Serialize` + `Deserialize` + `StableEnumTrace` impls.
pub fn generate_all(input: &ItemEnum, crate_root: CrateRoot) -> Result<TokenStream2> {
let ser = generate_serialize(input, &crate_root)?;
let de = generate_deserialize(input, &crate_root)?;
let tr = generate_trace(input, &crate_root)?;
Ok(quote! {
#ser
#de
#tr
})
}View on GitHub (pinned to 6c226ddcb3)
Solutions
- Split the generic enum into concrete enums (one per payload type) and derive each.
- Hoist the varying payload out of the enum: keep a non-generic StableEnum for the discriminant and store the payload alongside it in a struct.
- If generics are essential, implement Serialize/Deserialize manually instead of using the derive.
- For lifetime-only parameters, switch to owned data (`String`, `Vec<u8>`) so the enum is non-generic.
Example fix
// before
#[derive(StableEnum)]
enum Message<T> { Set(T), Clear } // does not yet support generic enums
// after
#[derive(StableEnum)]
enum MessageKind { Set, Clear }
struct Message<T> { kind: MessageKind, value: Option<T> } Defensive patterns
Strategy: validation
Validate before calling
// compile-time guard: StableEnum requires a non-generic enum // `cargo check` fails fast with 'does not yet support generic enums' — keep enums concrete
Prevention
- Don't port generic serde enums into StableEnum verbatim; monomorphize first.
- Model varying payloads as struct fields beside a non-generic discriminant enum.
- Use owned types to eliminate lifetime parameters.
When it happens
Trigger: Deriving `StableEnum` on `enum E<T> { A(T), B }`, on an enum with a lifetime parameter, or on an enum carrying a `where` clause.
Common situations: Porting a generic state-machine enum to Linera's stable serialization; sharing one generic enum between an application contract and its Rust host/SDK code.
Related errors
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/12e19f2ba7bf202d.
Report an issue: GitHub.