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
- Fix the pass that desynchronizes the struct type from the field accesses
- Ensure the type checker rejects unknown field accesses with a user-facing diagnostic before codegen
- 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
- Guarantee type checking runs and passes before rust codegen
- Add tests for passes that mutate anonymous struct shapes
- Keep struct_field_access behavior aligned with the C++ generator
- Include field names in panic messages to speed up debugging
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
- Expression::ObjectAccess: Cannot find a key in an object
- there should be a popup menu if we want to show it
- model two-way bindings only exist on sub-components
- ShowPopupWindow is invoked on a sub-component
- there should be a popup menu if we want to show it
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)