{"record":{"id":"d78aabd350674cd1","repo":"slint-ui/slint","slug":"showpopupwindow-is-invoked-on-a-sub-component","errorCode":null,"errorMessage":"ShowPopupWindow is invoked on a sub-component","messagePattern":"ShowPopupWindow is invoked on a sub-component","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/compiler/generator/cpp.rs","lineNumber":5381,"sourceCode":"                let popup_ctx = EvaluationContext::new_sub_component(\n                    ctx.compilation_unit,\n                    popup.item_tree.root,\n                    CppGeneratorContext { global_access: \"self->globals\".into(), conditional_includes: ctx.generator_state.conditional_includes },\n                    Some(&parent_ctx),\n                );\n                let position = compile_expression(&popup.position.borrow(), &popup_ctx);\n                let close_policy = compile_expression(close_policy, ctx);\n                let window_kind = if popup.is_tooltip { \"slint::cbindgen_private::WindowKind::ToolTip\" } else { \"slint::cbindgen_private::WindowKind::Popup\" };\n                // Keep the parent's `is-open` property in sync. The setter is passed directly into\n                // `show_popup`, so there is no extra registration call and no second popup lookup. The\n                // `false` is delivered when the popup is dropped, which may be long after this frame, so\n                // we cannot capture a raw `self`. We capture a weak *mapped* handle to the current\n                // component instance -- the C++ equivalent of Rust's `self_weak`, which for a\n                // sub-component points at that sub-component itself rather than at the enclosing item\n                // tree (`self->self_weak`). Popups without `is-open` get a no-op setter.\n                let is_open_setter = match is_open_args.first() {\n                    Some(llr::Expression::PropertyReference(is_open_ref)) => {\n                        let self_ty = ident(&ctx.current_sub_component().expect(\"ShowPopupWindow is invoked on a sub-component\").name);\n                        let set_is_open = access_member(is_open_ref, ctx).then(|p| format!(\"{p}.set(is_open)\"));\n                        format!(\n                            \"[weak = vtable::VWeakMapped<slint::private_api::ItemTreeVTable, const {self_ty}>( \\\n                                    vtable::VRcMapped<slint::private_api::ItemTreeVTable, const {self_ty}>(self->self_weak.lock().value(), self))] \\\n                             (bool is_open) {{ \\\n                                auto rc = weak.lock(); \\\n                                if (!rc) return; \\\n                                [[maybe_unused]] auto self = &**rc; \\\n                                {set_is_open}; \\\n                            }}\"\n                        )\n                    }\n                    _ => \"[](bool) {}\".to_string(),\n                };\n                item_owner(anchor_ref).then_named(\"anchor_owner\", |owner| {\n                    let (_, parent_component) = native_item_from_owner(anchor_ref, ctx, owner);\n                    component_access.then(|component_access| {\n                    let compo_ptr = if compo_path.is_empty() {","sourceCodeStart":5363,"sourceCodeEnd":5399,"githubUrl":"https://github.com/slint-ui/slint/blob/3a7e700487dc74d404cad0726378053ab763d4e0/internal/compiler/generator/cpp.rs#L5363-L5399","documentation":"When generating C++ code for `show-popup-window` (and its `is-open` handling), the generator needs the current sub-component's class name to build a weak mapped handle for the popup's `is-open` setter. If `ctx.current_sub_component()` is None the generator panics: popup invocation is expected to be compiled within a sub-component context.","triggerScenarios":"A `ShowPopupWindow` expression is compiled while the EvaluationContext has no current sub-component — e.g. the popup call got moved into a global or root-level context by an earlier pass, or a new code path compiles popup expressions without `new_sub_component`.","commonSituations":"Slint compiler development: refactoring how popup expressions or `is-open` bindings are lowered; adding a new generator entry point that forgets to establish the sub-component frame.","solutions":["Ensure the ShowPopupWindow expression is compiled with an EvaluationContext created via `new_sub_component` for the containing sub-component","If popups can now live at other levels, capture the enclosing component handle explicitly instead of expecting a sub-component","Report with a reproducing .slint file if hit as a user"],"exampleFix":"// before\nlet self_ty = ident(&ctx.current_sub_component().expect(\"...\").name);\n// after\nlet self_ty = ident(&ctx.current_sub_component().unwrap_or_else(||\n    panic!(\"ShowPopupWindow compiled outside sub-component context\")).name);","handlingStrategy":"validation","validationCode":"debug_assert!(ctx.current_sub_component().is_some(), \"ShowPopupWindow requires a sub-component context\");","typeGuard":"let self_component = ctx.current_sub_component().ok_or_else(||\n    panic!(\"ShowPopupWindow compiled outside sub-component context\"))?;","tryCatchPattern":null,"preventionTips":["Compile popup expressions only within new_sub_component contexts","Assert the context kind at the top of popup-expression compilation","Test show-popup-window lowering from every generator entry point","Keep popup handling symmetric between C++ and Rust generators"],"tags":["compiler","cpp-codegen","popups","internal-invariant"],"backgroundTag":"internal-invariant-violation","analyzedSha":"3a7e700487dc74d404cad0726378053ab763d4e0","analyzedAt":"2026-09-16T01:37:20.251Z","contentChangedAt":"2026-09-16T01:37:20.251Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}