1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

cgen: fix nested generic fn call with reference argument (#15353)

This commit is contained in:
yuyi 2022-08-07 00:07:33 +08:00 committed by GitHub
parent 4588bb44ab
commit 8d9af2e4a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 73 additions and 5 deletions

View File

@ -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*/')

View File

@ -6,7 +6,7 @@ struct ContainerType<T> {
typ &Type<T>
}
fn (instance &ContainerType<T>) contains(typ Type<T>) bool {
fn (instance &ContainerType<T>) contains(typ &Type<T>) bool {
println(typ)
if instance.typ == typ {
return true

View File

@ -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

View File

@ -0,0 +1,44 @@
interface Average {
ave() f64
}
struct Score {
ave f64
}
pub fn (s &Score) ave() f64 {
return s.ave
}
fn next<T>(input T) f64 {
$if T is Average {
dump('${T.name} $input')
ret := next2<T>(input)
return ret
} $else {
dump('${T.name} $input')
ret := next2<T>(input)
return ret
}
}
fn next2<T>(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))
}