slint-ui/slint · error

Unmapped struct field type

Error message

Unmapped struct field type `{other}` for default-value computation. Extend `field_default` in api/node/build.rs.

What it means

field_default computes a JS default-value literal for each builtin struct field type. This panic is the same style of forward-compatibility guard as map_field_type: a struct field whose Rust type has no arm in the match cannot get a default expression, so the build stops with instructions to extend field_default. The offending input is the unmapped Rust type string; without the guard the generated code would have a missing or wrong initializer.

Solutions

  1. Add a match arm in field_default in api/node/build.rs returning a correct JS default-expression for the new type
  2. For a type that needs a non-trivial default, emit a constructor call or 'undefined' intentionally after confirming the JS runtime accepts it
  3. If the field must not appear in defaults, exclude it in the struct-walking code rather than extending the match
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at api/node/build.rs:249 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of slint-ui/slint@bb937076de (2026-09-16). Data as JSON: /api/errors/1f9dd92c3e003faa. Report an issue: GitHub.

Appendix: source

Thrown at api/node/build.rs:249

        return match text.split_once("::") {
            // Enum values are kebab-case strings in the JS API
            Some((_, variant)) => {
                format!("\"{}\"", to_kebab_case(variant.trim_start_matches("r#")))
            }
            // bool and number literals are the same in JS
            None => text,
        };
    }
    let t = rust_ty.trim();
    match t {
        "bool" => "false".to_string(),
        "i32" | "f32" | "f64" | "Coord" => "0".to_string(),
        "SharedString" => "\"\"".to_string(),
        "DataTransfer" => "new DataTransfer()".to_string(),
        "LogicalPosition" => "{ x: 0, y: 0 }".to_string(),
        ident if enum_defaults.contains_key(ident) => format!("\"{}\"", enum_defaults[ident]),
        ident if structs.contains(ident) => format!("_data.{ident}()"),
        other => panic!(
            "Unmapped struct field type `{other}` for default-value computation. \
             Extend `field_default` in api/node/build.rs."
        ),
    }
}

/// Emit a `Foo: (props?: Partial<language.Foo>): language.Foo => Object.freeze({ … })` factory
/// inside `_data`. The factory exists so consumers can build values without specifying every
/// field, which gives us forward-compatibility (the Rust-side analogue of `#[non_exhaustive]`).
fn emit_struct_factory(
    out: &mut String,
    s: &StructEntry,
    enum_defaults: &HashMap<&'static str, String>,
    struct_names: &HashSet<&'static str>,
) {
    out.push_str("    /**\n");
    out.push_str(
        "     * Build a value of this struct. Any field you omit takes a documented default,\n",

View on GitHub (pinned to bb937076de)