From 8d9af2e4a149a65cb62060c4e129da4b49437dbd Mon Sep 17 00:00:00 2001 From: yuyi Date: Sun, 7 Aug 2022 00:07:33 +0800 Subject: [PATCH] cgen: fix nested generic fn call with reference argument (#15353) --- vlib/v/gen/c/fn.v | 9 ++-- ...ric_fn_call_with_reference_argument_test.v | 2 +- .../dump_nested_generic_fn_call_ref_arg.out | 23 ++++++++++ .../dump_nested_generic_fn_call_ref_arg.vv | 44 +++++++++++++++++++ 4 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.out create mode 100644 vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index c41e673cb6..81cc4f364d 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -1208,7 +1208,8 @@ fn (mut g Gen) fn_call(node ast.CallExpr) { if g.comptime_for_field_type != 0 && g.inside_comptime_for_field { name = g.generic_fn_name([g.comptime_for_field_type], name, false) } else { - name = g.generic_fn_name(node.concrete_types, name, false) + concrete_types := node.concrete_types.map(g.unwrap_generic(it)) + name = g.generic_fn_name(concrete_types, name, false) } } } @@ -1492,7 +1493,7 @@ fn (mut g Gen) call_args(node ast.CallExpr) { } else { node.args } - mut expected_types := node.expected_arg_types + mut expected_types := node.expected_arg_types.map(g.unwrap_generic(it)) // unwrap generics fn/method arguments to concretes if node.concrete_types.len > 0 && node.concrete_types.all(!it.has_flag(.generic)) { if node.is_method { @@ -1924,13 +1925,13 @@ fn (mut g Gen) keep_alive_call_postgen(node ast.CallExpr, tmp_cnt_save int) { [inline] fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type ast.Type, lang ast.Language) { + arg_typ := g.unwrap_generic(arg.typ) exp_is_ptr := expected_type.is_ptr() || expected_type.idx() in ast.pointer_type_idxs - arg_is_ptr := arg.typ.is_ptr() || arg.typ.idx() in ast.pointer_type_idxs + arg_is_ptr := arg_typ.is_ptr() || arg_typ.idx() in ast.pointer_type_idxs if expected_type == 0 { g.checker_bug('ref_or_deref_arg expected_type is 0', arg.pos) } exp_sym := g.table.sym(expected_type) - arg_typ := g.unwrap_generic(arg.typ) mut needs_closing := false if arg.is_mut && !exp_is_ptr { g.write('&/*mut*/') diff --git a/vlib/v/tests/generic_fn_call_with_reference_argument_test.v b/vlib/v/tests/generic_fn_call_with_reference_argument_test.v index e4d9944cdb..bc62ee4e56 100644 --- a/vlib/v/tests/generic_fn_call_with_reference_argument_test.v +++ b/vlib/v/tests/generic_fn_call_with_reference_argument_test.v @@ -6,7 +6,7 @@ struct ContainerType { typ &Type } -fn (instance &ContainerType) contains(typ Type) bool { +fn (instance &ContainerType) contains(typ &Type) bool { println(typ) if instance.typ == typ { return true diff --git a/vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.out b/vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.out new file mode 100644 index 0000000000..e333bf90f2 --- /dev/null +++ b/vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.out @@ -0,0 +1,23 @@ +[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:19] '$T.name $input': int 1 +[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:26] '$T.name $input': int 1 +[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:36] next(1): 0 +[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:19] '$T.name $input': f64 1. +[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:26] '$T.name $input': f64 1. +[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:37] next(1.0): 64. +[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:19] '$T.name $input': f64 11.1 +[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:26] '$T.name $input': f64 11.1 +[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:38] next(11.1): 64. +[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:15] '$T.name $input': Score Score{ + ave: 23.4 +} +[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:26] '$T.name $input': Score Score{ + ave: 23.4 +} +[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:42] next(ave): 23.4 +[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:15] '$T.name $input': &Score &Score{ + ave: 23.4 +} +[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:26] '$T.name $input': &Score &Score{ + ave: 23.4 +} +[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:43] next(&ave): 23.4 diff --git a/vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv b/vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv new file mode 100644 index 0000000000..b0730d5d6c --- /dev/null +++ b/vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv @@ -0,0 +1,44 @@ +interface Average { + ave() f64 +} + +struct Score { + ave f64 +} + +pub fn (s &Score) ave() f64 { + return s.ave +} + +fn next(input T) f64 { + $if T is Average { + dump('${T.name} $input') + ret := next2(input) + return ret + } $else { + dump('${T.name} $input') + ret := next2(input) + return ret + } +} + +fn next2(input T) f64 { + dump('${T.name} $input') + $if T is Average { + return input.ave() + } $else $if T is f64 { + return 64.0 + } + return 0.0 +} + +fn main() { + dump(next(1)) + dump(next(1.0)) + dump(next(11.1)) + ave := Score { + ave: 23.4 + } + dump(next(ave)) + dump(next(&ave)) +}