Rust generated: fix constant non-inlined global

We must take care that all access to property that we consider constant
in global are accessed after the global has been initialized.

So initialize the global before the properties.

Fixes #8375 , #8337
This commit is contained in:
Olivier Goffart 2025-05-05 18:55:19 +02:00 committed by GitHub
parent 23daf50422
commit 86978e9fc1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 24 additions and 17 deletions

View file

@ -290,7 +290,6 @@ fn generate_public_component(
pub fn new() -> core::result::Result<Self, slint::PlatformError> { pub fn new() -> core::result::Result<Self, slint::PlatformError> {
let inner = #inner_component_id::new()?; let inner = #inner_component_id::new()?;
#init_bundle_translations #init_bundle_translations
inner.globals.get().unwrap().init();
#inner_component_id::user_init(sp::VRc::map(inner.clone(), |x| x)); #inner_component_id::user_init(sp::VRc::map(inner.clone(), |x| x));
// ensure that the window exist as this point so further call to window() don't panic // ensure that the window exist as this point so further call to window() don't panic
inner.globals.get().unwrap().window_adapter_ref()?; inner.globals.get().unwrap().window_adapter_ref()?;
@ -379,16 +378,14 @@ fn generate_shared_globals(
root_item_tree_weak : sp::VWeak<sp::ItemTreeVTable>, root_item_tree_weak : sp::VWeak<sp::ItemTreeVTable>,
} }
impl SharedGlobals { impl SharedGlobals {
fn new(root_item_tree_weak : sp::VWeak<sp::ItemTreeVTable>) -> Self { fn new(root_item_tree_weak : sp::VWeak<sp::ItemTreeVTable>) -> sp::Rc<Self> {
Self { let _self = sp::Rc::new(Self {
#(#global_names : #global_types::new(),)* #(#global_names : #global_types::new(),)*
window_adapter : ::core::default::Default::default(), window_adapter : ::core::default::Default::default(),
root_item_tree_weak, root_item_tree_weak,
} });
} #(_self.#global_names.clone().init(&_self);)*
_self
fn init(self: &sp::Rc<Self>) {
#(self.#global_names.clone().init(self);)*
} }
fn window_adapter_impl(&self) -> sp::Rc<dyn sp::WindowAdapter> { fn window_adapter_impl(&self) -> sp::Rc<dyn sp::WindowAdapter> {
@ -1520,7 +1517,7 @@ fn generate_item_tree(
} else if parent_ctx.is_some() { } else if parent_ctx.is_some() {
quote!(parent.upgrade().unwrap().globals.get().unwrap().clone()) quote!(parent.upgrade().unwrap().globals.get().unwrap().clone())
} else { } else {
quote!(sp::Rc::new(SharedGlobals::new(sp::VRc::downgrade(&self_dyn_rc)))) quote!(SharedGlobals::new(sp::VRc::downgrade(&self_dyn_rc)))
}; };
let globals_arg = is_popup_menu.then(|| quote!(globals: sp::Rc<SharedGlobals>)); let globals_arg = is_popup_menu.then(|| quote!(globals: sp::Rc<SharedGlobals>));

View file

@ -3,38 +3,48 @@
// This tests that constant property from global are properly initialized // This tests that constant property from global are properly initialized
global Glob := { global Glob {
property <int> a: 3; in-out property <int> a: 3;
property <int> b: a + 3; in-out property <int> b: a + 3;
} }
global Glob2 := { global Glob2 {
property <int> a: other; in-out property <int> a: other;
property <int> other: 5; in-out property <int> other: 5;
// A constant property that is not going to be inlined
out property <int> const-no-inline: {
debug("this debug message should make no-inline to not be inlined");
82
}
} }
TestCase := Rectangle { export component TestCase inherits Window {
r := Rectangle { r := Rectangle {
property <int> value1: Glob.b; property <int> value1: Glob.b;
property <int> value2: true ? Glob2.a : 88; property <int> value2: true ? Glob2.a : 88;
} }
property <bool> test: r.value1 + r.value2 == 3+3 +5; out property <int> value3: Glob2.const-no-inline;
out property <bool> test: r.value1 + r.value2 == 3+3 +5 && value3 == 82;
} }
/* /*
```rust ```rust
let instance = TestCase::new().unwrap(); let instance = TestCase::new().unwrap();
assert_eq!(instance.get_value3(), 82);
assert!(instance.get_test()); assert!(instance.get_test());
``` ```
```cpp ```cpp
auto handle = TestCase::create(); auto handle = TestCase::create();
const TestCase &instance = *handle; const TestCase &instance = *handle;
assert_eq(instance.get_value3(), 82);
assert(instance.get_test()); assert(instance.get_test());
``` ```
```js ```js
let instance = new slint.TestCase({}); let instance = new slint.TestCase({});
assert.equal(instance.value3, 82);
assert(instance.test); assert(instance.test);
``` ```