slint-ui/slint · error

Expression::StructFieldAccess: Cannot find a key in an…

Error message

Expression::StructFieldAccess: Cannot find a key in an object

What it means

Rust generator counterpart of the C++ struct-key panic: anonymous structs become tuples, and `struct_field_access` computes the tuple element index from the field name. Panics when the requested field name is absent from the struct's field map — an expression accessing a key that does not exist reached codegen despite type checking.

Solutions

  1. Fix the pass that desynchronizes the struct type from the field accesses
  2. Ensure the type checker rejects unknown field accesses with a user-facing diagnostic before codegen
  3. Dump the Struct's fields at the panic site to identify which pass dropped the key

Example fix

// before
let index = s.fields.keys().position(|k| k == name).expect("...");
// after
let index = s.fields.keys().position(|k| k == name).unwrap_or_else(||
    panic!("StructFieldAccess: key '{name}' not found in fields {:?}", s.fields.keys().collect::<Vec<_>>()));
Defensive patterns

Strategy: type-guard

Validate before calling

fn struct_has_field(s: &Struct, name: &str) -> bool {
    s.fields.keys().any(|k| k == name)
}

Type guard

fn field_index(s: &Struct, name: &str) -> Option<usize> {
    s.fields.keys().position(|k| k == name)
}

Prevention

When it happens

Trigger: `lower_field_access_chain` or `compile_expression` lowering a `StructFieldAccess` whose `name` is missing from `s.fields` of an anonymous struct — caused by a pass rewriting struct shapes or a typecheck/codegen inconsistency.

Common situations: Compiler development: field-renaming or optimization passes that change anonymous struct fields without tracking dependent accesses; lookup/type-inference regressions; fuzzed inputs that bypass checker invariants.

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/a8518c18b1e3ac26. Report an issue: GitHub.

Appendix: source

Thrown at internal/compiler/generator/rust.rs:4522

                &self::_SLINT_TRANSLATED_STRINGS_PLURALS[#string_index],
                &self::_SLINT_TRANSLATED_PLURAL_RULES,
                sp::Slice::<sp::SharedString>::from(#args).as_slice(),
                #plural as _
            ))
        }
        None => {
            quote!(sp::translate_from_bundle(&self::_SLINT_TRANSLATED_STRINGS[#string_index], sp::Slice::<sp::SharedString>::from(#args).as_slice()))
        }
    }
}

fn struct_field_access(s: &Struct, name: &str) -> proc_macro2::TokenTree {
    if s.name.is_none() {
        let index = s
            .fields
            .keys()
            .position(|k| k == name)
            .expect("Expression::StructFieldAccess: Cannot find a key in an object");
        proc_macro2::Literal::usize_unsuffixed(index).into()
    } else {
        ident(name).into()
    }
}

fn compile_builtin_function_call(
    function: BuiltinFunction,
    arguments: &[Expression],
    ctx: &EvaluationContext,
) -> TokenStream {
    let mut a = arguments.iter().map(|a| compile_expression_to_value(a, ctx));
    match function {
        BuiltinFunction::SetFocusItem => {
            if let [Expression::PropertyReference(pr)] = arguments {
                let window_tokens = access_window_adapter_field(ctx);
                item_owner(pr).then(|owner| {
                    let (_, focus_item) = native_item_from_owner(pr, ctx, &owner);

View on GitHub (pinned to 3a7e700487)