From 0aacc9a80a80977a5031479453373b3f53bbadd6 Mon Sep 17 00:00:00 2001 From: LilEnvy <75917200+lilenvy@users.noreply.github.com> Date: Sat, 12 Dec 2020 18:29:48 -0800 Subject: [PATCH] array: [].map(fn...) return type can be different than original type (#7300) --- vlib/builtin/array_test.v | 17 +++++++++++++++++ vlib/v/checker/checker.v | 10 +++++----- .../v/checker/tests/array_map_anon_fn_err_b.out | 4 ++-- .../v/checker/tests/array_map_anon_fn_err_c.out | 6 ++++++ vlib/v/checker/tests/array_map_anon_fn_err_c.vv | 4 ++++ vlib/v/checker/tests/array_map_fn_err_b.out | 4 ++-- vlib/v/checker/tests/array_map_fn_err_c.out | 7 +++++++ vlib/v/checker/tests/array_map_fn_err_c.vv | 5 +++++ 8 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 vlib/v/checker/tests/array_map_anon_fn_err_c.out create mode 100644 vlib/v/checker/tests/array_map_anon_fn_err_c.vv create mode 100644 vlib/v/checker/tests/array_map_fn_err_c.out create mode 100644 vlib/v/checker/tests/array_map_fn_err_c.vv diff --git a/vlib/builtin/array_test.v b/vlib/builtin/array_test.v index 07cb3e2ebb..19542a1424 100644 --- a/vlib/builtin/array_test.v +++ b/vlib/builtin/array_test.v @@ -676,6 +676,23 @@ fn test_anon_fn_arg_map() { assert a == [2,3,4] } +fn test_anon_fn_arg_different_type_map() { + i_to_str := fn (i int) string { + return i.str() + } + a := [1, 2, 3].map(i_to_str) + + assert a == ['1', '2', '3'] +} + +fn test_anon_fn_inline_different_type_map() { + a := [1, 2, 3].map(fn (i int) string { + return i.str() + }) + + assert a == ['1', '2', '3'] +} + fn test_array_str() { numbers := [1, 2, 3] assert numbers == [1,2,3] diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 63e468ceec..04a6ac0281 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1086,9 +1086,8 @@ fn (mut c Checker) check_map_and_filter(is_map bool, elem_typ table.Type, call_e if arg_expr.decl.params.len > 1 { c.error('function needs exactly 1 argument', arg_expr.decl.pos) } else if is_map && - (arg_expr.decl.return_type != elem_typ || arg_expr.decl.params[0].typ != elem_typ) { - c.error('type mismatch, should use `fn(a $elem_sym.name) $elem_sym.name {...}`', - arg_expr.decl.pos) + (arg_expr.decl.return_type == table.void_type || arg_expr.decl.params[0].typ != elem_typ) { + c.error('type mismatch, should use `fn(a $elem_sym.name) T {...}`', arg_expr.decl.pos) } else if !is_map && (arg_expr.decl.return_type != table.bool_type || arg_expr.decl.params[0].typ != elem_typ) { c.error('type mismatch, should use `fn(a $elem_sym.name) bool {...}`', @@ -1103,8 +1102,9 @@ fn (mut c Checker) check_map_and_filter(is_map bool, elem_typ table.Type, call_e } if func.params.len > 1 { c.error('function needs exactly 1 argument', call_expr.pos) - } else if is_map && (func.return_type != elem_typ || func.params[0].typ != elem_typ) { - c.error('type mismatch, should use `fn(a $elem_sym.name) $elem_sym.name {...}`', + } else if is_map && + (func.return_type == table.void_type || func.params[0].typ != elem_typ) { + c.error('type mismatch, should use `fn(a $elem_sym.name) T {...}`', arg_expr.pos) } else if !is_map && (func.return_type != table.bool_type || func.params[0].typ != elem_typ) { diff --git a/vlib/v/checker/tests/array_map_anon_fn_err_b.out b/vlib/v/checker/tests/array_map_anon_fn_err_b.out index 409d866d1a..f08ab7de5b 100644 --- a/vlib/v/checker/tests/array_map_anon_fn_err_b.out +++ b/vlib/v/checker/tests/array_map_anon_fn_err_b.out @@ -1,6 +1,6 @@ -vlib/v/checker/tests/array_map_anon_fn_err_b.vv:2:21: error: type mismatch, should use `fn(a int) int {...}` +vlib/v/checker/tests/array_map_anon_fn_err_b.vv:2:21: error: type mismatch, should use `fn(a int) T {...}` 1 | fn main() { 2 | a := [1,2,3,4].map(fn(a string) string { return a }) | ~~ 3 | println(a) - 4 | } \ No newline at end of file + 4 | } diff --git a/vlib/v/checker/tests/array_map_anon_fn_err_c.out b/vlib/v/checker/tests/array_map_anon_fn_err_c.out new file mode 100644 index 0000000000..6e92fbd4c2 --- /dev/null +++ b/vlib/v/checker/tests/array_map_anon_fn_err_c.out @@ -0,0 +1,6 @@ +vlib/v/checker/tests/array_map_anon_fn_err_c.vv:2:21: error: type mismatch, should use `fn(a int) T {...}` + 1 | fn main() { + 2 | a := [1,2,3,4].map(fn(a string) {}) + | ~~ + 3 | println(a) + 4 | } diff --git a/vlib/v/checker/tests/array_map_anon_fn_err_c.vv b/vlib/v/checker/tests/array_map_anon_fn_err_c.vv new file mode 100644 index 0000000000..12d897faa2 --- /dev/null +++ b/vlib/v/checker/tests/array_map_anon_fn_err_c.vv @@ -0,0 +1,4 @@ +fn main() { + a := [1,2,3,4].map(fn(a string) {}) + println(a) +} diff --git a/vlib/v/checker/tests/array_map_fn_err_b.out b/vlib/v/checker/tests/array_map_fn_err_b.out index bbdbcbad0c..020da5e51c 100644 --- a/vlib/v/checker/tests/array_map_fn_err_b.out +++ b/vlib/v/checker/tests/array_map_fn_err_b.out @@ -1,7 +1,7 @@ -vlib/v/checker/tests/array_map_fn_err_b.vv:5:21: error: type mismatch, should use `fn(a int) int {...}` +vlib/v/checker/tests/array_map_fn_err_b.vv:5:21: error: type mismatch, should use `fn(a int) T {...}` 3 | } 4 | fn main() { 5 | a := [1,2,3,4].map(add) | ~~~ 6 | println(a) - 7 | } \ No newline at end of file + 7 | } diff --git a/vlib/v/checker/tests/array_map_fn_err_c.out b/vlib/v/checker/tests/array_map_fn_err_c.out new file mode 100644 index 0000000000..aaa4b73c27 --- /dev/null +++ b/vlib/v/checker/tests/array_map_fn_err_c.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/array_map_fn_err_c.vv:3:21: error: type mismatch, should use `fn(a int) T {...}` + 1 | fn do_nothing(a string) {} + 2 | fn main() { + 3 | a := [1,2,3,4].map(do_nothing) + | ~~~~~~~~~~ + 4 | println(a) + 5 | } diff --git a/vlib/v/checker/tests/array_map_fn_err_c.vv b/vlib/v/checker/tests/array_map_fn_err_c.vv new file mode 100644 index 0000000000..89f9b97a87 --- /dev/null +++ b/vlib/v/checker/tests/array_map_fn_err_c.vv @@ -0,0 +1,5 @@ +fn do_nothing(a string) {} +fn main() { + a := [1,2,3,4].map(do_nothing) + println(a) +}