diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index 045d151e95..5b80c1b183 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -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) diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index e6fc4768fa..50f0f3981a 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -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) diff --git a/vlib/v/gen/c/array.v b/vlib/v/gen/c/array.v index 3fc2ed17dc..312a097444 100644 --- a/vlib/v/gen/c/array.v +++ b/vlib/v/gen/c/array.v @@ -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 diff --git a/vlib/v/tests/generics_array_of_threads_test.v b/vlib/v/tests/generics_array_of_threads_test.v new file mode 100644 index 0000000000..e56039ebae --- /dev/null +++ b/vlib/v/tests/generics_array_of_threads_test.v @@ -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] +}