From 46f94e8d68831bd344b573e4cdc341ad30d076d5 Mon Sep 17 00:00:00 2001 From: crthpl <56052645+crthpl@users.noreply.github.com> Date: Thu, 19 May 2022 07:00:27 -0700 Subject: [PATCH] cgen: fix autostr of shared fields (#14455) --- vlib/v/gen/c/auto_str_methods.v | 42 ++++++++++++++++++++------------- vlib/v/tests/shared_str_test.v | 10 ++++++++ 2 files changed, 36 insertions(+), 16 deletions(-) create mode 100644 vlib/v/tests/shared_str_test.v diff --git a/vlib/v/gen/c/auto_str_methods.v b/vlib/v/gen/c/auto_str_methods.v index 341dd732ba..c83aa3a055 100644 --- a/vlib/v/gen/c/auto_str_methods.v +++ b/vlib/v/gen/c/auto_str_methods.v @@ -910,7 +910,16 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, str_fn_name stri fn_body.writeln('\tstring res = str_intp( ${info.fields.len * 4 + 3}, _MOV((StrIntpData[]){') fn_body.writeln('\t\t{_SLIT("$clean_struct_v_type_name{\\n"), 0, {.d_c=0}},') for i, field in info.fields { - mut ptr_amp := if field.typ.is_ptr() { '&' } else { '' } + ftyp_noshared := if field.typ.has_flag(.shared_f) { + field.typ.deref().clear_flag(.shared_f) + } else { + field.typ + } + mut ptr_amp := if ftyp_noshared.is_ptr() { + '&' + } else { + '' + } base_fmt := g.type_to_fmt(g.unwrap_generic(field.typ)) // manage prefix and quote symbol for the filed @@ -933,7 +942,7 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, str_fn_name stri // custom methods management sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info() - sftyp := g.typ(field.typ) + sftyp := g.typ(ftyp_noshared) mut field_styp := sftyp.replace('*', '') field_styp_fn_name := if sym_has_str_method { mut field_fn_name := '${field_styp}_str' @@ -943,7 +952,7 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, str_fn_name stri } field_fn_name } else { - g.get_str_fn(field.typ) + g.get_str_fn(ftyp_noshared) } // manage the fact hat with float we use always the g representation @@ -960,7 +969,7 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, str_fn_name stri if field.typ in ast.cptr_types { func = '(voidptr) it.$field.name' caller_should_free = false - } else if field.typ.is_ptr() { + } else if ftyp_noshared.is_ptr() { // reference types can be "nil" funcprefix += 'isnil(it.${c_name(field.name)})' funcprefix += ' ? _SLIT("nil") : ' @@ -999,34 +1008,35 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, str_fn_name stri fn_body.writeln('\t}));') } -fn struct_auto_str_func(sym &ast.TypeSymbol, field_type ast.Type, fn_name string, field_name string, has_custom_str bool, expects_ptr bool) (string, bool) { +fn struct_auto_str_func(sym &ast.TypeSymbol, _field_type ast.Type, fn_name string, field_name string, has_custom_str bool, expects_ptr bool) (string, bool) { $if trace_autostr ? { eprintln('> struct_auto_str_func: $sym.name | field_type.debug() | $fn_name | $field_name | $has_custom_str | $expects_ptr') } + field_type := if _field_type.has_flag(.shared_f) { _field_type.deref() } else { _field_type } + sufix := if field_type.has_flag(.shared_f) { '->val' } else { '' } deref, _ := deref_kind(expects_ptr, field_type.is_ptr(), field_type) if sym.kind == .enum_ { return '${fn_name}(${deref}it.${c_name(field_name)})', true } else if should_use_indent_func(sym.kind) { - obj := 'it.${c_name(field_name)}' + obj := '${deref}it.${c_name(field_name)}$sufix' if has_custom_str { - return '${fn_name}($deref$obj)', true + return '${fn_name}($obj)', true } - return 'indent_${fn_name}($deref$obj, indent_count + 1)', true + return 'indent_${fn_name}($obj, indent_count + 1)', true } else if sym.kind in [.array, .array_fixed, .map, .sum_type] { + obj := '${deref}it.${c_name(field_name)}$sufix' if has_custom_str { - return '${fn_name}(${deref}it.${c_name(field_name)})', true + return '${fn_name}($obj)', true } - return 'indent_${fn_name}(${deref}it.${c_name(field_name)}, indent_count + 1)', true + return 'indent_${fn_name}($obj, indent_count + 1)', true } else if sym.kind == .function { return '${fn_name}()', true + } else if sym.kind == .chan { + return '${fn_name}(${deref}it.${c_name(field_name)}$sufix)', true } else { - if sym.kind == .chan { - return '${fn_name}(${deref}it.${c_name(field_name)})', true - } mut method_str := 'it.${c_name(field_name)}' - mut caller_should_free := false if sym.kind == .bool { - method_str += ' ? _SLIT("true") : _SLIT("false")' + return '$method_str ? _SLIT("true") : _SLIT("false")', false } else if (field_type.is_int_valptr() || field_type.is_float_valptr()) && field_type.is_ptr() && !expects_ptr { // ptr int can be "nil", so this needs to be casted to a string @@ -1045,6 +1055,6 @@ fn struct_auto_str_func(sym &ast.TypeSymbol, field_type ast.Type, fn_name string fmt_type := StrIntpType.si_i32 return 'str_intp(1, _MOV((StrIntpData[]){{_SLIT0, ${u32(fmt_type) | 0xfe00}, {.d_i32 = *$method_str }}}))', true } - return method_str, caller_should_free + return method_str, false } } diff --git a/vlib/v/tests/shared_str_test.v b/vlib/v/tests/shared_str_test.v new file mode 100644 index 0000000000..f97820218b --- /dev/null +++ b/vlib/v/tests/shared_str_test.v @@ -0,0 +1,10 @@ +struct AA { + a shared []int +} + +fn test_shared_str() { + a := AA{ + a: [1, 2] + } + assert a.str() == 'AA{\n a: [1, 2]\n}' +}