generic: fix return multi array generic (fix #7727 #7753) (#7855)

pull/7864/head^2
yuyi 2021-01-05 00:40:53 +08:00 committed by GitHub
parent 7533ffa48f
commit 46d311dcc4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 11 deletions

View File

@ -427,13 +427,24 @@ 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
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 {
c.error('could not infer generic type `$gt_name` in call to `$f.name`', call_expr.pos)

View File

@ -1766,14 +1766,24 @@ 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 {
c.error('a non generic function called like a generic one', call_expr.generic_list_pos)

View File

@ -0,0 +1,25 @@
fn example1<T>(data []T) [][]T {
return [data]
}
fn example2<T>(data [][]T) [][][]T {
return [data]
}
fn example3<T>(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]]]]
}