From 46d311dcc46477f74843c0ff73de0dbbc7029833 Mon Sep 17 00:00:00 2001 From: yuyi Date: Tue, 5 Jan 2021 00:40:53 +0800 Subject: [PATCH] generic: fix return multi array generic (fix #7727 #7753) (#7855) --- vlib/v/checker/check_types.v | 21 ++++++++++++---- vlib/v/checker/checker.v | 22 +++++++++++----- .../tests/generics_return_multi_array_test.v | 25 +++++++++++++++++++ 3 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 vlib/v/tests/generics_return_multi_array_test.v diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index 7b0ab45d98..c2653b38a2 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -427,12 +427,23 @@ pub fn (mut c Checker) infer_fn_types(f table.Fn, mut call_expr ast.CallExpr) { arg_sym := c.table.get_type_symbol(arg.typ) param_type_sym := c.table.get_type_symbol(param.typ) if arg_sym.kind == .array && param_type_sym.kind == .array { - param_info := param_type_sym.info as table.Array - if param_info.elem_type.has_flag(.generic) { - arg_info := arg_sym.info as table.Array - typ = arg_info.elem_type - break + mut arg_elem_info := arg_sym.info as table.Array + mut param_elem_info := param_type_sym.info as table.Array + mut arg_elem_sym := c.table.get_type_symbol(arg_elem_info.elem_type) + mut param_elem_sym := c.table.get_type_symbol(param_elem_info.elem_type) + for { + if arg_elem_sym.kind == .array && + param_elem_sym.kind == .array && param_elem_sym.name != 'T' { + arg_elem_info = arg_elem_sym.info as table.Array + arg_elem_sym = c.table.get_type_symbol(arg_elem_info.elem_type) + param_elem_info = param_elem_sym.info as table.Array + param_elem_sym = c.table.get_type_symbol(param_elem_info.elem_type) + } else { + typ = arg_elem_info.elem_type + break + } } + break } } if typ == table.void_type { diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index ded686f710..79caecdafe 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1766,13 +1766,23 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type { } call_expr.return_type = typ return typ - } else if return_sym.kind == .array { - elem_info := return_sym.info as table.Array - elem_sym := c.table.get_type_symbol(elem_info.elem_type) - if elem_sym.name == 'T' { - idx := c.table.find_or_register_array(call_expr.generic_type, 1) - return table.new_type(idx) + } else if return_sym.kind == .array && return_sym.name.contains('T') { + mut info := return_sym.info as table.Array + mut sym := c.table.get_type_symbol(info.elem_type) + mut dims := 1 + for { + if sym.kind == .array { + info = sym.info as table.Array + sym = c.table.get_type_symbol(info.elem_type) + dims++ + } else { + break + } } + idx := c.table.find_or_register_array(call_expr.generic_type, dims) + typ := table.new_type(idx) + call_expr.return_type = typ + return typ } } if call_expr.generic_type.is_full() && !f.is_generic { diff --git a/vlib/v/tests/generics_return_multi_array_test.v b/vlib/v/tests/generics_return_multi_array_test.v new file mode 100644 index 0000000000..eaa8fe1adc --- /dev/null +++ b/vlib/v/tests/generics_return_multi_array_test.v @@ -0,0 +1,25 @@ +fn example1(data []T) [][]T { + return [data] +} + +fn example2(data [][]T) [][][]T { + return [data] +} + +fn example3(data [][][]T) [][][][]T { + return [data] +} + +fn test_generic_return_multi_array() { + d1 := [1, 2, 3] + d2 := example1(d1) + assert d2 == [[1, 2, 3]] + + d11 := [[1, 2, 3]] + d22 := example2(d11) + assert d22 == [[[1, 2, 3]]] + + d111 := [[[1, 2, 3]]] + d222 := example3(d111) + assert d222 == [[[[1, 2, 3]]]] +}