]> granicus.if.org Git - vim/commitdiff
patch 8.2.2441: Vim9: extend() does not give an error for a type mismatch v8.2.2441
authorBram Moolenaar <Bram@vim.org>
Sun, 31 Jan 2021 16:48:30 +0000 (17:48 +0100)
committerBram Moolenaar <Bram@vim.org>
Sun, 31 Jan 2021 16:48:30 +0000 (17:48 +0100)
Problem:    Vim9: extend() does not give an error for a type mismatch.
Solution:   Check the type of the second argument. (closes #7760)

src/list.c
src/testdir/test_vim9_builtin.vim
src/version.c

index 77dd2a3074992fcddfbb1453daa92ca438706609..ca6e469c41a3fd0ac9871d0a7cdd0894ef6c9749 100644 (file)
@@ -2493,6 +2493,16 @@ f_count(typval_T *argvars, typval_T *rettv)
     static void
 extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
 {
+    type_T     *type = NULL;
+    garray_T   type_list;
+
+    if (!is_new && in_vim9script())
+    {
+       // Check that map() does not change the type of the dict.
+       ga_init2(&type_list, sizeof(type_T *), 10);
+       type = typval2type(argvars, &type_list);
+    }
+
     if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST)
     {
        list_T          *l1, *l2;
@@ -2504,7 +2514,7 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
        if (l1 == NULL)
        {
            emsg(_(e_cannot_extend_null_list));
-           return;
+           goto theend;
        }
        l2 = argvars[1].vval.v_list;
        if ((is_new || !value_check_lock(l1->lv_lock, arg_errmsg, TRUE))
@@ -2514,14 +2524,14 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
            {
                l1 = list_copy(l1, FALSE, get_copyID());
                if (l1 == NULL)
-                   return;
+                   goto theend;
            }
 
            if (argvars[2].v_type != VAR_UNKNOWN)
            {
                before = (long)tv_get_number_chk(&argvars[2], &error);
                if (error)
-                   return;             // type error; errmsg already given
+                   goto theend;        // type error; errmsg already given
 
                if (before == l1->lv_len)
                    item = NULL;
@@ -2531,12 +2541,14 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
                    if (item == NULL)
                    {
                        semsg(_(e_listidx), before);
-                       return;
+                       goto theend;
                    }
                }
            }
            else
                item = NULL;
+           if (type != NULL && check_typval_type(type, &argvars[1], 2) == FAIL)
+               goto theend;
            list_extend(l1, l2, item);
 
            if (is_new)
@@ -2559,7 +2571,7 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
        if (d1 == NULL)
        {
            emsg(_(e_cannot_extend_null_dict));
-           return;
+           goto theend;
        }
        d2 = argvars[1].vval.v_dict;
        if ((is_new || !value_check_lock(d1->dv_lock, arg_errmsg, TRUE))
@@ -2569,7 +2581,7 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
            {
                d1 = dict_copy(d1, FALSE, get_copyID());
                if (d1 == NULL)
-                   return;
+                   goto theend;
            }
 
            // Check the third argument.
@@ -2579,19 +2591,21 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
 
                action = tv_get_string_chk(&argvars[2]);
                if (action == NULL)
-                   return;             // type error; errmsg already given
+                   goto theend;        // type error; errmsg already given
                for (i = 0; i < 3; ++i)
                    if (STRCMP(action, av[i]) == 0)
                        break;
                if (i == 3)
                {
                    semsg(_(e_invarg2), action);
-                   return;
+                   goto theend;
                }
            }
            else
                action = (char_u *)"force";
 
+           if (type != NULL && check_typval_type(type, &argvars[1], 2) == FAIL)
+               goto theend;
            dict_extend(d1, d2, action);
 
            if (is_new)
@@ -2606,6 +2620,10 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
     }
     else
        semsg(_(e_listdictarg), is_new ? "extendnew()" : "extend()");
+
+theend:
+    if (type != NULL)
+       clear_type_list(&type_list);
 }
 
 /*
index d9275e617bd04a7366cbe2e91b372b1b2f1a1778..e7bec71c8e4ca1e3d312b1594e929422907a5e05 100644 (file)
@@ -240,19 +240,24 @@ def Test_expand()
 enddef
 
 def Test_extend_arg_types()
-  assert_equal([1, 2, 3], extend([1, 2], [3]))
-  assert_equal([3, 1, 2], extend([1, 2], [3], 0))
-  assert_equal([1, 3, 2], extend([1, 2], [3], 1))
-  assert_equal([1, 3, 2], extend([1, 2], [3], s:number_one))
-
-  assert_equal({a: 1, b: 2, c: 3}, extend({a: 1, b: 2}, {c: 3}))
-  assert_equal({a: 1, b: 4}, extend({a: 1, b: 2}, {b: 4}))
-  assert_equal({a: 1, b: 2}, extend({a: 1, b: 2}, {b: 4}, 'keep'))
-  assert_equal({a: 1, b: 2}, extend({a: 1, b: 2}, {b: 4}, s:string_keep))
-
-  var res: list<dict<any>>
-  extend(res, mapnew([1, 2], (_, v) => ({})))
-  assert_equal([{}, {}], res)
+  g:number_one = 1
+  g:string_keep = 'keep'
+  var lines =<< trim END
+      assert_equal([1, 2, 3], extend([1, 2], [3]))
+      assert_equal([3, 1, 2], extend([1, 2], [3], 0))
+      assert_equal([1, 3, 2], extend([1, 2], [3], 1))
+      assert_equal([1, 3, 2], extend([1, 2], [3], g:number_one))
+
+      assert_equal({a: 1, b: 2, c: 3}, extend({a: 1, b: 2}, {c: 3}))
+      assert_equal({a: 1, b: 4}, extend({a: 1, b: 2}, {b: 4}))
+      assert_equal({a: 1, b: 2}, extend({a: 1, b: 2}, {b: 4}, 'keep'))
+      assert_equal({a: 1, b: 2}, extend({a: 1, b: 2}, {b: 4}, g:string_keep))
+
+      var res: list<dict<any>>
+      extend(res, mapnew([1, 2], (_, v) => ({})))
+      assert_equal([{}, {}], res)
+  END
+  CheckDefAndScriptSuccess(lines)
 
   CheckDefFailure(['extend([1, 2], 3)'], 'E1013: Argument 2: type mismatch, expected list<number> but got number')
   CheckDefFailure(['extend([1, 2], ["x"])'], 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>')
@@ -300,8 +305,7 @@ def Test_extend_dict_item_type()
        var d: dict<number> = {a: 1}
        extend(d, {b: 'x'})
   END
-  CheckDefFailure(lines, 'E1013: Argument 2: type mismatch, expected dict<number> but got dict<string>', 2)
-  CheckScriptFailure(['vim9script'] + lines, 'E1012:', 3)
+  CheckDefAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected dict<number> but got dict<string>', 2)
 
   lines =<< trim END
        var d: dict<number> = {a: 1}
@@ -326,8 +330,7 @@ def Test_extend_list_item_type()
        var l: list<number> = [1]
        extend(l, ['x'])
   END
-  CheckDefFailure(lines, 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>', 2)
-  CheckScriptFailure(['vim9script'] + lines, 'E1012:', 3)
+  CheckDefAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>', 2)
 
   lines =<< trim END
        var l: list<number> = [1]
index c5074c2741f56fdbba51ee6e000051f728a99e5d..5555c77121e11e1c09f58c2db688e5bf1b30f049 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2441,
 /**/
     2440,
 /**/