diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index f6eac7c134..546095cf05 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1954,12 +1954,22 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type { if rts.info.generic_types.len == generic_types.len { for i, _ in fields { mut field := fields[i] - if field.typ.has_flag(.generic) { - for j, gp in rts.info.generic_types { - if gp == field.typ { + sym := c.table.get_type_symbol(field.typ) + mut field_typ := field.typ + mut nr_dims := 0 + if sym.kind == .array { + field_typ, nr_dims = c.array_element_info(field.typ) + } + for j, gp in rts.info.generic_types { + if gp == field_typ { + if sym.kind == .array { + field_idx := c.table.find_or_register_array_with_dims(generic_types[j], + nr_dims) + field.typ = table.new_type(field_idx) + } else { field.typ = generic_types[j].derive(field.typ).clear_flag(.generic) - break } + break } } fields[i] = field @@ -2136,6 +2146,21 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type { return f.return_type } +fn (mut c Checker) array_element_info(typ table.Type) (table.Type, int) { + mut typ_ := typ + mut dims := 0 + for { + sym := c.table.get_type_symbol(typ_) + if sym.info is table.Array { + typ_ = sym.info.elem_type + dims++ + } else { + break + } + } + return typ_, dims +} + fn (mut c Checker) deprecate_fnmethod(kind string, name string, the_fn table.Fn, call_expr ast.CallExpr) { start_message := '$kind `$name`' mut deprecation_message := '' diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index 2c87a720d0..4e4861a873 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -698,6 +698,7 @@ pub fn (mut t Table) find_or_register_array(elem_type Type) int { name: name cname: cname info: Array{ + nr_dims: 1 elem_type: elem_type } } diff --git a/vlib/v/tests/generics_return_generics_struct_test.v b/vlib/v/tests/generics_return_generics_struct_test.v index 82958f2c03..7b8b101aab 100644 --- a/vlib/v/tests/generics_return_generics_struct_test.v +++ b/vlib/v/tests/generics_return_generics_struct_test.v @@ -29,3 +29,23 @@ fn test_generics_return_generics_struct() { println(get(o)) assert get(o) == 42 } + +pub struct ArrayIterator { + data []T +mut: + index int +} + +pub fn iter(arr []T) ArrayIterator { + return ArrayIterator{data: arr, index: 11} +} + +fn test_generics_with_generics_struct_string() { + data := ['foo' 'bar'] + it := iter(data) + println(it) + ret := '$it' + assert ret.contains('arrayIterator{') + assert ret.contains("data: ['foo', 'bar']") + assert ret.contains('index: 11') +}