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.

Raspunde prin e-mail lui