From e563c8f7135767cb64127e4cbdd668cf75320fe3 Mon Sep 17 00:00:00 2001 From: kbkpbot Date: Tue, 4 Nov 2025 23:16:30 +0800 Subject: [PATCH] cgen: fix infix expr ComptimeSelector type (fix #25659) (#25662) --- vlib/v/gen/c/infix.v | 14 +++- ...omptime_for_struct_field_infix_expr_test.v | 84 +++++++++++++++++++ 2 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 vlib/v/tests/comptime/comptime_for_struct_field_infix_expr_test.v diff --git a/vlib/v/gen/c/infix.v b/vlib/v/gen/c/infix.v index 0361a94f6..19400442a 100644 --- a/vlib/v/gen/c/infix.v +++ b/vlib/v/gen/c/infix.v @@ -1033,8 +1033,18 @@ fn (mut g Gen) infix_expr_arithmetic_op(node ast.InfixExpr) { // infix_expr_left_shift_op generates code for the `<<` operator // This can either be a value pushed into an array or a bit shift fn (mut g Gen) infix_expr_left_shift_op(node ast.InfixExpr) { - left := g.unwrap(node.left_type) - right := g.unwrap(node.right_type) + left_type := if node.left is ast.ComptimeSelector { + g.type_resolver.get_type(node.left) + } else { + node.left_type + } + right_type := if node.right is ast.ComptimeSelector { + g.type_resolver.get_type(node.right) + } else { + node.right_type + } + left := g.unwrap(left_type) + right := g.unwrap(right_type) if left.unaliased_sym.kind == .array { // arr << val tmp_var := g.new_tmp_var() diff --git a/vlib/v/tests/comptime/comptime_for_struct_field_infix_expr_test.v b/vlib/v/tests/comptime/comptime_for_struct_field_infix_expr_test.v new file mode 100644 index 000000000..6c23e8620 --- /dev/null +++ b/vlib/v/tests/comptime/comptime_for_struct_field_infix_expr_test.v @@ -0,0 +1,84 @@ +pub type Any = string | []Any | map[string]Any + +pub fn decode_struct[T](value map[string]Any, mut t T) ! { + $for f in T.fields { + key := f.name + vals := value[key] or { '' } + if vals is string && vals != '' { + $if f is string { + t.$(f.name) = vals + } + } else if vals is map[string]Any { + if f.is_struct { + decode_struct(vals, mut t.$(f.name))! + } + } else if vals is []Any { + $if f is $array { + for val in vals { + if val is map[string]Any { + mut elem := array_element(t.$(f.name)) + $if elem is $struct { + decode_struct(val, mut elem)! + t.$(f.name) << elem + } + } + } + } + } + } +} + +fn array_element[T](a []T) T { + return T{} +} + +struct Element { + name string +} + +struct Set { + name string + elems []Element +} + +struct Tree { + name string + children []Tree +} + +const set_any = { + 'name': Any('1') + 'elems': Any([ + Any({ + 'name': Any('2') + }), + { + 'name': Any('3') + }, + ]) +} +const tree_any = { + 'name': Any('1') + 'children': Any([ + Any({ + 'name': Any('2') + }), + { + 'name': Any('3') + }, + ]) +} + +fn test_main() { + mut set := Set{} + decode_struct(set_any, mut set)! + assert set.name == '1' + assert set.elems[0].name == '2' + assert set.elems[1].name == '3' + + mut tree := Tree{} + decode_struct(tree_any, mut tree)! + assert tree.name == '1' + assert tree.children[0].name == '2' + assert tree.children[1].name == '3' +} -- 2.39.5