slint-ui/slint · error

named struct declarations have symbol counters

Error message

named struct declarations have symbol counters

What it means

This panic fires in object_tree.rs:3916 when resolving default values for fields of a named struct declaration. `resolve_struct_field_default_value` requires the `symbol_counters` parameter to track unique identifiers, and the code asserts that named struct declarations always have counters available. A `None` here means the struct being processed was not registered with symbol counters, which the compiler treats as an impossible state.

Solutions

  1. Simplify: remove the default value expression from the struct field declaration and assign defaults at the property/binding site instead.
  2. Check whether the .slint file compiles with the latest stable Slint release; upgrade the slint compiler crate.
  3. If you are a compiler contributor, ensure the code path creating the named struct allocates symbol counters before default-value resolution runs.
  4. File a minimal reproducer as a compiler bug if it persists.

Example fix

// before
struct Data { count: int = 1; }
// after
struct Data { count: int; }
property <Data> d: { count: 1 };
Defensive patterns

Strategy: validation

Validate before calling

// Avoid the risky pattern in user code: no default values on named struct fields
fn has_struct_field_defaults(src: &str) -> bool {
    src.lines().any(|l| l.contains(":") && l.trim_end().ends_with("= ...;"))
}

Prevention

When it happens

Trigger: Compiling a .slint file containing a named `struct` declaration with a field default value, while the `symbol_counters` slot passed down is `None` — i.e. the struct was not created through the path that allocates counters (e.g. struct defined in a context where counters were not initialized, or a compiler pass ordering regression).

Common situations: Compiler development/refactoring around named struct declarations and default values; using an in-development Slint nightly with a pass-ordering regression; .slint files with struct field defaults processed through an unusual import/preprocessing path.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at internal/compiler/object_tree.rs:3982

    let fields: BTreeMap<SmolStr, Type> = object_node
        .ObjectTypeMember()
        .map(|member| {
            let field_name = parser::identifier_text(&member).unwrap_or_default();
            field_order.push(field_name.clone());
            let field_ty = type_from_node(member.Type(), diag, tr);
            if let Some(default_value_node) = member.Expression() {
                if name.is_none() {
                    diag.push_error(
                        "Field default values are only supported in named struct declarations"
                            .into(),
                        &default_value_node,
                    );
                } else if let Some(expr) = resolve_struct_field_default_value(
                    default_value_node,
                    &field_ty,
                    diag,
                    tr,
                    symbol_counters.expect("named struct declarations have symbol counters"),
                ) {
                    field_defaults.insert(field_name.clone(), expr);
                }
            }
            (field_name, field_ty)
        })
        .collect();
    // The `@rust-attr` attributes and the declaration node live on the
    // enclosing `StructDeclaration` (the parent of the `ObjectType`).
    let struct_decl = object_node.parent();
    Type::Struct(Arc::new(Struct {
        fields,
        field_defaults,
        name: name.map_or(StructName::None, |name| {
            let rust_attributes = struct_decl
                .as_ref()
                .and_then(|p| syntax_nodes::StructDeclaration::new(p.clone()))
                .map(|d| d.AtRustAttr().map(|a| SmolStr::from(a.text().to_string())).collect())

View on GitHub (pinned to 3a7e700487)