checker, cgen: fix for in iterator of generic struct (#12441)
parent
50a608aab3
commit
3bb1c3f930
|
@ -4816,7 +4816,7 @@ fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) {
|
|||
sym := c.table.get_final_type_symbol(typ)
|
||||
if sym.kind == .struct_ {
|
||||
// iterators
|
||||
next_fn := sym.find_method('next') or {
|
||||
next_fn := sym.find_method_with_generic_parent('next') or {
|
||||
c.error('a struct must have a `next()` method to be an iterator', node.cond.position())
|
||||
return
|
||||
}
|
||||
|
|
|
@ -2145,7 +2145,7 @@ fn (mut g Gen) for_in_stmt(node ast.ForInStmt) {
|
|||
}
|
||||
} else if node.kind == .struct_ {
|
||||
cond_type_sym := g.table.get_type_symbol(node.cond_type)
|
||||
next_fn := cond_type_sym.find_method('next') or {
|
||||
next_fn := cond_type_sym.find_method_with_generic_parent('next') or {
|
||||
verror('`next` method not found')
|
||||
return
|
||||
}
|
||||
|
@ -2162,7 +2162,14 @@ fn (mut g Gen) for_in_stmt(node ast.ForInStmt) {
|
|||
t_var := g.new_tmp_var()
|
||||
receiver_typ := next_fn.params[0].typ
|
||||
receiver_styp := g.typ(receiver_typ)
|
||||
fn_name := receiver_styp.replace_each(['*', '', '.', '__']) + '_next'
|
||||
mut fn_name := receiver_styp.replace_each(['*', '', '.', '__']) + '_next'
|
||||
receiver_sym := g.table.get_type_symbol(receiver_typ)
|
||||
if receiver_sym.info is ast.Struct {
|
||||
if receiver_sym.info.concrete_types.len > 0 {
|
||||
fn_name = g.generic_fn_name(receiver_sym.info.concrete_types, fn_name,
|
||||
false)
|
||||
}
|
||||
}
|
||||
g.write('\t${g.typ(ret_typ)} $t_var = ${fn_name}(')
|
||||
if !node.cond_type.is_ptr() && receiver_typ.is_ptr() {
|
||||
g.write('&')
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
struct Split<T> {
|
||||
arr []T
|
||||
pred fn (T) bool
|
||||
mut:
|
||||
idx int
|
||||
}
|
||||
|
||||
fn (mut iter Split<T>) next() ?[]T {
|
||||
start := iter.idx
|
||||
for iter.idx < iter.arr.len {
|
||||
if iter.pred(iter.arr[iter.idx]) {
|
||||
iter.idx++
|
||||
return iter.arr[start..iter.idx]
|
||||
}
|
||||
iter.idx++
|
||||
}
|
||||
return none
|
||||
}
|
||||
|
||||
fn split<T>(arr []T, pred fn (T) bool) Split<T> {
|
||||
return Split<T>{arr, pred, 0}
|
||||
}
|
||||
|
||||
fn test_for_in_iterator_of_generic_struct() {
|
||||
items := [0, 1, 2, 3, 4, 5, 6, 7, 8]
|
||||
mut iter := split<int>(items, fn (item int) bool {
|
||||
return item % 3 == 0
|
||||
})
|
||||
iter.next() or {}
|
||||
mut ret_list := [][]int{}
|
||||
for item in iter {
|
||||
dump(item)
|
||||
ret_list << item
|
||||
}
|
||||
println(ret_list)
|
||||
assert ret_list.len == 2
|
||||
assert ret_list[0] == [1, 2, 3]
|
||||
assert ret_list[1] == [4, 5, 6]
|
||||
}
|
Loading…
Reference in New Issue