Skip to content

Commit a3ab90d

Browse files
committed
compiler: Fix infinite recursion trying to inline function argument
We can't use `body.visit_recursive_mut` because it will recurse on the newly replaced argument. Implement recursion manually instead.
1 parent 9f91a60 commit a3ab90d

File tree

2 files changed

+52
-6
lines changed

2 files changed

+52
-6
lines changed

internal/compiler/passes/const_propagation.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -263,14 +263,17 @@ fn try_inline_function(function: &Callable, arguments: &[Expression]) -> Option<
263263
}
264264
let mut body = extract_constant_property_reference(function)?;
265265

266-
body.visit_recursive_mut(&mut |e| {
266+
fn substitute_arguments_recursive(e: &mut Expression, arguments: &[Expression]) {
267267
if let Expression::FunctionParameterReference { index, ty } = e {
268-
let Some(e_new) = arguments.get(*index).cloned() else { return };
269-
if e_new.ty() == *ty {
270-
*e = e_new;
271-
}
268+
let e_new = arguments.get(*index).expect("reference to invalid arg").clone();
269+
debug_assert_eq!(e_new.ty(), *ty);
270+
*e = e_new;
271+
} else {
272+
e.visit_mut(|e| substitute_arguments_recursive(e, arguments));
272273
}
273-
});
274+
}
275+
substitute_arguments_recursive(&mut body, arguments);
276+
274277
if simplify_expression(&mut body) {
275278
Some(body)
276279
} else {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright © SixtyFPS GmbH <[email protected]>
2+
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
3+
4+
struct Structure {
5+
value: int,
6+
}
7+
8+
component AlignedValue {
9+
in property <int> alignment: 1;
10+
in-out property <int> aligned-value;
11+
pure function align(value: int) -> int {
12+
(value / alignment) * alignment
13+
}
14+
public function set-value(new-value: int) {
15+
aligned-value = align(Math.max(0, new-value));
16+
}
17+
}
18+
19+
export component TestCase inherits Window {
20+
in-out property <Structure> range: { value: 42 };
21+
checked-range := AlignedValue {
22+
aligned-value: range.value;
23+
}
24+
25+
init => {
26+
checked-range.set_value(78);
27+
}
28+
29+
out property <bool> test: checked-range.aligned-value == 78;
30+
}
31+
32+
/*
33+
```cpp
34+
auto handle = TestCase::create();
35+
const TestCase &instance = *handle;
36+
assert(instance.get_test());
37+
```
38+
39+
```rust
40+
let instance = TestCase::new().unwrap();
41+
assert!(instance.get_test());
42+
```
43+
*/

0 commit comments

Comments
 (0)