# HG changeset patch # User Bram Moolenaar # Date 1643221803 -3600 # Node ID ec2ba9acec1b05cd0fd833723c898466158da86e # Parent 5854ea4dc13250572546f14805288ca770d98974 patch 8.2.4224: Vim9: no error when using a number for map() second argument Commit: https://github.com/vim/vim/commit/1080c48ec8d672d7e9fbefb5a1255c9df09a2884 Author: Bram Moolenaar Date: Wed Jan 26 18:26:21 2022 +0000 patch 8.2.4224: Vim9: no error when using a number for map() second argument Problem: Vim9: no error when using a number for map() second argument Solution: Disallow number to string conversion. (closes https://github.com/vim/vim/issues/9630) diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -291,7 +291,7 @@ eval_expr_typval(typval_T *expr, typval_ } else { - s = tv_get_string_buf_chk(expr, buf); + s = tv_get_string_buf_chk_strict(expr, buf, TRUE); if (s == NULL) return FAIL; s = skipwhite(s); diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -491,13 +491,26 @@ arg_list_or_dict_or_blob_or_string(type_ static int arg_filter_func(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { - if (type->tt_type == VAR_FUNC - && !(type->tt_member->tt_type == VAR_BOOL + if (type->tt_type == VAR_STRING + || type->tt_type == VAR_PARTIAL + || type == &t_unknown + || type == &t_any) + return OK; + + if (type->tt_type == VAR_FUNC) + { + if (!(type->tt_member->tt_type == VAR_BOOL || type->tt_member->tt_type == VAR_NUMBER || type->tt_member->tt_type == VAR_UNKNOWN || type->tt_member->tt_type == VAR_ANY)) - { - arg_type_mismatch(&t_func_bool, type, context->arg_idx + 1); + { + arg_type_mismatch(&t_func_bool, type, context->arg_idx + 1); + return FAIL; + } + } + else + { + semsg(_(e_string_or_function_required_for_argument_nr), 2); return FAIL; } return OK; @@ -509,26 +522,39 @@ arg_filter_func(type_T *type, type_T *de static int arg_map_func(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { - if (type->tt_type == VAR_FUNC - && type->tt_member != &t_any + if (type->tt_type == VAR_STRING + || type->tt_type == VAR_PARTIAL + || type == &t_unknown + || type == &t_any) + return OK; + + if (type->tt_type == VAR_FUNC) + { + if (type->tt_member != &t_any && type->tt_member != &t_unknown) - { - type_T *expected = NULL; - - if (context->arg_types[0].type_curr->tt_type == VAR_LIST - || context->arg_types[0].type_curr->tt_type == VAR_DICT) - expected = context->arg_types[0].type_curr->tt_member; - else if (context->arg_types[0].type_curr->tt_type == VAR_STRING) - expected = &t_string; - else if (context->arg_types[0].type_curr->tt_type == VAR_BLOB) - expected = &t_number; - if (expected != NULL) - { - type_T t_func_exp = {VAR_FUNC, -1, 0, TTFLAG_STATIC, NULL, NULL}; - - t_func_exp.tt_member = expected; - return check_arg_type(&t_func_exp, type, context); - } + { + type_T *expected = NULL; + + if (context->arg_types[0].type_curr->tt_type == VAR_LIST + || context->arg_types[0].type_curr->tt_type == VAR_DICT) + expected = context->arg_types[0].type_curr->tt_member; + else if (context->arg_types[0].type_curr->tt_type == VAR_STRING) + expected = &t_string; + else if (context->arg_types[0].type_curr->tt_type == VAR_BLOB) + expected = &t_number; + if (expected != NULL) + { + type_T t_func_exp = {VAR_FUNC, -1, 0, TTFLAG_STATIC, NULL, NULL}; + + t_func_exp.tt_member = expected; + return check_arg_type(&t_func_exp, type, context); + } + } + } + else + { + semsg(_(e_string_or_function_required_for_argument_nr), 2); + return FAIL; } return OK; } diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -1275,6 +1275,7 @@ enddef def Test_filter() CheckDefAndScriptFailure(['filter(1.1, "1")'], ['E1013: Argument 1: type mismatch, expected list but got float', 'E1251: List, Dictionary, Blob or String required for argument 1']) + CheckDefAndScriptFailure(['filter([1, 2], 4)'], ['E1256: String or function required for argument 2', 'E1024: Using a Number as a String']) var lines =<< trim END def F(i: number, v: any): string @@ -2153,6 +2154,7 @@ def Test_map() CheckDefAndScriptFailure(['map(test_null_channel(), "1")'], ['E1013: Argument 1: type mismatch, expected list but got channel', 'E1251: List, Dictionary, Blob or String required for argument 1']) endif CheckDefAndScriptFailure(['map(1, "1")'], ['E1013: Argument 1: type mismatch, expected list but got number', 'E1251: List, Dictionary, Blob or String required for argument 1']) + CheckDefAndScriptFailure(['map([1, 2], 4)'], ['E1256: String or function required for argument 2', 'E1024: Using a Number as a String']) # type of dict remains dict even when type of values changes # same for list diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4224, +/**/ 4223, /**/ 4222,