1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

ast, checker, cgen: fix generic array of threads (fix #17976) (#17986)

This commit is contained in:
yuyi 2023-04-18 17:43:30 +08:00 committed by GitHub
parent df3ee9a64a
commit 6cc420880f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 4 deletions

View File

@ -1530,6 +1530,18 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
}
}
}
Thread {
if typ := t.resolve_generic_to_concrete(sym.info.return_type, generic_names,
concrete_types)
{
idx := t.find_or_register_thread(typ)
if typ.has_flag(.generic) {
return new_type(idx).derive_add_muls(generic_type).set_flag(.generic)
} else {
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
}
}
}
FnType {
mut func := sym.info.func
mut has_generic := false
@ -1773,6 +1785,11 @@ pub fn (mut t Table) unwrap_generic_type(typ Type, generic_names []string, concr
idx := t.find_or_register_chan(unwrap_typ, unwrap_typ.nr_muls() > 0)
return new_type(idx).derive_add_muls(typ).clear_flag(.generic)
}
Thread {
unwrap_typ := t.unwrap_generic_type(ts.info.return_type, generic_names, concrete_types)
idx := t.find_or_register_thread(unwrap_typ)
return new_type(idx).derive_add_muls(typ).clear_flag(.generic)
}
Map {
unwrap_key_type := t.unwrap_generic_type(ts.info.key_type, generic_names,
concrete_types)

View File

@ -2109,9 +2109,9 @@ fn (mut c Checker) go_expr(mut node ast.GoExpr) ast.Type {
}
if c.pref.backend.is_js() {
return c.table.find_or_register_promise(ret_type)
return c.table.find_or_register_promise(c.unwrap_generic(ret_type))
} else {
return c.table.find_or_register_thread(ret_type)
return c.table.find_or_register_thread(c.unwrap_generic(ret_type))
}
}
@ -2420,7 +2420,7 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
if node.args.len != 0 {
c.error('`.wait()` does not have any arguments', node.args[0].pos)
}
thread_ret_type := elem_sym.thread_info().return_type
thread_ret_type := c.unwrap_generic(elem_sym.thread_info().return_type)
if thread_ret_type.has_flag(.option) {
c.error('`.wait()` cannot be called for an array when thread functions return options. Iterate over the arrays elements instead and handle each returned option with `or`.',
node.pos)

View File

@ -980,7 +980,7 @@ fn (mut g Gen) gen_array_index(node ast.CallExpr) {
}
fn (mut g Gen) gen_array_wait(node ast.CallExpr) {
arr := g.table.sym(node.receiver_type)
arr := g.table.sym(g.unwrap_generic(node.receiver_type))
thread_type := arr.array_info().elem_type
thread_sym := g.table.sym(thread_type)
thread_ret_type := thread_sym.thread_info().return_type

View File

@ -0,0 +1,16 @@
fn async_map[T](arr []T, func fn (T) T) []T {
mut threads := []thread T{}
for element in arr {
threads << spawn func(element)
}
return threads.wait()
}
fn test_generic_array_of_threads() {
arr := [1, 2, 3, 4]
results := async_map(arr, fn (a int) int {
return -a
})
println(results)
assert results == [-1, -2, -3, -4]
}