diff --git a/vlib/v/gen/c/auto_str_methods.v b/vlib/v/gen/c/auto_str_methods.v index 2657bc40044165..a7c53458cd6a91 100644 --- a/vlib/v/gen/c/auto_str_methods.v +++ b/vlib/v/gen/c/auto_str_methods.v @@ -589,7 +589,8 @@ fn (mut g Gen) gen_str_for_array(info ast.Array, styp string, str_fn_name string } mut typ := info.elem_type mut sym := g.table.sym(info.elem_type) - if mut sym.info is ast.Alias { + is_option := typ.has_flag(.option) + if !is_option && mut sym.info is ast.Alias { typ = sym.info.parent_type sym = g.table.sym(typ) } @@ -628,7 +629,12 @@ fn (mut g Gen) gen_str_for_array(info ast.Array, styp string, str_fn_name string g.auto_str_funcs.writeln('\t\t}') } } else { - g.auto_str_funcs.writeln('\t\tstring x = indent_${elem_str_fn_name}(it, indent_count);') + prefix := if !is_option && sym.is_c_struct() && str_method_expects_ptr { + '&' + } else { + '' + } + g.auto_str_funcs.writeln('\t\tstring x = indent_${elem_str_fn_name}(${prefix}it, indent_count);') } } else if sym.kind in [.f32, .f64] { if sym.kind == .f32 { @@ -763,19 +769,20 @@ fn (mut g Gen) gen_str_for_map(info ast.Map, styp string, str_fn_name string) { key_sym = g.table.sym(key_typ) } key_styp := g.typ(key_typ) - key_str_fn_name := key_styp.replace('*', '') + '_str' + key_str_fn_name := styp_to_str_fn_name(key_styp) if !key_sym.has_method('str') { g.get_str_fn(key_typ) } mut val_typ := info.value_type mut val_sym := g.table.sym(val_typ) - if mut val_sym.info is ast.Alias { + is_option := val_typ.has_flag(.option) + if !is_option && mut val_sym.info is ast.Alias { val_typ = val_sym.info.parent_type val_sym = g.table.sym(val_typ) } val_styp := g.typ(val_typ) - mut elem_str_fn_name := val_styp.replace('*', '') + '_str' + mut elem_str_fn_name := styp_to_str_fn_name(val_styp) mut receiver_is_ptr := false fn_str := val_sym.find_method_with_generic_parent('str') or { ast.Fn{} } @@ -836,8 +843,12 @@ fn (mut g Gen) gen_str_for_map(info ast.Map, styp string, str_fn_name string) { g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${tmp_str});') } } else if should_use_indent_func(val_sym.kind) && fn_str.name != 'str' { - ptr_str := '*'.repeat(val_typ.nr_muls()) - g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, indent_${elem_str_fn_name}(*${ptr_str}(${val_styp}*)DenseArray_value(&m.key_values, i), indent_count));') + ptr_str := if !is_option && val_sym.is_c_struct() && str_method_expects_ptr { + '' + } else { + '*'.repeat(val_typ.nr_muls() + 1) + } + g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, indent_${elem_str_fn_name}(${ptr_str}(${val_styp}*)DenseArray_value(&m.key_values, i), indent_count));') } else if val_sym.kind in [.f32, .f64] { tmp_val := '*(${val_styp}*)DenseArray_value(&m.key_values, i)' if val_typ.has_flag(.option) { diff --git a/vlib/v/gen/c/str.v b/vlib/v/gen/c/str.v index c8f0f8ca997730..57cac60880ae03 100644 --- a/vlib/v/gen/c/str.v +++ b/vlib/v/gen/c/str.v @@ -212,7 +212,7 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype ast.Type) { str_fn_name := g.get_str_fn(typ) g.write('${str_fn_name}(') if sym.kind != .function { - if str_method_expects_ptr && !is_ptr { + if str_method_expects_ptr && !is_ptr && !typ.has_flag(.option) { g.write('&') } else if (!str_method_expects_ptr && is_ptr && !is_shared) || is_var_mut { g.write('*') diff --git a/vlib/v/tests/c_structs/cstruct_arr_map_test.c.v b/vlib/v/tests/c_structs/cstruct_arr_map_test.c.v new file mode 100644 index 00000000000000..c817296d5afaae --- /dev/null +++ b/vlib/v/tests/c_structs/cstruct_arr_map_test.c.v @@ -0,0 +1,46 @@ +module main + +#include "@VMODROOT/cstruct.h" + +@[typedef] +struct C.Foo { + a int = 100 +} + +type Foo = C.Foo + +struct GameObject { +mut: + map_a map[string]Foo + map_b map[string]?Foo + b []Foo + c []?Foo +} + +fn test_main() { + mut g := GameObject{} + g.map_a['a'] = Foo{} + g.map_b['a'] = ?Foo{ + a: 123 + } + g.map_b['aa'] = ?Foo{} + g.b << Foo{} + g.c << ?Foo{ + a: 123 + } + g.c << ?Foo{} + println(g) + dump(g) + assert g.map_a.len == 1 + assert g.map_b.len == 2 + assert g.b.len == 1 + assert g.c.len == 2 + assert g.c[0] != none + assert g.c[1] == none + + t := ?Foo{ + a: 123 + } + dump(t) + assert t?.a == 123 +}