Patch 8.2.3221
Problem: Vim9: argument types are not checked at compile time.
Solution: Add several more type checks. (Yegappan Lakshmanan, closes #8632)
Files: src/evalfunc.c, src/popupwin.c, src/proto/typval.pro,
src/testdir/test_assert.vim, src/testdir/test_vim9_builtin.vim,
src/testdir/test_vim9_script.vim, src/testing.c, src/typval.c
*** ../vim-8.2.3220/src/evalfunc.c 2021-07-24 21:33:22.391681954 +0200
--- src/evalfunc.c 2021-07-25 15:55:35.014494127 +0200
***************
*** 558,563 ****
--- 558,601 ----
}
/*
+ * Check "type" which is the first argument of get() (blob or list or dict or
+ * funcref)
+ */
+ static int
+ arg_get1(type_T *type, argcontext_T *context)
+ {
+ if (type->tt_type == VAR_ANY
+ || type->tt_type == VAR_BLOB
+ || type->tt_type == VAR_LIST
+ || type->tt_type == VAR_DICT
+ || type->tt_type == VAR_FUNC
+ || type->tt_type == VAR_PARTIAL)
+ return OK;
+
+ arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
+ return FAIL;
+ }
+
+ /*
+ * Check "type" which is the first argument of len() (number or string or
+ * blob or list or dict)
+ */
+ static int
+ arg_len1(type_T *type, argcontext_T *context)
+ {
+ if (type->tt_type == VAR_ANY
+ || type->tt_type == VAR_STRING
+ || type->tt_type == VAR_NUMBER
+ || type->tt_type == VAR_BLOB
+ || type->tt_type == VAR_LIST
+ || type->tt_type == VAR_DICT)
+ return OK;
+
+ arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
+ return FAIL;
+ }
+
+ /*
* Check "type" which is the second argument of remove() (number or string or
* any)
*/
***************
*** 685,690 ****
--- 723,729 ----
static argcheck_T arg2_lnum[] = {arg_lnum, arg_lnum};
static argcheck_T arg2_lnum_number[] = {arg_lnum, arg_number};
static argcheck_T arg2_number[] = {arg_number, arg_number};
+ static argcheck_T arg2_number_any[] = {arg_number, NULL};
static argcheck_T arg2_number_bool[] = {arg_number, arg_bool};
static argcheck_T arg2_number_dict_any[] = {arg_number, arg_dict_any};
static argcheck_T arg2_number_list[] = {arg_number, arg_list_any};
***************
*** 716,721 ****
--- 755,761 ----
static argcheck_T arg3_number_string_string[] = {arg_number, arg_string,
arg_string};
static argcheck_T arg3_string[] = {arg_string, arg_string, arg_string};
static argcheck_T arg3_string_any_dict[] = {arg_string, NULL, arg_dict_any};
+ static argcheck_T arg3_string_any_string[] = {arg_string, NULL, arg_string};
static argcheck_T arg3_string_bool_bool[] = {arg_string, arg_bool, arg_bool};
static argcheck_T arg3_string_bool_dict[] = {arg_string, arg_bool,
arg_dict_any};
static argcheck_T arg3_string_number_bool[] = {arg_string, arg_number,
arg_bool};
***************
*** 729,734 ****
--- 769,776 ----
static argcheck_T arg4_string_string_number_string[] = {arg_string,
arg_string, arg_number, arg_string};
static argcheck_T arg5_number[] = {arg_number, arg_number, arg_number,
arg_number, arg_number};
/* Function specific argument types (not covered by the above) */
+ static argcheck_T arg15_assert_fails[] = {arg_string_or_nr,
arg_string_or_list_any, NULL, arg_number, arg_string};
+ static argcheck_T arg34_assert_inrange[] = {arg_float_or_nr, arg_float_or_nr,
arg_float_or_nr, arg_string};
static argcheck_T arg4_browse[] = {arg_bool, arg_string, arg_string,
arg_string};
static argcheck_T arg23_chanexpr[] = {arg_chan_or_job, NULL, arg_dict_any};
static argcheck_T arg23_chanraw[] = {arg_chan_or_job, arg_string_or_blob,
arg_dict_any};
***************
*** 738,752 ****
--- 780,797 ----
static argcheck_T arg12_execute[] = {arg_string_or_list_string, arg_string};
static argcheck_T arg23_extend[] = {arg_list_or_dict, arg_same_as_prev,
arg_extend3};
static argcheck_T arg23_extendnew[] = {arg_list_or_dict,
arg_same_struct_as_prev, arg_extend3};
+ static argcheck_T arg23_get[] = {arg_get1, arg_string_or_nr, NULL};
static argcheck_T arg14_glob[] = {arg_string, arg_bool, arg_bool, arg_bool};
static argcheck_T arg25_globpath[] = {arg_string, arg_string, arg_bool,
arg_bool, arg_bool};
static argcheck_T arg24_index[] = {arg_list_or_blob, arg_item_of_prev,
arg_number, arg_bool};
static argcheck_T arg23_insert[] = {arg_list_or_blob, arg_item_of_prev,
arg_number};
+ static argcheck_T arg1_len[] = {arg_len1};
static argcheck_T arg3_libcall[] = {arg_string, arg_string, arg_string_or_nr};
static argcheck_T arg14_maparg[] = {arg_string, arg_string, arg_bool,
arg_bool};
static argcheck_T arg2_mapfilter[] = {arg_list_or_dict_or_blob, NULL};
static argcheck_T arg25_matchadd[] = {arg_string, arg_string, arg_number,
arg_number, arg_dict_any};
static argcheck_T arg25_matchaddpos[] = {arg_string, arg_list_any,
arg_number, arg_number, arg_dict_any};
+ static argcheck_T arg119_printf[] = {arg_string_or_nr, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL};
static argcheck_T arg23_reduce[] = {arg_list_or_blob, NULL, NULL};
static argcheck_T arg24_remote_expr[] = {arg_string, arg_string, arg_string,
arg_number};
static argcheck_T arg23_remove[] = {arg_list_or_dict_or_blob, arg_remove2,
arg_number};
***************
*** 1067,1077 ****
ret_number_bool, f_assert_equalfile},
{"assert_exception", 1, 2, 0, arg2_string,
ret_number_bool, f_assert_exception},
! {"assert_fails", 1, 5, FEARG_1, NULL,
ret_number_bool, f_assert_fails},
{"assert_false", 1, 2, FEARG_1, NULL,
ret_number_bool, f_assert_false},
! {"assert_inrange", 3, 4, FEARG_3, NULL,
ret_number_bool, f_assert_inrange},
{"assert_match", 2, 3, FEARG_2, arg3_string,
ret_number_bool, f_assert_match},
--- 1112,1122 ----
ret_number_bool, f_assert_equalfile},
{"assert_exception", 1, 2, 0, arg2_string,
ret_number_bool, f_assert_exception},
! {"assert_fails", 1, 5, FEARG_1, arg15_assert_fails,
ret_number_bool, f_assert_fails},
{"assert_false", 1, 2, FEARG_1, NULL,
ret_number_bool, f_assert_false},
! {"assert_inrange", 3, 4, FEARG_3, arg34_assert_inrange,
ret_number_bool, f_assert_inrange},
{"assert_match", 2, 3, FEARG_2, arg3_string,
ret_number_bool, f_assert_match},
***************
*** 1325,1331 ****
ret_f_function, f_function},
{"garbagecollect", 0, 1, 0, arg1_bool,
ret_void, f_garbagecollect},
! {"get", 2, 3, FEARG_1, NULL,
ret_any, f_get},
{"getbufinfo", 0, 1, FEARG_1, arg1_buffer_or_dict_any,
ret_list_dict_any, f_getbufinfo},
--- 1370,1376 ----
ret_f_function, f_function},
{"garbagecollect", 0, 1, 0, arg1_bool,
ret_void, f_garbagecollect},
! {"get", 2, 3, FEARG_1, arg23_get,
ret_any, f_get},
{"getbufinfo", 0, 1, FEARG_1, arg1_buffer_or_dict_any,
ret_list_dict_any, f_getbufinfo},
***************
*** 1515,1521 ****
ret_list_string, f_keys},
{"last_buffer_nr", 0, 0, 0, NULL, // obsolete
ret_number, f_last_buffer_nr},
! {"len", 1, 1, FEARG_1, NULL,
ret_number, f_len},
{"libcall", 3, 3, FEARG_3, arg3_libcall,
ret_string, f_libcall},
--- 1560,1566 ----
ret_list_string, f_keys},
{"last_buffer_nr", 0, 0, 0, NULL, // obsolete
ret_number, f_last_buffer_nr},
! {"len", 1, 1, FEARG_1, arg1_len,
ret_number, f_len},
{"libcall", 3, 3, FEARG_3, arg3_libcall,
ret_string, f_libcall},
***************
*** 1541,1547 ****
ret_float, FLOAT_FUNC(f_log)},
{"log10", 1, 1, FEARG_1, arg1_float_or_nr,
ret_float, FLOAT_FUNC(f_log10)},
! {"luaeval", 1, 2, FEARG_1, NULL,
ret_any,
#ifdef FEAT_LUA
f_luaeval
--- 1586,1592 ----
ret_float, FLOAT_FUNC(f_log)},
{"log10", 1, 1, FEARG_1, arg1_float_or_nr,
ret_float, FLOAT_FUNC(f_log10)},
! {"luaeval", 1, 2, FEARG_1, arg2_string_any,
ret_any,
#ifdef FEAT_LUA
f_luaeval
***************
*** 1627,1633 ****
ret_number, PROP_FUNC(f_popup_beval)},
{"popup_clear", 0, 1, 0, arg1_bool,
ret_void, PROP_FUNC(f_popup_clear)},
! {"popup_close", 1, 2, FEARG_1, NULL,
ret_void, PROP_FUNC(f_popup_close)},
{"popup_create", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict,
ret_number, PROP_FUNC(f_popup_create)},
--- 1672,1678 ----
ret_number, PROP_FUNC(f_popup_beval)},
{"popup_clear", 0, 1, 0, arg1_bool,
ret_void, PROP_FUNC(f_popup_clear)},
! {"popup_close", 1, 2, FEARG_1, arg2_number_any,
ret_void, PROP_FUNC(f_popup_close)},
{"popup_create", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict,
ret_number, PROP_FUNC(f_popup_create)},
***************
*** 1667,1673 ****
ret_float, FLOAT_FUNC(f_pow)},
{"prevnonblank", 1, 1, FEARG_1, arg1_lnum,
ret_number, f_prevnonblank},
! {"printf", 1, 19, FEARG_2, NULL,
ret_string, f_printf},
{"prompt_getprompt", 1, 1, FEARG_1, arg1_buffer,
ret_string, JOB_FUNC(f_prompt_getprompt)},
--- 1712,1718 ----
ret_float, FLOAT_FUNC(f_pow)},
{"prevnonblank", 1, 1, FEARG_1, arg1_lnum,
ret_number, f_prevnonblank},
! {"printf", 1, 19, FEARG_2, arg119_printf,
ret_string, f_printf},
{"prompt_getprompt", 1, 1, FEARG_1, arg1_buffer,
ret_string, JOB_FUNC(f_prompt_getprompt)},
***************
*** 1829,1835 ****
ret_bool, f_setdigraph},
{"setdigraphlist", 1, 1, FEARG_1, arg1_list_string,
ret_bool, f_setdigraphlist},
! {"setenv", 2, 2, FEARG_2, NULL,
ret_void, f_setenv},
{"setfperm", 2, 2, FEARG_1, arg2_string,
ret_number_bool, f_setfperm},
--- 1874,1880 ----
ret_bool, f_setdigraph},
{"setdigraphlist", 1, 1, FEARG_1, arg1_list_string,
ret_bool, f_setdigraphlist},
! {"setenv", 2, 2, FEARG_2, arg2_string_any,
ret_void, f_setenv},
{"setfperm", 2, 2, FEARG_1, arg2_string,
ret_number_bool, f_setfperm},
***************
*** 1843,1849 ****
ret_number_bool, f_setpos},
{"setqflist", 1, 3, FEARG_1, arg13_setqflist,
ret_number_bool, f_setqflist},
! {"setreg", 2, 3, FEARG_2, NULL,
ret_number_bool, f_setreg},
{"settabvar", 3, 3, FEARG_3, arg3_number_string_any,
ret_void, f_settabvar},
--- 1888,1894 ----
ret_number_bool, f_setpos},
{"setqflist", 1, 3, FEARG_1, arg13_setqflist,
ret_number_bool, f_setqflist},
! {"setreg", 2, 3, FEARG_2, arg3_string_any_string,
ret_number_bool, f_setreg},
{"settabvar", 3, 3, FEARG_3, arg3_number_string_any,
ret_void, f_settabvar},
***************
*** 6563,6568 ****
--- 6608,6616 ----
if (check_restricted() || check_secure())
return;
+ if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
+ return;
+
str = tv_get_string_buf(&argvars[0], buf);
do_luaeval(str, argvars + 1, rettv);
}
***************
*** 7139,7144 ****
--- 7187,7195 ----
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
+ if (in_vim9script() && check_for_string_or_number_arg(argvars, 0) == FAIL)
+ return;
+
// Get the required length, allocate the buffer and do it for real.
did_emsg = FALSE;
fmt = (char *)tv_get_string_buf(&argvars[0], buf);
***************
*** 8515,8522 ****
{
char_u namebuf[NUMBUFLEN];
char_u valbuf[NUMBUFLEN];
! char_u *name = tv_get_string_buf(&argvars[0], namebuf);
if (argvars[1].v_type == VAR_SPECIAL
&& argvars[1].vval.v_number == VVAL_NULL)
vim_unsetenv(name);
--- 8566,8577 ----
{
char_u namebuf[NUMBUFLEN];
char_u valbuf[NUMBUFLEN];
! char_u *name;
!
! if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
! return;
+ name = tv_get_string_buf(&argvars[0], namebuf);
if (argvars[1].v_type == VAR_SPECIAL
&& argvars[1].vval.v_number == VVAL_NULL)
vim_unsetenv(name);
***************
*** 8616,8621 ****
--- 8671,8681 ----
typval_T *regcontents;
int pointreg;
+ if (in_vim9script()
+ && (check_for_string_arg(argvars, 0) == FAIL
+ || check_for_opt_string_arg(argvars, 2) == FAIL))
+ return;
+
pointreg = 0;
regcontents = NULL;
block_len = -1;
*** ../vim-8.2.3220/src/popupwin.c 2021-07-23 20:37:52.022322433 +0200
--- src/popupwin.c 2021-07-25 15:55:35.014494127 +0200
***************
*** 2516,2524 ****
void
f_popup_close(typval_T *argvars, typval_T *rettv UNUSED)
{
! int id = (int)tv_get_number(argvars);
win_T *wp;
if (
# ifdef FEAT_TERMINAL
// if the popup contains a terminal it will become hidden
--- 2516,2528 ----
void
f_popup_close(typval_T *argvars, typval_T *rettv UNUSED)
{
! int id;
win_T *wp;
+ if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
+ return;
+
+ id = (int)tv_get_number(argvars);
if (
# ifdef FEAT_TERMINAL
// if the popup contains a terminal it will become hidden
*** ../vim-8.2.3220/src/proto/typval.pro 2021-07-24 16:16:11.542239515
+0200
--- src/proto/typval.pro 2021-07-25 15:55:35.014494127 +0200
***************
*** 14,19 ****
--- 14,20 ----
int check_for_opt_string_arg(typval_T *args, int idx);
int check_for_number_arg(typval_T *args, int idx);
int check_for_opt_number_arg(typval_T *args, int idx);
+ int check_for_float_or_nr_arg(typval_T *args, int idx);
int check_for_bool_arg(typval_T *args, int idx);
int check_for_opt_bool_arg(typval_T *args, int idx);
int check_for_list_arg(typval_T *args, int idx);
***************
*** 31,36 ****
--- 32,38 ----
int check_for_opt_string_or_number_arg(typval_T *args, int idx);
int check_for_string_or_blob_arg(typval_T *args, int idx);
int check_for_string_or_list_arg(typval_T *args, int idx);
+ int check_for_opt_string_or_list_arg(typval_T *args, int idx);
int check_for_list_or_blob_arg(typval_T *args, int idx);
int check_for_list_or_dict_or_blob_arg(typval_T *args, int idx);
int check_for_buffer_or_dict_arg(typval_T *args, int idx);
*** ../vim-8.2.3220/src/testdir/test_assert.vim 2021-06-22 19:52:23.901800877
+0200
--- src/testdir/test_assert.vim 2021-07-25 15:55:35.014494127 +0200
***************
*** 268,288 ****
catch
let exp = v:exception
endtry
! call assert_match("E856: \"assert_fails()\" second argument", exp)
try
call assert_equal(1, assert_fails('xxx', 'E492', '', 'burp'))
catch
let exp = v:exception
endtry
! call assert_match("E1115: \"assert_fails()\" fourth argument must be a
number", exp)
try
call assert_equal(1, assert_fails('xxx', 'E492', '', 54, 123))
catch
let exp = v:exception
endtry
! call assert_match("E1116: \"assert_fails()\" fifth argument must be a
string", exp)
endfunc
func Test_assert_fails_in_try_block()
--- 268,288 ----
catch
let exp = v:exception
endtry
! call assert_match("E1174: String required for argument 2", exp)
try
call assert_equal(1, assert_fails('xxx', 'E492', '', 'burp'))
catch
let exp = v:exception
endtry
! call assert_match("E1210: Number required for argument 4", exp)
try
call assert_equal(1, assert_fails('xxx', 'E492', '', 54, 123))
catch
let exp = v:exception
endtry
! call assert_match("E1174: String required for argument 5", exp)
endfunc
func Test_assert_fails_in_try_block()
*** ../vim-8.2.3220/src/testdir/test_vim9_builtin.vim 2021-07-25
15:41:40.996569003 +0200
--- src/testdir/test_vim9_builtin.vim 2021-07-25 15:55:35.014494127 +0200
***************
*** 234,239 ****
--- 234,253 ----
CheckDefFailure(['assert_exception("E1:", v:null)'], 'E1013: Argument 2:
type mismatch, expected string but got special')
enddef
+ def Test_assert_fails()
+ CheckDefAndScriptFailure2(['assert_fails([])'], 'E1013: Argument 1: type
mismatch, expected string but got list<unknown>', 'E1174: String required for
argument 1')
+ CheckDefAndScriptFailure2(['assert_fails("a", true)'], 'E1013: Argument 2:
type mismatch, expected string but got bool', 'E1174: String required for
argument 2')
+ CheckDefAndScriptFailure2(['assert_fails("a", "b", "c", "d")'], 'E1013:
Argument 4: type mismatch, expected number but got string', 'E1210: Number
required for argument 4')
+ CheckDefAndScriptFailure2(['assert_fails("a", "b", "c", 4, 5)'], 'E1013:
Argument 5: type mismatch, expected string but got number', 'E1174: String
required for argument 5')
+ enddef
+
+ def Test_assert_inrange()
+ CheckDefAndScriptFailure2(['assert_inrange("a", 2, 3)'], 'E1013: Argument
1: type mismatch, expected number but got string', 'E1210: Number required for
argument 1')
+ CheckDefAndScriptFailure2(['assert_inrange(1, "b", 3)'], 'E1013: Argument
2: type mismatch, expected number but got string', 'E1210: Number required for
argument 2')
+ CheckDefAndScriptFailure2(['assert_inrange(1, 2, "c")'], 'E1013: Argument
3: type mismatch, expected number but got string', 'E1210: Number required for
argument 3')
+ CheckDefAndScriptFailure2(['assert_inrange(1, 2, 3, 4)'], 'E1013: Argument
4: type mismatch, expected string but got number', 'E1174: String required for
argument 4')
+ enddef
+
def Test_assert_match()
CheckDefFailure(['assert_match({}, "b")'], 'E1013: Argument 1: type
mismatch, expected string but got dict<unknown>')
CheckDefFailure(['assert_match("a", 1)'], 'E1013: Argument 2: type
mismatch, expected string but got number')
***************
*** 1144,1149 ****
--- 1158,1177 ----
CheckDefAndScriptFailure2(['garbagecollect(20)'], 'E1013: Argument 1: type
mismatch, expected bool but got number', 'E1023: Using a Number as a Bool')
enddef
+ def Test_get()
+ CheckDefAndScriptFailure2(['get("a", 1)'], 'E1013: Argument 1: type
mismatch, expected list<any> but got string', 'E896: Argument of get() must be
a List, Dictionary or Blob')
+ [3, 5, 2]->get(1)->assert_equal(5)
+ [3, 5, 2]->get(3)->assert_equal(0)
+ [3, 5, 2]->get(3, 9)->assert_equal(9)
+ assert_equal(get(0z102030, 2), 0x30)
+ {a: 7, b: 11, c: 13}->get('c')->assert_equal(13)
+ {10: 'a', 20: 'b', 30: 'd'}->get(20)->assert_equal('b')
+ function('max')->get('name')->assert_equal('max')
+ var F: func = function('min', [[5, 8, 6]])
+ F->get('name')->assert_equal('min')
+ F->get('args')->assert_equal([[5, 8, 6]])
+ enddef
+
def Test_getbufinfo()
var bufinfo = getbufinfo(bufnr())
getbufinfo('%')->assert_equal(bufinfo)
***************
*** 1703,1708 ****
--- 1731,1745 ----
var->assert_equal(['a', 'b'])
enddef
+ def Test_len()
+ CheckDefAndScriptFailure2(['len(true)'], 'E1013: Argument 1: type mismatch,
expected list<any> but got bool', 'E701: Invalid type for len()')
+ assert_equal(2, "ab"->len())
+ assert_equal(3, 456->len())
+ assert_equal(0, []->len())
+ assert_equal(1, {a: 10}->len())
+ assert_equal(4, 0z20304050->len())
+ enddef
+
def Test_libcall()
CheckFeature libcall
CheckDefAndScriptFailure2(['libcall(1, "b", 3)'], 'E1013: Argument 1: type
mismatch, expected string but got number', 'E1174: String required for argument
1')
***************
*** 1764,1769 ****
--- 1801,1813 ----
CheckDefAndScriptFailure2(['listener_remove("x")'], 'E1013: Argument 1:
type mismatch, expected number but got string', 'E1030: Using a String as a
Number')
enddef
+ def Test_lua()
+ if !has('lua')
+ CheckFeature lua
+ endif
+ CheckDefAndScriptFailure2(['luaeval(10)'], 'E1013: Argument 1: type
mismatch, expected string but got number', 'E1174: String required for argument
1')
+ enddef
+
def Test_map()
CheckDefAndScriptFailure2(['map("x", "1")'], 'E1013: Argument 1: type
mismatch, expected list<any> but got string', 'E1211: List required for
argument 1')
CheckDefAndScriptFailure2(['map(1, "1")'], 'E1013: Argument 1: type
mismatch, expected list<any> but got number', 'E1211: List required for
argument 1')
***************
*** 2112,2117 ****
--- 2156,2165 ----
CheckDefAndScriptFailure2(['popup_clear(2)'], 'E1013: Argument 1: type
mismatch, expected bool but got number', 'E1023: Using a Number as a Bool')
enddef
+ def Test_popup_close()
+ CheckDefAndScriptFailure2(['popup_close("a")'], 'E1013: Argument 1: type
mismatch, expected number but got string', 'E1210: Number required for argument
1')
+ enddef
+
def Test_popup_create()
# Pass variable of type 'any' to popup_create()
var what: any = 'Hello'
***************
*** 2190,2195 ****
--- 2238,2249 ----
assert_equal(0, prevnonblank(1))
enddef
+ def Test_printf()
+ CheckDefAndScriptFailure2(['printf([1])'], 'E1013: Argument 1: type
mismatch, expected string but got list<number>', 'E1174: String required for
argument 1')
+ printf(0x10)->assert_equal('16')
+ assert_equal(" abc", "abc"->printf("%4s"))
+ enddef
+
def Test_prompt_getprompt()
if !has('channel')
CheckFeature channel
***************
*** 2798,2803 ****
--- 2852,2861 ----
CheckDefAndScriptFailure2(['setcursorcharpos(1, 2, "3")'], 'E1013: Argument
3: type mismatch, expected number but got string', 'E1210: Number required for
argument 3')
enddef
+ def Test_setenv()
+ CheckDefAndScriptFailure2(['setenv(1, 2)'], 'E1013: Argument 1: type
mismatch, expected string but got number', 'E1174: String required for argument
1')
+ enddef
+
def Test_setfperm()
CheckDefFailure(['setfperm(1, "b")'], 'E1013: Argument 1: type mismatch,
expected string but got number')
CheckDefFailure(['setfperm("a", 0z10)'], 'E1013: Argument 2: type mismatch,
expected string but got blob')
***************
*** 2851,2856 ****
--- 2909,2916 ----
setreg('a', reginfo)
getreginfo('a')->assert_equal(reginfo)
assert_fails('setreg("ab", 0)', 'E1162:')
+ CheckDefAndScriptFailure2(['setreg(1, "b")'], 'E1013: Argument 1: type
mismatch, expected string but got number', 'E1174: String required for argument
1')
+ CheckDefAndScriptFailure2(['setreg("a", "b", 3)'], 'E1013: Argument 3: type
mismatch, expected string but got number', 'E1174: String required for argument
3')
enddef
def Test_settabvar()
*** ../vim-8.2.3220/src/testdir/test_vim9_script.vim 2021-07-25
14:13:50.040566339 +0200
--- src/testdir/test_vim9_script.vim 2021-07-25 15:55:35.014494127 +0200
***************
*** 521,528 ****
assert_equal(344, n)
try
! echo len(v:true)
! catch /E701:/
n = 355
endtry
assert_equal(355, n)
--- 521,528 ----
assert_equal(344, n)
try
! echo range(1, 2, 0)
! catch /E726:/
n = 355
endtry
assert_equal(355, n)
*** ../vim-8.2.3220/src/testing.c 2021-07-24 21:33:22.391681954 +0200
--- src/testing.c 2021-07-25 15:55:35.014494127 +0200
***************
*** 566,577 ****
void
f_assert_fails(typval_T *argvars, typval_T *rettv)
{
! char_u *cmd = tv_get_string_chk(&argvars[0]);
garray_T ga;
int save_trylevel = trylevel;
int called_emsg_before = called_emsg;
char *wrong_arg_msg = NULL;
// trylevel must be zero for a ":throw" command to be considered failed
trylevel = 0;
suppress_errthrow = TRUE;
--- 566,588 ----
void
f_assert_fails(typval_T *argvars, typval_T *rettv)
{
! char_u *cmd;
garray_T ga;
int save_trylevel = trylevel;
int called_emsg_before = called_emsg;
char *wrong_arg_msg = NULL;
+ if (check_for_string_or_number_arg(argvars, 0) == FAIL
+ || check_for_opt_string_or_list_arg(argvars, 1) == FAIL
+ || (argvars[1].v_type != VAR_UNKNOWN
+ && (argvars[2].v_type != VAR_UNKNOWN
+ && (check_for_opt_number_arg(argvars, 3) == FAIL
+ || (argvars[3].v_type != VAR_UNKNOWN
+ && check_for_opt_string_arg(argvars, 4) == FAIL)))))
+ return;
+
+ cmd = tv_get_string_chk(&argvars[0]);
+
// trylevel must be zero for a ":throw" command to be considered failed
trylevel = 0;
suppress_errthrow = TRUE;
***************
*** 799,804 ****
--- 810,821 ----
void
f_assert_inrange(typval_T *argvars, typval_T *rettv)
{
+ if (check_for_float_or_nr_arg(argvars, 0) == FAIL
+ || check_for_float_or_nr_arg(argvars, 1) == FAIL
+ || check_for_float_or_nr_arg(argvars, 2) == FAIL
+ || check_for_opt_string_arg(argvars, 3) == FAIL)
+ return;
+
rettv->vval.v_number = assert_inrange(argvars);
}
*** ../vim-8.2.3220/src/typval.c 2021-07-24 16:16:11.542239515 +0200
--- src/typval.c 2021-07-25 15:55:35.014494127 +0200
***************
*** 422,427 ****
--- 422,444 ----
}
/*
+ * Give an error and return FAIL unless "args[idx]" is a float or a number.
+ */
+ int
+ check_for_float_or_nr_arg(typval_T *args, int idx)
+ {
+ if (args[idx].v_type != VAR_FLOAT && args[idx].v_type != VAR_NUMBER)
+ {
+ if (idx >= 0)
+ semsg(_(e_number_required_for_argument_nr), idx + 1);
+ else
+ emsg(_(e_numberreq));
+ return FAIL;
+ }
+ return OK;
+ }
+
+ /*
* Give an error and return FAIL unless "args[idx]" is a bool.
*/
int
***************
*** 653,658 ****
--- 670,685 ----
}
/*
+ * Check for an optional string or list argument at 'idx'
+ */
+ int
+ check_for_opt_string_or_list_arg(typval_T *args, int idx)
+ {
+ return (args[idx].v_type == VAR_UNKNOWN
+ || check_for_string_or_list_arg(args, idx));
+ }
+
+ /*
* Give an error and return FAIL unless "args[idx]" is a list or a blob.
*/
int
*** ../vim-8.2.3220/src/version.c 2021-07-25 15:41:40.996569003 +0200
--- src/version.c 2021-07-25 15:56:53.050306622 +0200
***************
*** 757,758 ****
--- 757,760 ----
{ /* Add new patch number below this line */
+ /**/
+ 3221,
/**/
--
You are Dead. Do you wish to restart, load, or quit?
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/202107251358.16PDw7r71083954%40masaka.moolenaar.net.