Skip to content

Commit 46f94e8

Browse files
authored
cgen: fix autostr of shared fields (#14455)
1 parent a52fbc5 commit 46f94e8

File tree

2 files changed

+36
-16
lines changed

2 files changed

+36
-16
lines changed

vlib/v/gen/c/auto_str_methods.v

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -910,7 +910,16 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, str_fn_name stri
910910
fn_body.writeln('\tstring res = str_intp( ${info.fields.len * 4 + 3}, _MOV((StrIntpData[]){')
911911
fn_body.writeln('\t\t{_SLIT("$clean_struct_v_type_name{\\n"), 0, {.d_c=0}},')
912912
for i, field in info.fields {
913-
mut ptr_amp := if field.typ.is_ptr() { '&' } else { '' }
913+
ftyp_noshared := if field.typ.has_flag(.shared_f) {
914+
field.typ.deref().clear_flag(.shared_f)
915+
} else {
916+
field.typ
917+
}
918+
mut ptr_amp := if ftyp_noshared.is_ptr() {
919+
'&'
920+
} else {
921+
''
922+
}
914923
base_fmt := g.type_to_fmt(g.unwrap_generic(field.typ))
915924

916925
// 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
933942

934943
// custom methods management
935944
sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info()
936-
sftyp := g.typ(field.typ)
945+
sftyp := g.typ(ftyp_noshared)
937946
mut field_styp := sftyp.replace('*', '')
938947
field_styp_fn_name := if sym_has_str_method {
939948
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
943952
}
944953
field_fn_name
945954
} else {
946-
g.get_str_fn(field.typ)
955+
g.get_str_fn(ftyp_noshared)
947956
}
948957

949958
// 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
960969
if field.typ in ast.cptr_types {
961970
func = '(voidptr) it.$field.name'
962971
caller_should_free = false
963-
} else if field.typ.is_ptr() {
972+
} else if ftyp_noshared.is_ptr() {
964973
// reference types can be "nil"
965974
funcprefix += 'isnil(it.${c_name(field.name)})'
966975
funcprefix += ' ? _SLIT("nil") : '
@@ -999,34 +1008,35 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, str_fn_name stri
9991008
fn_body.writeln('\t}));')
10001009
}
10011010

1002-
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) {
1011+
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) {
10031012
$if trace_autostr ? {
10041013
eprintln('> struct_auto_str_func: $sym.name | field_type.debug() | $fn_name | $field_name | $has_custom_str | $expects_ptr')
10051014
}
1015+
field_type := if _field_type.has_flag(.shared_f) { _field_type.deref() } else { _field_type }
1016+
sufix := if field_type.has_flag(.shared_f) { '->val' } else { '' }
10061017
deref, _ := deref_kind(expects_ptr, field_type.is_ptr(), field_type)
10071018
if sym.kind == .enum_ {
10081019
return '${fn_name}(${deref}it.${c_name(field_name)})', true
10091020
} else if should_use_indent_func(sym.kind) {
1010-
obj := 'it.${c_name(field_name)}'
1021+
obj := '${deref}it.${c_name(field_name)}$sufix'
10111022
if has_custom_str {
1012-
return '${fn_name}($deref$obj)', true
1023+
return '${fn_name}($obj)', true
10131024
}
1014-
return 'indent_${fn_name}($deref$obj, indent_count + 1)', true
1025+
return 'indent_${fn_name}($obj, indent_count + 1)', true
10151026
} else if sym.kind in [.array, .array_fixed, .map, .sum_type] {
1027+
obj := '${deref}it.${c_name(field_name)}$sufix'
10161028
if has_custom_str {
1017-
return '${fn_name}(${deref}it.${c_name(field_name)})', true
1029+
return '${fn_name}($obj)', true
10181030
}
1019-
return 'indent_${fn_name}(${deref}it.${c_name(field_name)}, indent_count + 1)', true
1031+
return 'indent_${fn_name}($obj, indent_count + 1)', true
10201032
} else if sym.kind == .function {
10211033
return '${fn_name}()', true
1034+
} else if sym.kind == .chan {
1035+
return '${fn_name}(${deref}it.${c_name(field_name)}$sufix)', true
10221036
} else {
1023-
if sym.kind == .chan {
1024-
return '${fn_name}(${deref}it.${c_name(field_name)})', true
1025-
}
10261037
mut method_str := 'it.${c_name(field_name)}'
1027-
mut caller_should_free := false
10281038
if sym.kind == .bool {
1029-
method_str += ' ? _SLIT("true") : _SLIT("false")'
1039+
return '$method_str ? _SLIT("true") : _SLIT("false")', false
10301040
} else if (field_type.is_int_valptr() || field_type.is_float_valptr())
10311041
&& field_type.is_ptr() && !expects_ptr {
10321042
// 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
10451055
fmt_type := StrIntpType.si_i32
10461056
return 'str_intp(1, _MOV((StrIntpData[]){{_SLIT0, ${u32(fmt_type) | 0xfe00}, {.d_i32 = *$method_str }}}))', true
10471057
}
1048-
return method_str, caller_should_free
1058+
return method_str, false
10491059
}
10501060
}

vlib/v/tests/shared_str_test.v

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
struct AA {
2+
a shared []int
3+
}
4+
5+
fn test_shared_str() {
6+
a := AA{
7+
a: [1, 2]
8+
}
9+
assert a.str() == 'AA{\n a: [1, 2]\n}'
10+
}

0 commit comments

Comments
 (0)