Skip to content

Commit

Permalink
Fix compiler crash when const propagating a property of `component-fa…
Browse files Browse the repository at this point in the history
…ctory` with its default value

We couldn't represent an empty component factory in the exrpession tree,
so add Expression::EmptyComponentFactory for that
  • Loading branch information
ogoffart committed Jun 25, 2024
1 parent bc35d49 commit bd18d8d
Show file tree
Hide file tree
Showing 9 changed files with 24 additions and 2 deletions.
9 changes: 8 additions & 1 deletion internal/compiler/expression_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,8 @@ pub enum Expression {
lhs: Box<Expression>,
rhs: Box<Expression>,
},

EmptyComponentFactory,
}

impl Expression {
Expand Down Expand Up @@ -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,
}
}

Expand Down Expand Up @@ -966,6 +969,7 @@ impl Expression {
visitor(lhs);
visitor(rhs);
}
Expression::EmptyComponentFactory => {}
}
}

Expand Down Expand Up @@ -1070,6 +1074,7 @@ impl Expression {
visitor(lhs);
visitor(rhs);
}
Expression::EmptyComponentFactory => {}
}
}

Expand Down Expand Up @@ -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,
}
}

Expand Down Expand Up @@ -1334,7 +1340,6 @@ impl Expression {
match ty {
Type::Invalid
| Type::Callback { .. }
| Type::ComponentFactory
| Type::Function { .. }
| Type::InferredProperty
| Type::InferredCallback
Expand Down Expand Up @@ -1379,6 +1384,7 @@ impl Expression {
Type::Enumeration(enumeration) => {
Expression::EnumerationValue(enumeration.clone().default_value())
}
Type::ComponentFactory => Expression::EmptyComponentFactory,
}
}

Expand Down Expand Up @@ -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, "<empty-component-factory>"),
}
}
1 change: 1 addition & 0 deletions internal/compiler/generator/cpp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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++"),
}
}

Expand Down
1 change: 1 addition & 0 deletions internal/compiler/generator/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2395,6 +2395,7 @@ fn compile_expression(expr: &Expression, ctx: &EvaluationContext) -> TokenStream
}
}
}
Expression::EmptyComponentFactory => quote!(slint::ComponentFactory::default()),
}
}

Expand Down
6 changes: 5 additions & 1 deletion internal/compiler/llr/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,14 +187,15 @@ pub enum Expression {
lhs: Box<Expression>,
rhs: Box<Expression>,
},

EmptyComponentFactory,
}

impl Expression {
pub fn default_value_for_type(ty: &Type) -> Option<Self> {
Some(match ty {
Type::Invalid
| Type::Callback { .. }
| Type::ComponentFactory
| Type::Function { .. }
| Type::Void
| Type::InferredProperty
Expand Down Expand Up @@ -241,6 +242,7 @@ impl Expression {
Type::Enumeration(enumeration) => {
Expression::EnumerationValue(enumeration.clone().default_value())
}
Type::ComponentFactory => Expression::EmptyComponentFactory,
})
}

Expand Down Expand Up @@ -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,
}
}
}
Expand Down Expand Up @@ -382,6 +385,7 @@ macro_rules! visit_impl {
$visitor(lhs);
$visitor(rhs);
}
Expression::EmptyComponentFactory => {}
}
};
}
Expand Down
1 change: 1 addition & 0 deletions internal/compiler/llr/lower_expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}

Expand Down
1 change: 1 addition & 0 deletions internal/compiler/llr/optim_passes/inline_expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)));
Expand Down
1 change: 1 addition & 0 deletions internal/compiler/llr/pretty_print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, "<empty-component-factory>",),
}
}
}
1 change: 1 addition & 0 deletions internal/interpreter/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
}
}

Expand Down
5 changes: 5 additions & 0 deletions tests/cases/elements/component_container.slint
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ export component TestCase inherits Rectangle {
in property<component-factory> c1 <=> cont1.component-factory;
in property<component-factory> c2 <=> cont2.component-factory;
out property<bool> outside-focus <=> outside.has-focus;


private property <component-factory> some-factory;
ComponentContainer { component-factory: some-factory; }
out property <bool> test: some-factory == some-factory;
}

/*
Expand Down

0 comments on commit bd18d8d

Please sign in to comment.