generics: fix generics_struct with generic array string (#9494)

pull/9496/head
yuyi 2021-03-28 16:46:13 +08:00 committed by GitHub
parent 76dc4cf13f
commit 92f19f5767
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 4 deletions

View File

@ -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 { if rts.info.generic_types.len == generic_types.len {
for i, _ in fields { for i, _ in fields {
mut field := fields[i] mut field := fields[i]
if field.typ.has_flag(.generic) { sym := c.table.get_type_symbol(field.typ)
for j, gp in rts.info.generic_types { mut field_typ := field.typ
if gp == field.typ { mut nr_dims := 0
field.typ = generic_types[j].derive(field.typ).clear_flag(.generic) if sym.kind == .array {
break 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
} }
} }
fields[i] = field 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 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) { fn (mut c Checker) deprecate_fnmethod(kind string, name string, the_fn table.Fn, call_expr ast.CallExpr) {
start_message := '$kind `$name`' start_message := '$kind `$name`'
mut deprecation_message := '' mut deprecation_message := ''

View File

@ -698,6 +698,7 @@ pub fn (mut t Table) find_or_register_array(elem_type Type) int {
name: name name: name
cname: cname cname: cname
info: Array{ info: Array{
nr_dims: 1
elem_type: elem_type elem_type: elem_type
} }
} }

View File

@ -29,3 +29,23 @@ fn test_generics_return_generics_struct() {
println(get<int>(o)) println(get<int>(o))
assert get<int>(o) == 42 assert get<int>(o) == 42
} }
pub struct ArrayIterator<T> {
data []T
mut:
index int
}
pub fn iter<T>(arr []T) ArrayIterator<T> {
return ArrayIterator{data: arr, index: 11}
}
fn test_generics_with_generics_struct_string() {
data := ['foo' 'bar']
it := iter<string>(data)
println(it)
ret := '$it'
assert ret.contains('arrayIterator<string>{')
assert ret.contains("data: ['foo', 'bar']")
assert ret.contains('index: 11')
}