slint-ui / slint

Slint is a declarative GUI toolkit to build native user interfaces for Rust, C++, or JavaScript apps.
https://slint.dev
Other
16.88k stars 560 forks source link

Compiler unable to represent state property binding when the default binding is declared in a different component #1461

Open tay64 opened 2 years ago

tay64 commented 2 years ago

Consider

Hello := Rectangle {
    background: xxx.color;
    xxx := Text {}
 }

 export AppWindow := Window {
    Hello {
        states [
            highlight when width < height : {
                background: red;
            }
        ]
    }
 }

This will get lowered to something like

export AppWindow := Window {
   Hello { 
       property <int> state: ...;
       background: state == 1 ? red : xxx.color;   
   }
}

But xxx.color can't be represented properly because xxx is inaccessible from within the AppWindow context. This may resulting in panics in the compiler in further passes.

To fix this, we need to change the representation of properties access to be able to access properties within element of components.

Original bug report Observed with slint 0.2.5 from crates.io and with a head version from git, commit 5bc56a3924408985. **Steps to reproduce**: 1. Start with `cargo generate --git https://github.com/slint-ui/slint-rust-template`. 2. Apply this diff: ```diff diff --git a/ui/appwindow.slint b/ui/appwindow.slint index 5345759..03e9e94 100644 --- a/ui/appwindow.slint +++ b/ui/appwindow.slint @@ -12,6 +12,11 @@ export AppWindow := Window { clicked => { request-increase-value(); } + states [ + highlight when counter > 45 : { + background: red; + } + ] } } } ``` [modified appwindow.slint](https://github.com/slint-ui/slint/files/9275730/appwindow.slint.txt) 3. Run `cargo build` **Error**: ``` error: failed to run custom build command for `slint-bug-state-background v0.1.0 (D:\0\slint-bug-state-background)` Caused by: process didn't exit successfully: `D:\0\slint-bug-state-background\target\debug\build\slint-bug-state-background-81a7ccd94231b199\build-script-build` (exit code: 101) --- stderr thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', C:\Users\user\.cargo\registry\src\github.com-1ecc6299db9ec823\i-slint-compiler-0.2.5\llr\lower_expression.rs:35:34 ``` [Error output with RUST_BACKTRACE=1](https://github.com/slint-ui/slint/files/9275733/error.log) **Additional observations**: * It works just fine when I load the .slint file at runtime using `slint_interpreter`. * The problem is specifically with the background: if I comment out the line `background: red;` but leave the rest of the added `states` in place, the error disappears. * No error if I change some of the other properties instead of `background` (I tried `text` and `opacity`). * Assigning to `background` in the `clicked` callback instead of `states` works fine. * Changing a custom property instead of `background` also works and gives a workaround. **Workaround**: Create a custom property and bind `background` to it: ```diff diff --git a/ui/appwindow.slint b/ui/appwindow.slint index 5345759..2e61b0f 100644 --- a/ui/appwindow.slint +++ b/ui/appwindow.slint @@ -12,6 +12,13 @@ export AppWindow := Window { clicked => { request-increase-value(); } + property my-background; + background: my-background; + states [ + highlight when counter > 45 : { + my-background: red; + } + ] } } } ``` OS: Windows Slint style: fluent (EDITED: added a workaround. Seems obvious but somehow didn't occur to me when I wrote the original description).
ogoffart commented 2 years ago

Thanks for the well written bug report. I was able to reproduce and found out what the problem is. This is a difficult problem to solve so I took the liberty to edit the description and title. I'm going to keep the issue open and implemented a workaround by making this code an error for now: https://github.com/slint-ui/slint/pull/1490 The actual fix will need some more refactorings in the compiler which will be done in a later release.