diesel-rs/diesel · error

expected a literal expression, but got something else

Error message

expected a literal expression, but got something else

What it means

An explicit variant discriminant in a diesel enum must be a literal expression (e.g. `A = 1`). If the discriminant is any other expression — a path/constant, arithmetic, or a function call — the parser cannot evaluate it at macro-expansion time and errors.

Solutions

  1. Inline the literal value: `A = 42` instead of `A = SOME_CONST`.
  2. Precompute the value and write it as a literal with a comment explaining provenance.
  3. Remove the discriminant entirely if explicit numbering is not required.

Example fix

// before
enum Level { Low = BASE, High = BASE + 10 }

// after
enum Level { Low = 1, High = 11 }
Defensive patterns

Strategy: validation

Validate before calling

// Discriminants must be plain literals
fn validate_discriminants(values: &[String]) -> Result<(), String> {
    for v in values {
        if v.parse::<i64>().is_err() {
            return Err(format!("discriminant `{v}` must be a literal integer"));
        }
    }
    Ok(())
}

Prevention

When it happens

Trigger: `enum E { A = SOME_CONST, B }` or `enum E { A = 1 + 2, B }` where the discriminant is not a plain literal.

Common situations: Referencing a `const` item to keep values DRY; building values with arithmetic from other constants; code copied from a non-diesel context where complex discriminants are legal.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of diesel-rs/diesel@6fa6ed01b2 (2026-09-07). Data as JSON: /api/errors/777e550720c4794c. Report an issue: GitHub.

Appendix: source

Thrown at diesel_derives/src/enum_.rs:183

            if !v.fields.is_empty() {
                return Err(syn::Error::new(v.span(), ERROR_MESSAGE));
            }
            has_explicit_discriminants = has_explicit_discriminants && v.discriminant.is_some();
            let discriminant = v
                .discriminant
                .as_ref()
                .map(|(_, v)| {
                    let (f, l) = match v {
                        syn::Expr::Lit(l) => (1, l),
                        syn::Expr::Unary(syn::ExprUnary {
                            op: syn::UnOp::Neg(_),
                            expr,
                            ..
                        }) => {
                            if let syn::Expr::Lit(l) = &**expr {
                                (-1, l)
                            } else {
                                return Err(syn::Error::new(
                                    v.span(),
                                    "expected a literal expression, but got something else",
                                ));
                            }
                        }
                        _ => {
                            return Err(syn::Error::new(
                                v.span(),
                                "expected a literal expression, but got something else",
                            ));
                        }
                    };
                    let syn::Lit::Int(i) = &l.lit else {
                        return Err(syn::Error::new(
                            l.span(),
                            "expected a integer literal expression, but got something else",
                        ));
                    };

View on GitHub (pinned to 6fa6ed01b2)