diff --git a/vlib/sync/channels.v b/vlib/sync/channels.v index 1f1e630862..7802f84b0c 100644 --- a/vlib/sync/channels.v +++ b/vlib/sync/channels.v @@ -136,6 +136,10 @@ fn new_channel_st(n u32, st u32) &Channel { return ch } +pub fn (ch &Channel) auto_str(typename string) string { + return 'chan $typename{cap: $ch.cap, closed: $ch.closed}' +} + pub fn (mut ch Channel) close() { open_val := u16(0) if !C.atomic_compare_exchange_strong_u16(&ch.closed, &open_val, 1) { diff --git a/vlib/v/gen/c/auto_str_methods.v b/vlib/v/gen/c/auto_str_methods.v index c814621c95..b8298de81c 100644 --- a/vlib/v/gen/c/auto_str_methods.v +++ b/vlib/v/gen/c/auto_str_methods.v @@ -168,6 +168,9 @@ fn (mut g Gen) gen_str_for_type(typ ast.Type) string { ast.Interface { g.gen_str_for_interface(sym.info, styp, str_fn_name) } + ast.Chan { + g.gen_str_for_chan(sym.info, styp, str_fn_name) + } else { verror("could not generate string method $str_fn_name for type '$styp'") } @@ -489,6 +492,12 @@ fn (mut g Gen) gen_str_for_fn_type(info ast.FnType, styp string, str_fn_name str g.auto_str_funcs.writeln('static string ${str_fn_name}() { return _SLIT("${g.fn_decl_str(info)}");}') } +fn (mut g Gen) gen_str_for_chan(info ast.Chan, styp string, str_fn_name string) { + elem_type_name := util.strip_main_name(g.table.get_type_name(g.unwrap_generic(info.elem_type))) + g.type_definitions.writeln('static string ${str_fn_name}($styp x); // auto') + g.auto_str_funcs.writeln('static string ${str_fn_name}($styp x) { return sync__Channel_auto_str(x, _SLIT("$elem_type_name")); }') +} + [inline] fn styp_to_str_fn_name(styp string) string { return styp.replace_each(['*', '', '.', '__', ' ', '__']) + '_str' diff --git a/vlib/v/markused/markused.v b/vlib/v/markused/markused.v index 11f82df8c2..7d75135889 100644 --- a/vlib/v/markused/markused.v +++ b/vlib/v/markused/markused.v @@ -85,6 +85,7 @@ pub fn mark_used(mut table ast.Table, pref &pref.Preferences, ast_files []&ast.F '21.clone_static', '21.first', '21.last', + '21.pointers' /* TODO: handle generic methods calling array primitives more precisely in pool_test.v */, '21.reverse', '21.repeat', '21.slice', @@ -141,7 +142,9 @@ pub fn mark_used(mut table ast.Table, pref &pref.Preferences, ast_files []&ast.F all_fn_root_names << k continue } - if k.ends_with('.str') { + // auto generated string interpolation functions, may + // call .str or .auto_str methods for user types: + if k.ends_with('.str') || k.ends_with('.auto_str') { all_fn_root_names << k continue } @@ -153,11 +156,25 @@ pub fn mark_used(mut table ast.Table, pref &pref.Preferences, ast_files []&ast.F all_fn_root_names << k continue } + // sync: + if k == 'sync.new_channel_st' { + all_fn_root_names << k + continue + } + if k == 'sync.channel_select' { + all_fn_root_names << k + continue + } + if method_receiver_typename == '&sync.Channel' { + all_fn_root_names << k + continue + } if k.ends_with('.lock') || k.ends_with('.unlock') || k.ends_with('.rlock') || k.ends_with('.runlock') { all_fn_root_names << k continue } + // testing framework: if pref.is_test { if k.starts_with('test_') || k.contains('.test_') { all_fn_root_names << k @@ -169,6 +186,8 @@ pub fn mark_used(mut table ast.Table, pref &pref.Preferences, ast_files []&ast.F continue } } + // public/exported functions can not be skipped, + // especially when producing a shared library: if mfn.is_pub && pref.is_shared { all_fn_root_names << k continue diff --git a/vlib/v/tests/channels_test.v b/vlib/v/tests/channels_test.v new file mode 100644 index 0000000000..09c38070bd --- /dev/null +++ b/vlib/v/tests/channels_test.v @@ -0,0 +1,29 @@ +struct St1 { + val int = 5 + another chan f64 +} + +fn fn1(c chan St1) string { + println('1') + println(c) + x := <-c + println(x) + return x.str() +} + +fn test_printing_of_channels() { + ch := chan St1{cap: 10} + fch := chan f64{cap: 100} + ch <- St1{ + val: 1000 + another: fch + } + res := (go fn1(ch)).wait() + println(res) + println(ch) + assert res.str().contains('another: ') + assert ch.str() == 'chan St1{cap: 10, closed: 0}' + assert fch.str() == 'chan f64{cap: 100, closed: 0}' + fch.close() + assert fch.str() == 'chan f64{cap: 100, closed: 1}' +}