From 78d0255e6c101b9aa4f07efe13b5d3f3bbd492fd Mon Sep 17 00:00:00 2001 From: yuyi Date: Wed, 10 Aug 2022 16:29:19 +0800 Subject: [PATCH] checker: fix generics with nested generic method call (#15390) --- vlib/v/checker/fn.v | 10 ++--- ...ics_with_nested_generic_method_call_test.v | 40 +++++++++++++++++++ 2 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 vlib/v/tests/generics_with_nested_generic_method_call_test.v diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 03d59b627f..fa0d28f96d 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -1526,12 +1526,12 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type { if method.generic_names.len != node.concrete_types.len { // no type arguments given in call, attempt implicit instantiation c.infer_fn_generic_types(method, mut node) - concrete_types = node.concrete_types - } else { - if node.concrete_types.len > 0 && !node.concrete_types[0].has_flag(.generic) { - c.table.register_fn_concrete_types(method.fkey(), node.concrete_types) - } + concrete_types = node.concrete_types.map(c.unwrap_generic(it)) } + if concrete_types.len > 0 && !concrete_types[0].has_flag(.generic) { + c.table.register_fn_concrete_types(method.fkey(), concrete_types) + } + // resolve return generics struct to concrete type if method.generic_names.len > 0 && method.return_type.has_flag(.generic) && !isnil(c.table.cur_fn) && c.table.cur_fn.generic_names.len == 0 { diff --git a/vlib/v/tests/generics_with_nested_generic_method_call_test.v b/vlib/v/tests/generics_with_nested_generic_method_call_test.v new file mode 100644 index 0000000000..512aa62360 --- /dev/null +++ b/vlib/v/tests/generics_with_nested_generic_method_call_test.v @@ -0,0 +1,40 @@ +struct Calc { +mut: + typ S +} + +struct TypeA {} + +struct TypeB {} + +fn (mut c Calc) next(input T) f64 { + $if S is TypeA || S is TypeB { + return c.typ.next(input) + } $else { + return 99.0 + } +} + +fn (mut t TypeA) next(input T) f64 { + return 10.0 +} + +fn (mut t TypeB) next(input T) f64 { + return 11.0 +} + +fn test_generics_with_nested_generic_method_call() { + { + mut c := Calc{ + typ: TypeA{} + } + assert c.next(100) == 10.0 + } + { + mut c := Calc{ + typ: TypeB{} + } + assert c.next(100) == 11.0 + } + println('OK!!') +}