From bd18d8dc0abc132f4e2327d94abf8dabdad335c2 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 25 Jun 2024 18:09:32 +0200 Subject: [PATCH] Fix compiler crash when const propagating a property of `component-factory` with its default value We couldn't represent an empty component factory in the exrpession tree, so add Expression::EmptyComponentFactory for that --- internal/compiler/expression_tree.rs | 9 ++++++++- internal/compiler/generator/cpp.rs | 1 + internal/compiler/generator/rust.rs | 1 + internal/compiler/llr/expression.rs | 6 +++++- internal/compiler/llr/lower_expression.rs | 1 + internal/compiler/llr/optim_passes/inline_expressions.rs | 1 + internal/compiler/llr/pretty_print.rs | 1 + internal/interpreter/eval.rs | 1 + tests/cases/elements/component_container.slint | 5 +++++ 9 files changed, 24 insertions(+), 2 deletions(-) diff --git a/internal/compiler/expression_tree.rs b/internal/compiler/expression_tree.rs index 8cf116e8e5a..ef2701437d3 100644 --- a/internal/compiler/expression_tree.rs +++ b/internal/compiler/expression_tree.rs @@ -737,6 +737,8 @@ pub enum Expression { lhs: Box, rhs: Box, }, + + EmptyComponentFactory, } impl Expression { @@ -864,6 +866,7 @@ impl Expression { Expression::ComputeLayoutInfo(..) => crate::layout::layout_info_type(), Expression::SolveLayout(..) => Type::LayoutCache, Expression::MinMax { ty, .. } => ty.clone(), + Expression::EmptyComponentFactory => Type::ComponentFactory, } } @@ -966,6 +969,7 @@ impl Expression { visitor(lhs); visitor(rhs); } + Expression::EmptyComponentFactory => {} } } @@ -1070,6 +1074,7 @@ impl Expression { visitor(lhs); visitor(rhs); } + Expression::EmptyComponentFactory => {} } } @@ -1148,6 +1153,7 @@ impl Expression { Expression::ComputeLayoutInfo(..) => false, Expression::SolveLayout(..) => false, Expression::MinMax { lhs, rhs, .. } => lhs.is_constant() && rhs.is_constant(), + Expression::EmptyComponentFactory => true, } } @@ -1334,7 +1340,6 @@ impl Expression { match ty { Type::Invalid | Type::Callback { .. } - | Type::ComponentFactory | Type::Function { .. } | Type::InferredProperty | Type::InferredCallback @@ -1379,6 +1384,7 @@ impl Expression { Type::Enumeration(enumeration) => { Expression::EnumerationValue(enumeration.clone().default_value()) } + Type::ComponentFactory => Expression::EmptyComponentFactory, } } @@ -1781,5 +1787,6 @@ pub fn pretty_print(f: &mut dyn std::fmt::Write, expression: &Expression) -> std pretty_print(f, rhs)?; write!(f, ")") } + Expression::EmptyComponentFactory => write!(f, ""), } } diff --git a/internal/compiler/generator/cpp.rs b/internal/compiler/generator/cpp.rs index 09d8656cc4e..91d67272c5f 100644 --- a/internal/compiler/generator/cpp.rs +++ b/internal/compiler/generator/cpp.rs @@ -3096,6 +3096,7 @@ fn compile_expression(expr: &llr::Expression, ctx: &EvaluationContext) -> String rhs_code = rhs_code ) } + Expression::EmptyComponentFactory => panic!("component-factory not yet supported in C++"), } } diff --git a/internal/compiler/generator/rust.rs b/internal/compiler/generator/rust.rs index b05752e980a..69444f6bece 100644 --- a/internal/compiler/generator/rust.rs +++ b/internal/compiler/generator/rust.rs @@ -2395,6 +2395,7 @@ fn compile_expression(expr: &Expression, ctx: &EvaluationContext) -> TokenStream } } } + Expression::EmptyComponentFactory => quote!(slint::ComponentFactory::default()), } } diff --git a/internal/compiler/llr/expression.rs b/internal/compiler/llr/expression.rs index 64d51120191..138e4ce525d 100644 --- a/internal/compiler/llr/expression.rs +++ b/internal/compiler/llr/expression.rs @@ -187,6 +187,8 @@ pub enum Expression { lhs: Box, rhs: Box, }, + + EmptyComponentFactory, } impl Expression { @@ -194,7 +196,6 @@ impl Expression { Some(match ty { Type::Invalid | Type::Callback { .. } - | Type::ComponentFactory | Type::Function { .. } | Type::Void | Type::InferredProperty @@ -241,6 +242,7 @@ impl Expression { Type::Enumeration(enumeration) => { Expression::EnumerationValue(enumeration.clone().default_value()) } + Type::ComponentFactory => Expression::EmptyComponentFactory, }) } @@ -301,6 +303,7 @@ impl Expression { Type::Array(super::lower_expression::grid_layout_cell_data_ty().into()) } Self::MinMax { ty, .. } => ty.clone(), + Self::EmptyComponentFactory => Type::ComponentFactory, } } } @@ -382,6 +385,7 @@ macro_rules! visit_impl { $visitor(lhs); $visitor(rhs); } + Expression::EmptyComponentFactory => {} } }; } diff --git a/internal/compiler/llr/lower_expression.rs b/internal/compiler/llr/lower_expression.rs index f79a28e6fb5..524f5c0d451 100644 --- a/internal/compiler/llr/lower_expression.rs +++ b/internal/compiler/llr/lower_expression.rs @@ -213,6 +213,7 @@ pub fn lower_expression( lhs: Box::new(lower_expression(lhs, ctx)), rhs: Box::new(lower_expression(rhs, ctx)), }, + tree_Expression::EmptyComponentFactory => llr_Expression::EmptyComponentFactory, } } diff --git a/internal/compiler/llr/optim_passes/inline_expressions.rs b/internal/compiler/llr/optim_passes/inline_expressions.rs index a4df6e537e4..39ee34e4e71 100644 --- a/internal/compiler/llr/optim_passes/inline_expressions.rs +++ b/internal/compiler/llr/optim_passes/inline_expressions.rs @@ -51,6 +51,7 @@ fn expression_cost(exp: &Expression, ctx: &EvaluationContext) -> isize { Expression::BoxLayoutFunction { .. } => return isize::MAX, Expression::ComputeDialogLayoutCells { .. } => return isize::MAX, Expression::MinMax { .. } => 10, + Expression::EmptyComponentFactory => 10, }; exp.visit(|e| cost = cost.saturating_add(expression_cost(e, ctx))); diff --git a/internal/compiler/llr/pretty_print.rs b/internal/compiler/llr/pretty_print.rs index 37aaa8ff782..a96c7fdd855 100644 --- a/internal/compiler/llr/pretty_print.rs +++ b/internal/compiler/llr/pretty_print.rs @@ -268,6 +268,7 @@ impl<'a, T> Display for DisplayExpression<'a, T> { MinMaxOp::Min => write!(f, "min({}, {})", e(lhs), e(rhs)), MinMaxOp::Max => write!(f, "max({}, {})", e(lhs), e(rhs)), }, + Expression::EmptyComponentFactory => write!(f, "",), } } } diff --git a/internal/interpreter/eval.rs b/internal/interpreter/eval.rs index 1442aa3ab41..0e1edb15990 100644 --- a/internal/interpreter/eval.rs +++ b/internal/interpreter/eval.rs @@ -394,6 +394,7 @@ pub fn eval_expression(expression: &Expression, local_context: &mut EvalLocalCon MinMaxOp::Max => Value::Number(lhs.max(rhs)), } } + Expression::EmptyComponentFactory => Value::ComponentFactory(Default::default()) } } diff --git a/tests/cases/elements/component_container.slint b/tests/cases/elements/component_container.slint index 7e1a9ed9269..1c1168df91e 100644 --- a/tests/cases/elements/component_container.slint +++ b/tests/cases/elements/component_container.slint @@ -17,6 +17,11 @@ export component TestCase inherits Rectangle { in property c1 <=> cont1.component-factory; in property c2 <=> cont2.component-factory; out property outside-focus <=> outside.has-focus; + + + private property some-factory; + ComponentContainer { component-factory: some-factory; } + out property test: some-factory == some-factory; } /*