To: vim_dev@googlegroups.com Subject: Patch 8.2.3150 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.3150 Problem: Vim9: argument types are not checked at compile time. Solution: Add more type checks. (Yegappan Lakshmanan, closes #8545) Files: src/evalfunc.c, src/testing.c, src/testdir/test_vim9_builtin.vim *** ../vim-8.2.3149/src/evalfunc.c 2021-07-11 18:23:15.437471705 +0200 --- src/evalfunc.c 2021-07-11 19:40:40.798766630 +0200 *************** *** 322,328 **** * Check "type" is a string or a list of strings. */ static int ! arg_string_or_list(type_T *type, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_STRING) return OK; --- 322,328 ---- * Check "type" is a string or a list of strings. */ static int ! arg_string_or_list_string(type_T *type, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_STRING) return OK; *************** *** 340,345 **** --- 340,358 ---- } /* + * Check "type" is a string or a list of 'any' + */ + static int + arg_string_or_list_any(type_T *type, argcontext_T *context) + { + if (type->tt_type == VAR_ANY + || type->tt_type == VAR_STRING || type->tt_type == VAR_LIST) + return OK; + arg_type_mismatch(&t_string, type, context->arg_idx + 1); + return FAIL; + } + + /* * Check "type" is a list or a dict. */ static int *************** *** 413,418 **** --- 426,445 ---- } /* + * Check "type" is a string or a number or a list + */ + static int + arg_str_or_nr_or_list(type_T *type, argcontext_T *context) + { + if (type->tt_type == VAR_STRING + || type->tt_type == VAR_NUMBER + || type->tt_type == VAR_LIST) + return OK; + arg_type_mismatch(&t_string, type, context->arg_idx + 1); + return FAIL; + } + + /* * Check "type" which is the third argument of extend(). */ static int *************** *** 438,444 **** argcheck_T arg1_list_string[] = {arg_list_string}; argcheck_T arg1_float_or_nr[] = {arg_float_or_nr}; argcheck_T arg1_string_or_nr[] = {arg_string_or_nr}; ! argcheck_T arg1_string_or_list[] = {arg_string_or_list}; argcheck_T arg1_list_or_blob[] = {arg_list_or_blob}; argcheck_T arg1_chan_or_job[] = {arg_chan_or_job}; argcheck_T arg2_float_or_nr[] = {arg_float_or_nr, arg_float_or_nr}; --- 465,472 ---- argcheck_T arg1_list_string[] = {arg_list_string}; argcheck_T arg1_float_or_nr[] = {arg_float_or_nr}; argcheck_T arg1_string_or_nr[] = {arg_string_or_nr}; ! argcheck_T arg1_string_or_list_any[] = {arg_string_or_list_any}; ! argcheck_T arg1_string_or_list_string[] = {arg_string_or_list_string}; argcheck_T arg1_list_or_blob[] = {arg_list_or_blob}; argcheck_T arg1_chan_or_job[] = {arg_chan_or_job}; argcheck_T arg2_float_or_nr[] = {arg_float_or_nr, arg_float_or_nr}; *************** *** 449,462 **** argcheck_T arg2_dict_string_or_nr[] = {arg_dict_any, arg_string_or_nr}; argcheck_T arg2_string_dict[] = {arg_string, arg_dict_any}; argcheck_T arg2_listblob_item[] = {arg_list_or_blob, arg_item_of_prev}; ! argcheck_T arg2_execute[] = {arg_string_or_list, arg_string}; ! argcheck_T arg23_win_execute[] = {arg_number, arg_string_or_list, arg_string}; ! argcheck_T arg23_extend[] = {arg_list_or_dict, arg_same_as_prev, arg_extend3}; ! argcheck_T arg23_extendnew[] = {arg_list_or_dict, arg_same_struct_as_prev, arg_extend3}; argcheck_T arg3_string[] = {arg_string, arg_string, arg_string}; argcheck_T arg3_number[] = {arg_number, arg_number, arg_number}; argcheck_T arg3_string_nr_bool[] = {arg_string, arg_number, arg_bool}; argcheck_T arg3_string_string_nr[] = {arg_string, arg_string, arg_number}; argcheck_T arg3_insert[] = {arg_list_or_blob, arg_item_of_prev, arg_number}; /* --- 477,494 ---- argcheck_T arg2_dict_string_or_nr[] = {arg_dict_any, arg_string_or_nr}; argcheck_T arg2_string_dict[] = {arg_string, arg_dict_any}; argcheck_T arg2_listblob_item[] = {arg_list_or_blob, arg_item_of_prev}; ! argcheck_T arg2_str_or_nr_or_list_dict[] = {arg_str_or_nr_or_list, arg_dict_any}; ! argcheck_T arg2_string_or_list_dict[] = {arg_string_or_list_any, arg_dict_any}; argcheck_T arg3_string[] = {arg_string, arg_string, arg_string}; argcheck_T arg3_number[] = {arg_number, arg_number, arg_number}; argcheck_T arg3_string_nr_bool[] = {arg_string, arg_number, arg_bool}; argcheck_T arg3_string_string_nr[] = {arg_string, arg_string, arg_number}; + argcheck_T arg2_execute[] = {arg_string_or_list_string, arg_string}; + argcheck_T arg23_win_execute[] = {arg_number, arg_string_or_list_string, arg_string}; + argcheck_T arg2_setline[] = {arg_string_or_nr, arg_string_or_list_any}; + argcheck_T arg3_setbufline[] = {arg_string_or_nr, arg_string_or_nr, arg_string_or_list_any}; + argcheck_T arg23_extend[] = {arg_list_or_dict, arg_same_as_prev, arg_extend3}; + argcheck_T arg23_extendnew[] = {arg_list_or_dict, arg_same_struct_as_prev, arg_extend3}; argcheck_T arg3_insert[] = {arg_list_or_blob, arg_item_of_prev, arg_number}; /* *************** *** 765,771 **** ret_number_bool, f_assert_notequal}, {"assert_notmatch", 2, 3, FEARG_2, arg3_string, ret_number_bool, f_assert_notmatch}, ! {"assert_report", 1, 1, FEARG_1, NULL, ret_number_bool, f_assert_report}, {"assert_true", 1, 2, FEARG_1, NULL, ret_number_bool, f_assert_true}, --- 797,803 ---- ret_number_bool, f_assert_notequal}, {"assert_notmatch", 2, 3, FEARG_2, arg3_string, ret_number_bool, f_assert_notmatch}, ! {"assert_report", 1, 1, FEARG_1, arg1_string, ret_number_bool, f_assert_report}, {"assert_true", 1, 2, FEARG_1, NULL, ret_number_bool, f_assert_true}, *************** *** 781,787 **** NULL #endif }, ! {"balloon_show", 1, 1, FEARG_1, arg1_string_or_list, ret_void, #ifdef FEAT_BEVAL f_balloon_show --- 813,819 ---- NULL #endif }, ! {"balloon_show", 1, 1, FEARG_1, arg1_string_or_list_any, ret_void, #ifdef FEAT_BEVAL f_balloon_show *************** *** 877,883 **** ret_number, f_char2nr}, {"charclass", 1, 1, FEARG_1, arg1_string, ret_number, f_charclass}, ! {"charcol", 1, 1, FEARG_1, arg1_string_or_list, ret_number, f_charcol}, {"charidx", 2, 3, FEARG_1, arg3_string_nr_bool, ret_number, f_charidx}, --- 909,915 ---- ret_number, f_char2nr}, {"charclass", 1, 1, FEARG_1, arg1_string, ret_number, f_charclass}, ! {"charcol", 1, 1, FEARG_1, arg1_string_or_list_any, ret_number, f_charcol}, {"charidx", 2, 3, FEARG_1, arg3_string_nr_bool, ret_number, f_charidx}, *************** *** 887,893 **** ret_number, f_cindent}, {"clearmatches", 0, 1, FEARG_1, arg1_number, ret_void, f_clearmatches}, ! {"col", 1, 1, FEARG_1, arg1_string_or_list, ret_number, f_col}, {"complete", 2, 2, FEARG_2, NULL, ret_void, f_complete}, --- 919,925 ---- ret_number, f_cindent}, {"clearmatches", 0, 1, FEARG_1, arg1_number, ret_void, f_clearmatches}, ! {"col", 1, 1, FEARG_1, arg1_string_or_list_any, ret_number, f_col}, {"complete", 2, 2, FEARG_2, NULL, ret_void, f_complete}, *************** *** 1301,1317 **** NULL #endif }, ! {"popup_atcursor", 2, 2, FEARG_1, NULL, ret_number, PROP_FUNC(f_popup_atcursor)}, ! {"popup_beval", 2, 2, FEARG_1, NULL, ret_number, PROP_FUNC(f_popup_beval)}, {"popup_clear", 0, 1, 0, NULL, 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, NULL, ret_number, PROP_FUNC(f_popup_create)}, ! {"popup_dialog", 2, 2, FEARG_1, NULL, ret_number, PROP_FUNC(f_popup_dialog)}, {"popup_filter_menu", 2, 2, 0, NULL, ret_bool, PROP_FUNC(f_popup_filter_menu)}, --- 1333,1349 ---- NULL #endif }, ! {"popup_atcursor", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict, ret_number, PROP_FUNC(f_popup_atcursor)}, ! {"popup_beval", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict, ret_number, PROP_FUNC(f_popup_beval)}, {"popup_clear", 0, 1, 0, NULL, 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)}, ! {"popup_dialog", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict, ret_number, PROP_FUNC(f_popup_dialog)}, {"popup_filter_menu", 2, 2, 0, NULL, ret_bool, PROP_FUNC(f_popup_filter_menu)}, *************** *** 1331,1341 **** ret_list_number, PROP_FUNC(f_popup_list)}, {"popup_locate", 2, 2, 0, arg2_number, ret_number, PROP_FUNC(f_popup_locate)}, ! {"popup_menu", 2, 2, FEARG_1, NULL, ret_number, PROP_FUNC(f_popup_menu)}, {"popup_move", 2, 2, FEARG_1, NULL, ret_void, PROP_FUNC(f_popup_move)}, ! {"popup_notification", 2, 2, FEARG_1, NULL, ret_number, PROP_FUNC(f_popup_notification)}, {"popup_setoptions", 2, 2, FEARG_1, NULL, ret_void, PROP_FUNC(f_popup_setoptions)}, --- 1363,1373 ---- ret_list_number, PROP_FUNC(f_popup_list)}, {"popup_locate", 2, 2, 0, arg2_number, ret_number, PROP_FUNC(f_popup_locate)}, ! {"popup_menu", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict, ret_number, PROP_FUNC(f_popup_menu)}, {"popup_move", 2, 2, FEARG_1, NULL, ret_void, PROP_FUNC(f_popup_move)}, ! {"popup_notification", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict, ret_number, PROP_FUNC(f_popup_notification)}, {"popup_setoptions", 2, 2, FEARG_1, NULL, ret_void, PROP_FUNC(f_popup_setoptions)}, *************** *** 1541,1547 **** ret_string, f_shellescape}, {"shiftwidth", 0, 1, FEARG_1, arg1_number, ret_number, f_shiftwidth}, ! {"sign_define", 1, 2, FEARG_1, arg2_string_dict, ret_any, SIGN_FUNC(f_sign_define)}, {"sign_getdefined", 0, 1, FEARG_1, NULL, ret_list_dict_any, SIGN_FUNC(f_sign_getdefined)}, --- 1573,1579 ---- ret_string, f_shellescape}, {"shiftwidth", 0, 1, FEARG_1, arg1_number, ret_number, f_shiftwidth}, ! {"sign_define", 1, 2, FEARG_1, arg2_string_or_list_dict, ret_any, SIGN_FUNC(f_sign_define)}, {"sign_getdefined", 0, 1, FEARG_1, NULL, ret_list_dict_any, SIGN_FUNC(f_sign_getdefined)}, *************** *** 1553,1559 **** ret_number, SIGN_FUNC(f_sign_place)}, {"sign_placelist", 1, 1, FEARG_1, NULL, ret_list_number, SIGN_FUNC(f_sign_placelist)}, ! {"sign_undefine", 0, 1, FEARG_1, arg1_string_or_list, ret_number_bool, SIGN_FUNC(f_sign_undefine)}, {"sign_unplace", 1, 2, FEARG_1, arg2_string_dict, ret_number_bool, SIGN_FUNC(f_sign_unplace)}, --- 1585,1591 ---- ret_number, SIGN_FUNC(f_sign_place)}, {"sign_placelist", 1, 1, FEARG_1, NULL, ret_list_number, SIGN_FUNC(f_sign_placelist)}, ! {"sign_undefine", 0, 1, FEARG_1, arg1_string_or_list_string, ret_number_bool, SIGN_FUNC(f_sign_undefine)}, {"sign_unplace", 1, 2, FEARG_1, arg2_string_dict, ret_number_bool, SIGN_FUNC(f_sign_unplace)}, *************** *** 1827,1833 **** ret_list_any, f_uniq}, {"values", 1, 1, FEARG_1, arg1_dict, ret_list_any, f_values}, ! {"virtcol", 1, 1, FEARG_1, arg1_string_or_list, ret_number, f_virtcol}, {"visualmode", 0, 1, 0, NULL, ret_string, f_visualmode}, --- 1859,1865 ---- ret_list_any, f_uniq}, {"values", 1, 1, FEARG_1, arg1_dict, ret_list_any, f_values}, ! {"virtcol", 1, 1, FEARG_1, arg1_string_or_list_any, ret_number, f_virtcol}, {"visualmode", 0, 1, 0, NULL, ret_string, f_visualmode}, *** ../vim-8.2.3149/src/testing.c 2021-07-10 13:15:35.295053013 +0200 --- src/testing.c 2021-07-11 19:40:40.798766630 +0200 *************** *** 824,829 **** --- 824,832 ---- { garray_T ga; + if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) + return; + prepare_assert_error(&ga); ga_concat(&ga, tv_get_string(&argvars[0])); assert_error(&ga); *** ../vim-8.2.3149/src/testdir/test_vim9_builtin.vim 2021-07-11 18:23:15.441471695 +0200 --- src/testdir/test_vim9_builtin.vim 2021-07-11 19:40:40.798766630 +0200 *************** *** 213,224 **** --- 213,231 ---- CheckDefFailure(['assert_notmatch("a", "b", null)'], 'E1013: Argument 3: type mismatch, expected string but got special') enddef + def Test_assert_report() + CheckDefAndScriptFailure2(['assert_report([1, 2])'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E1174: String required for argument 1') + enddef + def Test_balloon_show() CheckGui CheckFeature balloon_eval assert_fails('balloon_show(10)', 'E1174:') assert_fails('balloon_show(true)', 'E1174:') + + CheckDefAndScriptFailure2(['balloon_show(1.2)'], 'E1013: Argument 1: type mismatch, expected string but got float', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['balloon_show({"a": 10})'], 'E1013: Argument 1: type mismatch, expected string but got dict', 'E1174: String required for argument 1') enddef def Test_balloon_split() *************** *** 387,392 **** --- 394,406 ---- def Test_charcol() CheckDefFailure(['charcol(10)'], 'E1013: Argument 1: type mismatch, expected string but got number') CheckDefFailure(['charcol({a: 10})'], 'E1013: Argument 1: type mismatch, expected string but got dict') + new + setline(1, ['abcdefgh']) + cursor(1, 4) + assert_equal(4, charcol('.')) + assert_equal(9, charcol([1, '$'])) + assert_equal(0, charcol([10, '$'])) + bw! enddef def Test_charidx() *************** *** 412,419 **** def Test_col() new ! setline(1, 'asdf') ! col([1, '$'])->assert_equal(5) assert_fails('col(true)', 'E1174:') --- 426,436 ---- def Test_col() new ! setline(1, 'abcdefgh') ! cursor(1, 4) ! assert_equal(4, col('.')) ! col([1, '$'])->assert_equal(9) ! assert_equal(0, col([10, '$'])) assert_fails('col(true)', 'E1174:') *************** *** 1503,1513 **** --- 1520,1555 ---- CheckDefFailure(['or(0x1, "x")'], 'E1013: Argument 2: type mismatch, expected number but got string') enddef + def Test_popup_atcursor() + CheckDefAndScriptFailure2(['popup_atcursor({"a": 10}, {})'], 'E1013: Argument 1: type mismatch, expected string but got dict', 'E450: buffer number, text or a list required') + CheckDefAndScriptFailure2(['popup_atcursor("a", [1, 2])'], 'E1013: Argument 2: type mismatch, expected dict but got list', 'E715: Dictionary required') + enddef + + def Test_popup_beval() + CheckDefAndScriptFailure2(['popup_beval({"a": 10}, {})'], 'E1013: Argument 1: type mismatch, expected string but got dict', 'E450: buffer number, text or a list required') + CheckDefAndScriptFailure2(['popup_beval("a", [1, 2])'], 'E1013: Argument 2: type mismatch, expected dict but got list', 'E715: Dictionary required') + enddef + + def Test_popup_dialog() + CheckDefAndScriptFailure2(['popup_dialog({"a": 10}, {})'], 'E1013: Argument 1: type mismatch, expected string but got dict', 'E450: buffer number, text or a list required') + CheckDefAndScriptFailure2(['popup_dialog("a", [1, 2])'], 'E1013: Argument 2: type mismatch, expected dict but got list', 'E715: Dictionary required') + enddef + def Test_popup_locate() CheckDefAndScriptFailure2(['popup_locate("a", 20)'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') CheckDefAndScriptFailure2(['popup_locate(10, "b")'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E1030: Using a String as a Number') enddef + def Test_popup_menu() + CheckDefAndScriptFailure2(['popup_menu({"a": 10}, {})'], 'E1013: Argument 1: type mismatch, expected string but got dict', 'E450: buffer number, text or a list required') + CheckDefAndScriptFailure2(['popup_menu("a", [1, 2])'], 'E1013: Argument 2: type mismatch, expected dict but got list', 'E715: Dictionary required') + enddef + + def Test_popup_notification() + CheckDefAndScriptFailure2(['popup_notification({"a": 10}, {})'], 'E1013: Argument 1: type mismatch, expected string but got dict', 'E450: buffer number, text or a list required') + CheckDefAndScriptFailure2(['popup_notification("a", [1, 2])'], 'E1013: Argument 2: type mismatch, expected dict but got list', 'E715: Dictionary required') + enddef + def Test_prevnonblank() CheckDefFailure(['prevnonblank(null)'], 'E1013: Argument 1: type mismatch, expected string but got special') assert_equal(0, prevnonblank(1)) *************** *** 1887,1892 **** --- 1929,1945 ---- CheckDefFailure(['setfperm("a", 0z10)'], 'E1013: Argument 2: type mismatch, expected string but got blob') enddef + def Test_setline() + new + setline(1, range(1, 4)) + assert_equal(['1', '2', '3', '4'], getline(1, '$')) + setline(1, ['a', 'b', 'c', 'd']) + assert_equal(['a', 'b', 'c', 'd'], getline(1, '$')) + setline(1, 'one') + assert_equal(['one', 'b', 'c', 'd'], getline(1, '$')) + bw! + enddef + def Test_setloclist() var items = [{filename: '/tmp/file', lnum: 1, valid: true}] var what = {items: items} *************** *** 2301,2306 **** --- 2354,2366 ---- def Test_virtcol() CheckDefAndScriptFailure2(['virtcol(1.1)'], 'E1013: Argument 1: type mismatch, expected string but got float', 'E1174: String required for argument 1') + new + setline(1, ['abcdefgh']) + cursor(1, 4) + assert_equal(4, virtcol('.')) + assert_equal(9, virtcol([1, '$'])) + assert_equal(0, virtcol([10, '$'])) + bw! enddef def Test_win_execute() *** ../vim-8.2.3149/src/version.c 2021-07-11 19:12:00.049760323 +0200 --- src/version.c 2021-07-11 19:42:52.174550850 +0200 *************** *** 757,758 **** --- 757,760 ---- { /* Add new patch number below this line */ + /**/ + 3150, /**/ -- hundred-and-one symptoms of being an internet addict: 119. You are reading a book and look for the scroll bar to get to the next page. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///