From 37618c946542cbcaa3ecec4f1610c7a974eaa981 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Tue, 23 May 2023 09:42:53 -0300 Subject: [PATCH] cgen, checker: fix comptime assigning to sumtype or indexexpr (#18240) --- vlib/v/checker/assign.v | 6 +- vlib/v/gen/c/assign.v | 15 ++++- vlib/v/gen/c/cgen.v | 2 +- vlib/v/tests/comptime_sumtype_cast_2_test.v | 38 +++++++++++++ vlib/v/tests/comptime_sumtype_cast_3_test.v | 61 +++++++++++++++++++++ 5 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 vlib/v/tests/comptime_sumtype_cast_2_test.v create mode 100644 vlib/v/tests/comptime_sumtype_cast_3_test.v diff --git a/vlib/v/checker/assign.v b/vlib/v/checker/assign.v index dd31975b17..fc165b865d 100644 --- a/vlib/v/checker/assign.v +++ b/vlib/v/checker/assign.v @@ -336,8 +336,10 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { } } if right is ast.ComptimeSelector { - left.obj.ct_type_var = .field_var - left.obj.typ = c.comptime_fields_default_type + if is_decl { + left.obj.ct_type_var = .field_var + left.obj.typ = c.comptime_fields_default_type + } } else if right is ast.Ident && (right as ast.Ident).obj is ast.Var && (right as ast.Ident).or_expr.kind == .absent { if ((right as ast.Ident).obj as ast.Var).ct_type_var != .no_comptime { diff --git a/vlib/v/gen/c/assign.v b/vlib/v/gen/c/assign.v index 68012552d0..59363ad0ab 100644 --- a/vlib/v/gen/c/assign.v +++ b/vlib/v/gen/c/assign.v @@ -238,9 +238,13 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) { } else if val is ast.ComptimeSelector { key_str := g.get_comptime_selector_key_type(val) if key_str != '' { - var_type = g.comptime_var_type_map[key_str] or { var_type } - val_type = var_type - left.obj.typ = var_type + if is_decl { + var_type = g.comptime_var_type_map[key_str] or { var_type } + val_type = var_type + left.obj.typ = var_type + } else { + val_type = g.comptime_var_type_map[key_str] or { var_type } + } } } else if val is ast.ComptimeCall { key_str := '${val.method_name}.return_type' @@ -283,6 +287,11 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) { val_type = g.comptime_var_type_map[key_str_right] or { var_type } } } + } else if mut left is ast.IndexExpr && val is ast.ComptimeSelector { + key_str := g.get_comptime_selector_key_type(val) + if key_str != '' { + val_type = g.comptime_var_type_map[key_str] or { var_type } + } } mut styp := g.typ(var_type) mut is_fixed_array_init := false diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 53348ac37e..0c89bc3c45 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -4263,7 +4263,7 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) { node_typ := g.unwrap_generic(node.typ) mut expr_type := node.expr_type sym := g.table.sym(node_typ) - if node.expr is ast.Ident && g.is_comptime_var(node.expr) { + if (node.expr is ast.Ident && g.is_comptime_var(node.expr)) || node.expr is ast.ComptimeSelector { expr_type = g.unwrap_generic(g.get_comptime_var_type(node.expr)) } if sym.kind in [.sum_type, .interface_] { diff --git a/vlib/v/tests/comptime_sumtype_cast_2_test.v b/vlib/v/tests/comptime_sumtype_cast_2_test.v new file mode 100644 index 0000000000..db753135af --- /dev/null +++ b/vlib/v/tests/comptime_sumtype_cast_2_test.v @@ -0,0 +1,38 @@ +pub type Any = bool | int | map[string]Any | string + +struct StructType[T] { +mut: + val T +} + +fn map_from[T](t T) Any { + mut value := Any{} + $if T is $struct { + $for field in T.fields { + println(t.$(field.name)) + value = t.$(field.name) + value = Any(t.$(field.name)) + } + } + return value +} + +fn test_generic_struct_with_sumtype() { + struct_type := StructType[string]{ + val: 'true' + } + struct_type2 := StructType[int]{ + val: 1 + } + array_of_struct := [struct_type, struct_type] + + for variable in array_of_struct { + assert map_from(variable) == Any('true') + } + + array_of_struct2 := [struct_type2, struct_type2] + + for variable in array_of_struct2 { + assert map_from(variable) == Any(1) + } +} diff --git a/vlib/v/tests/comptime_sumtype_cast_3_test.v b/vlib/v/tests/comptime_sumtype_cast_3_test.v new file mode 100644 index 0000000000..5e316db1c6 --- /dev/null +++ b/vlib/v/tests/comptime_sumtype_cast_3_test.v @@ -0,0 +1,61 @@ +pub type Any = bool | int | map[string]Any | string + +struct StructType[T] { +mut: + val T +} + +fn map_from[T](t T) map[string]Any { + mut m := map[string]Any{} + $if T is $struct { + $for field in T.fields { + key := field.name + m[key] = t.$(field.name) + } + } + return m +} + +fn test_struct_to_map_string() { + array_of_struct := [StructType[string]{ + val: 'true' + }, StructType[string]{ + val: 'false' + }] + + mut array_of_map := []Any{} + + for variable in array_of_struct { + array_of_map << map_from(variable) + } + + println(array_of_map) + assert array_of_map[0] == Any({ + 'val': Any('true') + }) + assert array_of_map[1] == Any({ + 'val': Any('false') + }) +} + +fn test_struct_to_map_bool() { + array_of_struct := [StructType[bool]{ + val: true + }, StructType[bool]{ + val: false + }] + + mut array_of_map := []Any{} + + for variable in array_of_struct { + array_of_map << map_from(variable) + } + + println(array_of_map) + assert array_of_map[0] == Any({ + 'val': Any(true) + }) + assert array_of_map[1] == Any({ + 'val': Any(false) + }) +}