diff --git a/cmd/tools/vast/vast.v b/cmd/tools/vast/vast.v index 1230322173..f6dd918a4f 100644 --- a/cmd/tools/vast/vast.v +++ b/cmd/tools/vast/vast.v @@ -1589,6 +1589,7 @@ fn (t Tree) map_init(node ast.MapInit) &Node { obj.add_terse('value_type', t.type_node(node.value_type)) obj.add_terse('keys', t.array_node_expr(node.keys)) obj.add_terse('vals', t.array_node_expr(node.vals)) + obj.add_terse('val_types', t.array_node_type(node.val_types)) obj.add('comments', t.two_dimension_comment(node.comments)) obj.add('pre_cmnts', t.array_node_comment(node.pre_cmnts)) obj.add('pos', t.pos(node.pos)) diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index b169da1cf4..aed4c8ccbb 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -1200,6 +1200,7 @@ pub: pub mut: keys []Expr vals []Expr + val_types []Type typ Type key_type Type value_type Type diff --git a/vlib/v/checker/containers.v b/vlib/v/checker/containers.v index 39fbb188e9..ff24d3bb86 100644 --- a/vlib/v/checker/containers.v +++ b/vlib/v/checker/containers.v @@ -247,6 +247,7 @@ pub fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type { if node.vals[0].is_auto_deref_var() { val0_type = val0_type.deref() } + node.val_types << val0_type } mut same_key_type := true for i, key in node.keys { @@ -258,6 +259,7 @@ pub fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type { key_type := c.expr(key) c.expected_type = val0_type val_type := c.expr(val) + node.val_types << val_type if !c.check_types(key_type, key0_type) || (i == 0 && key_type.is_number() && key0_type.is_number() && key0_type != ast.mktyp(key_type)) { msg := c.expected_msg(key_type, key0_type) diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 23f9fcaaff..184d07219a 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -4167,9 +4167,9 @@ fn (mut g Gen) map_init(node ast.MapInit) { unwrap_val_typ := g.unwrap_generic(node.value_type) key_typ_str := g.typ(unwrap_key_typ) value_typ_str := g.typ(unwrap_val_typ) - value_typ := g.table.sym(unwrap_val_typ) - key_typ := g.table.final_sym(unwrap_key_typ) - hash_fn, key_eq_fn, clone_fn, free_fn := g.map_fn_ptrs(key_typ) + value_sym := g.table.sym(unwrap_val_typ) + key_sym := g.table.final_sym(unwrap_key_typ) + hash_fn, key_eq_fn, clone_fn, free_fn := g.map_fn_ptrs(key_sym) size := node.vals.len mut shared_styp := '' // only needed for shared &[]{...} mut styp := '' @@ -4198,7 +4198,7 @@ fn (mut g Gen) map_init(node ast.MapInit) { } } if size > 0 { - if value_typ.kind == .function { + if value_sym.kind == .function { g.write('new_map_init${noscan}($hash_fn, $key_eq_fn, $clone_fn, $free_fn, $size, sizeof($key_typ_str), sizeof(voidptr), _MOV(($key_typ_str[$size]){') } else { g.write('new_map_init${noscan}($hash_fn, $key_eq_fn, $clone_fn, $free_fn, $size, sizeof($key_typ_str), sizeof($value_typ_str), _MOV(($key_typ_str[$size]){') @@ -4207,16 +4207,20 @@ fn (mut g Gen) map_init(node ast.MapInit) { g.expr(expr) g.write(', ') } - if value_typ.kind == .function { + if value_sym.kind == .function { g.write('}), _MOV((voidptr[$size]){') } else { g.write('}), _MOV(($value_typ_str[$size]){') } - for expr in node.vals { + for i, expr in node.vals { if expr.is_auto_deref_var() { g.write('*') } - g.expr(expr) + if value_sym.kind == .sum_type { + g.expr_with_cast(expr, node.val_types[i], unwrap_val_typ) + } else { + g.expr(expr) + } g.write(', ') } g.write('}))') diff --git a/vlib/v/tests/map_sumtype_value_init_test.v b/vlib/v/tests/map_sumtype_value_init_test.v new file mode 100644 index 0000000000..f185446e3c --- /dev/null +++ b/vlib/v/tests/map_sumtype_value_init_test.v @@ -0,0 +1,18 @@ +type Child = Tree | string + +struct Tree { + name string + child map[string]Child +} + +fn test_map_sumtype_value_init() { + tree := Tree{ + name: 'foo' + child: { + 'a': 'value' + } + } + println(tree) + ret := tree.child['a'] or { Child('') } + assert ret == Child('value') +}