diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 67e3316c5f..c5cc3393d3 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1471,6 +1471,7 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type { node.has_hidden_receiver = true method.name = '' fn_type := ast.new_type(c.table.find_or_register_fn_type(method, false, true)) + node.typ = fn_type return fn_type } if sym.kind !in [.struct_, .aggregate, .interface_, .sum_type] { diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 0079eb673a..e6fc4768fa 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -2444,8 +2444,16 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as c.check_map_and_filter(true, elem_typ, node) arg_sym := c.table.sym(arg_type) ret_type := match arg_sym.info { - ast.FnType { arg_sym.info.func.return_type } - else { arg_type } + ast.FnType { + if node.args[0].expr is ast.SelectorExpr { + arg_type + } else { + arg_sym.info.func.return_type + } + } + else { + arg_type + } } node.return_type = c.table.find_or_register_array(c.unwrap_generic(ret_type)) if node.return_type.has_flag(.shared_f) { diff --git a/vlib/v/gen/c/array.v b/vlib/v/gen/c/array.v index 6dec0869d1..3fc2ed17dc 100644 --- a/vlib/v/gen/c/array.v +++ b/vlib/v/gen/c/array.v @@ -421,12 +421,24 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) { ret_sym := g.table.sym(node.return_type) inp_sym := g.table.sym(node.receiver_type) ret_info := ret_sym.info as ast.Array - ret_elem_type := g.typ(ret_info.elem_type) + mut ret_elem_type := g.typ(ret_info.elem_type) inp_info := inp_sym.info as ast.Array inp_elem_type := g.typ(inp_info.elem_type) if inp_sym.kind != .array { verror('map() requires an array') } + + mut closure_var_decl := '' + if node.args[0].expr is ast.SelectorExpr { + if node.args[0].expr.typ != ast.void_type { + var_sym := g.table.sym(node.args[0].expr.typ) + if var_sym.info is ast.FnType { + ret_elem_type = 'voidptr' + closure_var_decl = g.fn_var_signature(var_sym.info.func.return_type, var_sym.info.func.params.map(it.typ), + 'ti') + } + } + } g.empty_line = true noscan := g.check_noscan(ret_info.elem_type) has_infix_left_var_name := g.write_prepared_tmp_value(tmp, node, ret_typ, '{0}') @@ -473,7 +485,11 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) { g.expr(node.args[0].expr) } else { - g.write('${ret_elem_type} ti = ') + if closure_var_decl != '' { + g.write('${closure_var_decl} = ') + } else { + g.write('${ret_elem_type} ti = ') + } g.expr(node.args[0].expr) } } diff --git a/vlib/v/tests/map_with_selector_test.v b/vlib/v/tests/map_with_selector_test.v new file mode 100644 index 0000000000..90f210d1f6 --- /dev/null +++ b/vlib/v/tests/map_with_selector_test.v @@ -0,0 +1,9 @@ +fn test_main() { + k := [10, 20, 30] + println(k.map(it.hex())) + dump(k.map(it.hex)) + a := k.map(it.hex) + assert dump(a[0]()) == 'a' + assert dump(a[1]()) == '14' + assert dump(a[2]()) == '1e' +}