checker, cgen: fix generics interface method (#10858)
parent
dbba46b349
commit
8e99a018df
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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]
|
||||
}
|
Loading…
Reference in New Issue