swc-project/swc · error

unsupported discriminant type

Error message

unsupported discriminant type

What it means

The Encode derive assigns each variant a CBOR index from a running u32 counter; an explicit discriminant is honored only when it is an integer literal (syn::Lit::Int) that parses as u32 — no const evaluation happens. `Variant = SOME_CONST` or any non-literal expression hits `Some(_) => panic!("unsupported discriminant type")`. Values that overflow u32 also fail in the subsequent parse unwrap.

Source

Thrown at crates/ast_node/src/encoding/encode.rs:128

                        },
                        _ => 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;
                let name = &field.ident;

                assert!(
                    !is_unknown(&field.attrs),
                    "unknown member must be first: {:?}",
                    field.attrs.len()
                );

                match enum_type {
                    EnumType::Unit => {
                        assert!(
                            is_with(&field.attrs).is_none(),
                            "unit member is not allowed with type"
                        );

View on GitHub (pinned to 5176682b65)

Solutions

  1. Inline the value as an integer literal: `Num = 3`.
  2. Or omit explicit discriminants and let the macro assign sequential indices.
  3. Guard against drift with a test asserting the encoded tag value.

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

When it happens

Trigger: derive(Encode) on an enum where a variant discriminant is a path/const, negative number, or other non-literal expression rather than a plain u32 integer literal.

Common situations: Refactoring wire-protocol magic numbers into shared consts; enums generated from specs where discriminants arrive as named constants.

Related errors


AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17). Data as JSON: /api/errors/aa443c693aeab020. Report an issue: GitHub.