swc-project/swc · error
unsupported discriminant type
Error message
unsupported discriminant type
What it means
The generated CBOR codec indexes each variant with a running u32 counter; an explicit discriminant is honored only when it is an integer literal (syn::Lit::Int) that base10_parse can read as u32 — the macro does no const evaluation. `A = SOME_CONST`, `A = -1`, or any other expression hits `Some(_) => panic!("unsupported discriminant type")`. Values that overflow u32 additionally fail inside the following unwrap().
Source
Thrown at crates/ast_node/src/encoding/decode.rs:160
_ => panic!("named enum unsupported"),
}
});
if matches!(enum_type, EnumType::Struct) {
assert!(
unknown_arm.is_none(),
"struct enum does not allow unknown variants"
);
}
let mut discriminant: u32 = 0;
let fields = iter
.map(|field| -> syn::Arm {
match field.discriminant.as_ref() {
Some((_, syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Int(lit), .. }))) => {
discriminant = lit.base10_parse::<u32>().unwrap();
},
Some(_) => panic!("unsupported discriminant type"),
None => (),
};
discriminant += 1;
let idx = discriminant as u64;
let name = &field.ident;
assert!(!is_unknown(&field.attrs), "unknown member must be first");
match enum_type {
EnumType::Unit => {
assert!(is_with(&field.attrs).is_none(), "unit member is not allowed with type");
syn::parse_quote!{
#idx => #ident::#name,
}
},
EnumType::One => {
let val_ty = &field.fields.iter().next().unwrap().ty;
let value: syn::Expr = match is_with(&field.attrs) {View on GitHub (pinned to 5176682b65)
Solutions
- Inline the value as an integer literal: `Num = 3`.
- Or remove explicit discriminants and let the macro assign sequential indices.
- Keep external consumers in sync by asserting the encoded tag value in a test instead of sharing a const into the enum definition.
Example fix
// before
const KIND_NUM: u32 = 3;
enum Tagged {
Str = 1,
Num = KIND_NUM,
}
// after — plain u32 literals
enum Tagged {
Str = 1,
Num = 3,
} Defensive patterns
Strategy: validation
Prevention
- Write enum discriminants as plain u32 integer literals in the enum definition.
- Share wire values via tests that assert the encoded tag, not via consts spliced into the enum.
- Avoid negative, float, or const-path discriminants on codec-derived enums.
When it happens
Trigger: derive(Decode) on an enum where a variant discriminant is a path/constant, a negative number, or any non-literal expression instead of a plain u32 integer literal.
Common situations: Sharing discriminant constants between the wire protocol and Rust code; refactoring magic numbers into consts and forgetting the macro only accepts literals.
Related errors
- more than 1 unnamed member field are not allowed
- enum member types must be consistent: {:?}
- unknown member must be a tag and a value
- named enum unsupported
- unsupported discriminant type
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/d42d210f396743bb.
Report an issue: GitHub.