Skip to content

Commit bc5dbc8

Browse files
dfaure-kdabtilladam
authored andcommitted
llr::Expression: add support for owned arrays (slint-ui#10382)
Generating Slice::from_slice(&[...]) is only valid for values being passed as function arguments. For a function's return type, for instance, this is invalid, the array will be deallocated immediately. The bool as_model is now an enum, to offer three choices Before: as_model=false => Slice::from_slice as_model=true => ModelRc<VecModel> After: ArrayOutput::Slice => Slice::from_slice ArrayOutput::Vector => Vec ArrayOutput::Model => ModelRc<VecModel>
1 parent 0698880 commit bc5dbc8

File tree

4 files changed

+53
-39
lines changed

4 files changed

+53
-39
lines changed

internal/compiler/generator/cpp.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3401,7 +3401,7 @@ fn compile_expression(expr: &llr::Expression, ctx: &EvaluationContext) -> String
34013401
) =>
34023402
{
34033403
let path_elements = match from.as_ref() {
3404-
Expression::Array { element_ty: _, values, as_model: _ } => {
3404+
Expression::Array { element_ty: _, values, output: _ } => {
34053405
values.iter().map(|path_elem_expr| {
34063406
let (field_count, qualified_elem_type_name) =
34073407
match path_elem_expr.ty(ctx) {
@@ -3609,25 +3609,27 @@ fn compile_expression(expr: &llr::Expression, ctx: &EvaluationContext) -> String
36093609
format!("({cond_code} ? {true_code} : {false_code})")
36103610
}
36113611
}
3612-
Expression::Array { element_ty, values, as_model } => {
3612+
Expression::Array { element_ty, values, output } => {
36133613
let ty = element_ty.cpp_type().unwrap();
36143614
let mut val = values
36153615
.iter()
36163616
.map(|e| format!("{ty} ( {expr} )", expr = compile_expression(e, ctx), ty = ty));
3617-
if *as_model {
3618-
format!(
3617+
match output {
3618+
llr::ArrayOutput::Model => format!(
36193619
"std::make_shared<slint::private_api::ArrayModel<{count},{ty}>>({val})",
36203620
count = values.len(),
36213621
ty = ty,
36223622
val = val.join(", ")
3623-
)
3624-
} else {
3625-
format!(
3623+
),
3624+
llr::ArrayOutput::Slice => format!(
36263625
"slint::private_api::make_slice<{ty}>(std::array<{ty}, {count}>{{ {val} }}.data(), {count})",
36273626
count = values.len(),
36283627
ty = ty,
36293628
val = val.join(", ")
3630-
)
3629+
),
3630+
llr::ArrayOutput::Vector => {
3631+
format!("std::vector<{ty}>{{ {val} }}", ty = ty, val = val.join(", "))
3632+
}
36313633
}
36323634
}
36333635
Expression::Struct { ty, values } => {

internal/compiler/generator/rust.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ use crate::expression_tree::{BuiltinFunction, EasingCurve, MinMaxOp, OperatorCla
1717
use crate::langtype::{Enumeration, EnumerationValue, Struct, StructName, Type};
1818
use crate::layout::Orientation;
1919
use crate::llr::{
20-
self, EvaluationContext as llr_EvaluationContext, EvaluationScope, Expression, ParentScope,
21-
TypeResolutionContext as _,
20+
self, ArrayOutput, EvaluationContext as llr_EvaluationContext, EvaluationScope, Expression,
21+
ParentScope, TypeResolutionContext as _,
2222
};
2323
use crate::object_tree::Document;
2424
use crate::typeloader::LibraryInfo;
@@ -2362,7 +2362,7 @@ fn compile_expression(expr: &Expression, ctx: &EvaluationContext) -> TokenStream
23622362
) =>
23632363
{
23642364
let path_elements = match from.as_ref() {
2365-
Expression::Array { element_ty: _, values, as_model: _ } => values
2365+
Expression::Array { element_ty: _, values, output: _ } => values
23662366
.iter()
23672367
.map(|path_elem_expr|
23682368
// Close{} is a struct with no fields in markup, and PathElement::Close has no fields
@@ -2612,17 +2612,19 @@ fn compile_expression(expr: &Expression, ctx: &EvaluationContext) -> TokenStream
26122612
}
26132613
)
26142614
}
2615-
Expression::Array { values, element_ty, as_model } => {
2615+
Expression::Array { values, element_ty, output } => {
26162616
let val = values.iter().map(|e| compile_expression(e, ctx));
2617-
if *as_model {
2618-
let rust_element_ty = rust_primitive_type(element_ty).unwrap();
2619-
quote!(sp::ModelRc::new(
2620-
sp::VecModel::<#rust_element_ty>::from(
2621-
sp::vec![#(#val as _),*]
2622-
)
2623-
))
2624-
} else {
2625-
quote!(sp::Slice::from_slice(&[#(#val),*]))
2617+
match output {
2618+
ArrayOutput::Model => {
2619+
let rust_element_ty = rust_primitive_type(element_ty).unwrap();
2620+
quote!(sp::ModelRc::new(
2621+
sp::VecModel::<#rust_element_ty>::from(
2622+
sp::vec![#(#val as _),*]
2623+
)
2624+
))
2625+
}
2626+
ArrayOutput::Slice => quote!(sp::Slice::from_slice(&[#(#val),*])),
2627+
ArrayOutput::Vector => quote!(sp::vec![#(#val as _),*]),
26262628
}
26272629
}
26282630
Expression::Struct { ty, values } => {

internal/compiler/llr/expression.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ use smol_str::SmolStr;
1313
use std::collections::BTreeMap;
1414
use std::rc::Rc;
1515

16+
#[derive(Debug, Clone)]
17+
pub enum ArrayOutput {
18+
Slice,
19+
Model,
20+
Vector,
21+
}
22+
1623
#[derive(Debug, Clone)]
1724
pub enum Expression {
1825
/// A string literal. The .0 is the content of the string, without the quotes
@@ -137,8 +144,8 @@ pub enum Expression {
137144
Array {
138145
element_ty: Type,
139146
values: Vec<Expression>,
140-
/// When true, this should be converted to a model. When false, this should stay as a slice
141-
as_model: bool,
147+
/// Choose what will be generated: a slice, a model, or a vector
148+
output: ArrayOutput,
142149
},
143150
Struct {
144151
ty: Rc<crate::langtype::Struct>,
@@ -252,7 +259,7 @@ impl Expression {
252259
Type::Array(element_ty) => Expression::Array {
253260
element_ty: (**element_ty).clone(),
254261
values: Vec::new(),
255-
as_model: true,
262+
output: ArrayOutput::Model,
256263
},
257264
Type::Struct(s) => Expression::Struct {
258265
ty: s.clone(),

internal/compiler/llr/lower_expression.rs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use super::{
1616
use crate::expression_tree::{BuiltinFunction, Callable, Expression as tree_Expression};
1717
use crate::langtype::{BuiltinPrivateStruct, EnumerationValue, Struct, StructName, Type};
1818
use crate::layout::{GridLayoutCell, Orientation, RowColExpr};
19+
use crate::llr::ArrayOutput as llr_ArrayOutput;
1920
use crate::llr::Expression as llr_Expression;
2021
use crate::namedreference::NamedReference;
2122
use crate::object_tree::{Element, ElementRc, PropertyAnimation};
@@ -144,9 +145,11 @@ pub fn lower_expression(
144145
Callable::Builtin(f) => {
145146
let mut arguments =
146147
arguments.iter().map(|e| lower_expression(e, ctx)).collect::<Vec<_>>();
148+
// https://github.com/rust-lang/rust-clippy/issues/16191
149+
#[allow(clippy::collapsible_if)]
147150
if *f == BuiltinFunction::Translate {
148-
if let llr_Expression::Array { as_model, .. } = &mut arguments[3] {
149-
*as_model = false;
151+
if let llr_Expression::Array { output, .. } = &mut arguments[3] {
152+
*output = llr_ArrayOutput::Slice;
150153
}
151154
#[cfg(feature = "bundle-translations")]
152155
if let Some(translation_builder) = ctx.state.translation_builder.as_mut() {
@@ -212,7 +215,7 @@ pub fn lower_expression(
212215
tree_Expression::Array { element_ty, values } => llr_Expression::Array {
213216
element_ty: element_ty.clone(),
214217
values: values.iter().map(|e| lower_expression(e, ctx)).collect::<_>(),
215-
as_model: true,
218+
output: llr_ArrayOutput::Model,
216219
},
217220
tree_Expression::Struct { ty, values } => llr_Expression::Struct {
218221
ty: ty.clone(),
@@ -628,7 +631,7 @@ fn compute_grid_layout_info(
628631
llr_Expression::Array {
629632
element_ty: Type::Int32,
630633
values: Vec::new(),
631-
as_model: false,
634+
output: llr_ArrayOutput::Slice,
632635
}
633636
} else {
634637
llr_Expression::ReadLocalVariable {
@@ -713,7 +716,7 @@ fn organize_grid_layout(
713716
let roles_expr = llr_Expression::Array {
714717
element_ty: Type::Enumeration(e),
715718
values: roles,
716-
as_model: false,
719+
output: llr_ArrayOutput::Slice,
717720
};
718721
llr_Expression::ExtraBuiltinFunctionCall {
719722
function: "organize_dialog_button_layout".into(),
@@ -729,7 +732,7 @@ fn organize_grid_layout(
729732
llr_Expression::Array {
730733
element_ty: Type::Int32,
731734
values: Vec::new(),
732-
as_model: false,
735+
output: llr_ArrayOutput::Slice,
733736
}
734737
} else {
735738
llr_Expression::ReadLocalVariable {
@@ -810,7 +813,7 @@ fn solve_grid_layout(
810813
// empty array of repeated indices
811814
element_ty: Type::Int32,
812815
values: Vec::new(),
813-
as_model: false,
816+
output: llr_ArrayOutput::Slice,
814817
},
815818
],
816819
return_ty: Type::LayoutCache,
@@ -868,7 +871,7 @@ fn solve_layout(
868871
llr_Expression::Array {
869872
element_ty: Type::Int32,
870873
values: Vec::new(),
871-
as_model: false,
874+
output: llr_ArrayOutput::Slice,
872875
},
873876
],
874877
return_ty: Type::LayoutCache,
@@ -926,7 +929,7 @@ fn box_layout_data(
926929
})
927930
.collect(),
928931
element_ty,
929-
as_model: false,
932+
output: llr_ArrayOutput::Slice,
930933
};
931934
BoxLayoutDataResult { alignment, cells, compute_cells: None }
932935
} else {
@@ -972,7 +975,7 @@ fn grid_layout_cell_constraints(
972975

973976
if repeater_count == 0 {
974977
let cells = llr_Expression::Array {
975-
element_ty: element_ty,
978+
element_ty,
976979
values: layout
977980
.elems
978981
.iter()
@@ -982,7 +985,7 @@ fn grid_layout_cell_constraints(
982985
make_layout_cell_data_struct(layout_info)
983986
})
984987
.collect(),
985-
as_model: false,
988+
output: llr_ArrayOutput::Slice,
986989
};
987990
GridLayoutCellConstraintsResult { cells, compute_cells: None }
988991
} else {
@@ -1066,7 +1069,7 @@ fn grid_layout_input_data(
10661069
)
10671070
})
10681071
.collect(),
1069-
as_model: false,
1072+
output: llr_ArrayOutput::Slice,
10701073
};
10711074
GridLayoutInputDataResult { cells, compute_cells: None }
10721075
} else {
@@ -1244,7 +1247,7 @@ fn compile_path(
12441247
from: llr_Expression::Array {
12451248
element_ty: crate::typeregister::path_element_type(),
12461249
values: elements,
1247-
as_model: false,
1250+
output: llr_ArrayOutput::Slice,
12481251
}
12491252
.into(),
12501253
to: Type::PathData,
@@ -1328,15 +1331,15 @@ fn compile_path(
13281331
llr_Expression::Array {
13291332
element_ty: event_type,
13301333
values: events,
1331-
as_model: false,
1334+
output: llr_ArrayOutput::Slice,
13321335
},
13331336
),
13341337
(
13351338
SmolStr::new_static("points"),
13361339
llr_Expression::Array {
13371340
element_ty: point_type,
13381341
values: points,
1339-
as_model: false,
1342+
output: llr_ArrayOutput::Slice,
13401343
},
13411344
),
13421345
])

0 commit comments

Comments
 (0)