summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-01-31 17:48:30 +0100
committerBram Moolenaar <Bram@vim.org>2021-01-31 17:48:30 +0100
commitc03f5c677a1fba99d2379550ccf2391eaa43e2ac (patch)
tree0ef0fc822f310f39a3e8ba536c3665e4ee89ab9b /src
parent853886722c051ecaef6d818ce32a822e4f43dc2b (diff)
patch 8.2.2441: Vim9: extend() does not give an error for a type mismatchv8.2.2441
Problem: Vim9: extend() does not give an error for a type mismatch. Solution: Check the type of the second argument. (closes #7760)
Diffstat (limited to 'src')
-rw-r--r--src/list.c34
-rw-r--r--src/testdir/test_vim9_builtin.vim37
-rw-r--r--src/version.c2
3 files changed, 48 insertions, 25 deletions
diff --git a/src/list.c b/src/list.c
index 77dd2a3074..ca6e469c41 100644
--- a/src/list.c
+++ b/src/list.c
@@ -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);
}
/*
diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim
index d9275e617b..e7bec71c8e 100644
--- a/src/testdir/test_vim9_builtin.vim
+++ b/src/testdir/test_vim9_builtin.vim
@@ -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]
diff --git a/src/version.c b/src/version.c
index c5074c2741..5555c77121 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2441,
+/**/
2440,
/**/
2439,