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<number>', '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<number>', '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<number>')
+   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<number>', 'E450: buffer 
number, text or a list required')
+   CheckDefAndScriptFailure2(['popup_atcursor("a", [1, 2])'], 'E1013: Argument 
2: type mismatch, expected dict<any> but got list<number>', 'E715: Dictionary 
required')
+ enddef
+ 
+ def Test_popup_beval()
+   CheckDefAndScriptFailure2(['popup_beval({"a": 10}, {})'], 'E1013: Argument 
1: type mismatch, expected string but got dict<number>', 'E450: buffer number, 
text or a list required')
+   CheckDefAndScriptFailure2(['popup_beval("a", [1, 2])'], 'E1013: Argument 2: 
type mismatch, expected dict<any> but got list<number>', 'E715: Dictionary 
required')
+ enddef
+ 
+ def Test_popup_dialog()
+   CheckDefAndScriptFailure2(['popup_dialog({"a": 10}, {})'], 'E1013: Argument 
1: type mismatch, expected string but got dict<number>', 'E450: buffer number, 
text or a list required')
+   CheckDefAndScriptFailure2(['popup_dialog("a", [1, 2])'], 'E1013: Argument 
2: type mismatch, expected dict<any> but got list<number>', '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<number>', 'E450: buffer number, 
text or a list required')
+   CheckDefAndScriptFailure2(['popup_menu("a", [1, 2])'], 'E1013: Argument 2: 
type mismatch, expected dict<any> but got list<number>', 'E715: Dictionary 
required')
+ enddef
+ 
+ def Test_popup_notification()
+   CheckDefAndScriptFailure2(['popup_notification({"a": 10}, {})'], 'E1013: 
Argument 1: type mismatch, expected string but got dict<number>', 'E450: buffer 
number, text or a list required')
+   CheckDefAndScriptFailure2(['popup_notification("a", [1, 2])'], 'E1013: 
Argument 2: type mismatch, expected dict<any> but got list<number>', '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 -- [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/202107111745.16BHjDeB878932%40masaka.moolenaar.net.

Raspunde prin e-mail lui