From 9be596ef12773ae9bad15ceb79f275af4b074fee Mon Sep 17 00:00:00 2001 From: yuyi Date: Fri, 21 May 2021 22:21:18 +0800 Subject: [PATCH] checker: fix generic struct with anon fn type (#10161) --- vlib/v/checker/checker.v | 2 +- .../tests/generics_struct_anon_fn_type_test.v | 46 +++++++++++++++---- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 5433457761..4e74fd0324 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2055,7 +2055,7 @@ pub fn (mut c Checker) method_call(mut call_expr ast.CallExpr) ast.Type { // call struct field fn type // TODO: can we use SelectorExpr for all? this dosent really belong here if field := c.table.find_field(left_type_sym, method_name) { - field_type_sym := c.table.get_type_symbol(field.typ) + field_type_sym := c.table.get_type_symbol(c.unwrap_generic(field.typ)) if field_type_sym.kind == .function { // call_expr.is_method = false call_expr.is_field = true diff --git a/vlib/v/tests/generics_struct_anon_fn_type_test.v b/vlib/v/tests/generics_struct_anon_fn_type_test.v index d3a7feca2d..eb0f21556d 100644 --- a/vlib/v/tests/generics_struct_anon_fn_type_test.v +++ b/vlib/v/tests/generics_struct_anon_fn_type_test.v @@ -2,22 +2,52 @@ fn neg(a int) int { return -a } -struct FnHolder { +struct FnHolder1 { func T } -fn (self FnHolder) call(a int) int { +fn (self FnHolder1) call(a int) int { return self.func(a) } -fn holder_call(func T, a int) int { - _ = FnHolder{func} - return 0 +struct FnHolder2 { + func fn (int) int +} + +fn (self FnHolder2) call(a int) int { + return self.func(a) +} + +fn holder_call_1(func T, a int) int { + h := FnHolder1{func} + return h.call(a) +} + +fn holder_call_2(func T, a int) int { + h := FnHolder2{func} + return h.call(a) +} + +fn holder_call_11(func T, a int) int { + f := func + h := FnHolder1{f} + return h.call(a) +} + +fn holder_call_21(func T, a int) int { + f := func + h := FnHolder2{f} + return h.call(a) } fn test_generic_struct_with_anon_fn_parameter() { - mut ret := 0 + mut ret := holder_call_1(neg, 1) + assert ret == -1 + ret = holder_call_11(neg, 2) + assert ret == -2 - ret = holder_call(neg, 1) - assert ret == 0 + ret = holder_call_2(neg, 3) + assert ret == -3 + ret = holder_call_21(neg, 4) + assert ret == -4 }