checker, cgen: fix generics interface method (#10858)

pull/10861/head
yuyi 2021-07-19 18:29:46 +08:00 committed by GitHub
parent dbba46b349
commit 8e99a018df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 5 deletions

View File

@ -1470,8 +1470,8 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
// `array << elm`
c.check_expr_opt_call(node.right, right_type)
node.auto_locked, _ = c.fail_if_immutable(node.left)
left_value_type := c.table.value_type(left_type)
left_value_sym := c.table.get_type_symbol(left_value_type)
left_value_type := c.table.value_type(c.unwrap_generic(left_type))
left_value_sym := c.table.get_type_symbol(c.unwrap_generic(left_value_type))
if left_value_sym.kind == .interface_ {
if right_final.kind != .array {
// []Animal << Cat
@ -1489,8 +1489,9 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
return ast.void_type
}
// []T << T or []T << []T
if c.check_types(right_type, left_value_type)
|| c.check_types(right_type, left_type) {
unwrapped_right_type := c.unwrap_generic(right_type)
if c.check_types(unwrapped_right_type, left_value_type)
|| c.check_types(unwrapped_right_type, left_type) {
return ast.void_type
}
c.error('cannot append `$right_sym.name` to `$left_sym.name`', right_pos)

View File

@ -548,7 +548,23 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
if node.receiver_type == 0 {
g.checker_bug('CallExpr.receiver_type is 0 in method_call', node.pos)
}
unwrapped_rec_type := g.unwrap_generic(node.receiver_type)
mut unwrapped_rec_type := node.receiver_type
if g.table.cur_fn.generic_names.len > 0 { // in generic fn
unwrapped_rec_type = g.unwrap_generic(node.receiver_type)
} else { // in non-generic fn
sym := g.table.get_type_symbol(node.receiver_type)
match sym.info {
ast.Struct, ast.Interface, ast.SumType {
generic_names := sym.info.generic_types.map(g.table.get_type_symbol(it).name)
if utyp := g.table.resolve_generic_to_concrete(node.receiver_type, generic_names,
sym.info.concrete_types)
{
unwrapped_rec_type = utyp
}
}
else {}
}
}
typ_sym := g.table.get_type_symbol(unwrapped_rec_type)
rec_cc_type := g.cc_type(unwrapped_rec_type, false)
mut receiver_type_name := util.no_dots(rec_cc_type)

View File

@ -0,0 +1,35 @@
interface Iter<T> {
next() ?T
}
fn (mut it Iter<T>) collect<T>() []T {
mut data := []T{}
for {
val := it.next() or { break }
data << val
}
return data
}
struct ArrayIter<T> {
data []T
mut:
index int
}
fn (mut it ArrayIter<T>) next<T>() ?T {
if it.index >= it.data.len {
return none
}
defer {
it.index++
}
return it.data[it.index]
}
fn test_generics_interface_method() {
mut iter := Iter<int>(ArrayIter<int>{
data: [1, 2, 3]
})
assert iter.collect() == [1, 2, 3]
}