Skip to content

Commit c03f5c6

Browse files
committed
patch 8.2.2441: Vim9: extend() does not give an error for a type mismatch
Problem: Vim9: extend() does not give an error for a type mismatch. Solution: Check the type of the second argument. (closes #7760)
1 parent 8538867 commit c03f5c6

3 files changed

Lines changed: 48 additions & 25 deletions

File tree

src/list.c

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2493,6 +2493,16 @@ f_count(typval_T *argvars, typval_T *rettv)
24932493
static void
24942494
extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
24952495
{
2496+
type_T *type = NULL;
2497+
garray_T type_list;
2498+
2499+
if (!is_new && in_vim9script())
2500+
{
2501+
// Check that map() does not change the type of the dict.
2502+
ga_init2(&type_list, sizeof(type_T *), 10);
2503+
type = typval2type(argvars, &type_list);
2504+
}
2505+
24962506
if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST)
24972507
{
24982508
list_T *l1, *l2;
@@ -2504,7 +2514,7 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
25042514
if (l1 == NULL)
25052515
{
25062516
emsg(_(e_cannot_extend_null_list));
2507-
return;
2517+
goto theend;
25082518
}
25092519
l2 = argvars[1].vval.v_list;
25102520
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)
25142524
{
25152525
l1 = list_copy(l1, FALSE, get_copyID());
25162526
if (l1 == NULL)
2517-
return;
2527+
goto theend;
25182528
}
25192529

25202530
if (argvars[2].v_type != VAR_UNKNOWN)
25212531
{
25222532
before = (long)tv_get_number_chk(&argvars[2], &error);
25232533
if (error)
2524-
return; // type error; errmsg already given
2534+
goto theend; // type error; errmsg already given
25252535

25262536
if (before == l1->lv_len)
25272537
item = NULL;
@@ -2531,12 +2541,14 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
25312541
if (item == NULL)
25322542
{
25332543
semsg(_(e_listidx), before);
2534-
return;
2544+
goto theend;
25352545
}
25362546
}
25372547
}
25382548
else
25392549
item = NULL;
2550+
if (type != NULL && check_typval_type(type, &argvars[1], 2) == FAIL)
2551+
goto theend;
25402552
list_extend(l1, l2, item);
25412553

25422554
if (is_new)
@@ -2559,7 +2571,7 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
25592571
if (d1 == NULL)
25602572
{
25612573
emsg(_(e_cannot_extend_null_dict));
2562-
return;
2574+
goto theend;
25632575
}
25642576
d2 = argvars[1].vval.v_dict;
25652577
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)
25692581
{
25702582
d1 = dict_copy(d1, FALSE, get_copyID());
25712583
if (d1 == NULL)
2572-
return;
2584+
goto theend;
25732585
}
25742586

25752587
// Check the third argument.
@@ -2579,19 +2591,21 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
25792591

25802592
action = tv_get_string_chk(&argvars[2]);
25812593
if (action == NULL)
2582-
return; // type error; errmsg already given
2594+
goto theend; // type error; errmsg already given
25832595
for (i = 0; i < 3; ++i)
25842596
if (STRCMP(action, av[i]) == 0)
25852597
break;
25862598
if (i == 3)
25872599
{
25882600
semsg(_(e_invarg2), action);
2589-
return;
2601+
goto theend;
25902602
}
25912603
}
25922604
else
25932605
action = (char_u *)"force";
25942606

2607+
if (type != NULL && check_typval_type(type, &argvars[1], 2) == FAIL)
2608+
goto theend;
25952609
dict_extend(d1, d2, action);
25962610

25972611
if (is_new)
@@ -2606,6 +2620,10 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
26062620
}
26072621
else
26082622
semsg(_(e_listdictarg), is_new ? "extendnew()" : "extend()");
2623+
2624+
theend:
2625+
if (type != NULL)
2626+
clear_type_list(&type_list);
26092627
}
26102628

26112629
/*

src/testdir/test_vim9_builtin.vim

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -240,19 +240,24 @@ def Test_expand()
240240
enddef
241241

242242
def Test_extend_arg_types()
243-
assert_equal([1, 2, 3], extend([1, 2], [3]))
244-
assert_equal([3, 1, 2], extend([1, 2], [3], 0))
245-
assert_equal([1, 3, 2], extend([1, 2], [3], 1))
246-
assert_equal([1, 3, 2], extend([1, 2], [3], s:number_one))
247-
248-
assert_equal({a: 1, b: 2, c: 3}, extend({a: 1, b: 2}, {c: 3}))
249-
assert_equal({a: 1, b: 4}, extend({a: 1, b: 2}, {b: 4}))
250-
assert_equal({a: 1, b: 2}, extend({a: 1, b: 2}, {b: 4}, 'keep'))
251-
assert_equal({a: 1, b: 2}, extend({a: 1, b: 2}, {b: 4}, s:string_keep))
252-
253-
var res: list<dict<any>>
254-
extend(res, mapnew([1, 2], (_, v) => ({})))
255-
assert_equal([{}, {}], res)
243+
g:number_one = 1
244+
g:string_keep = 'keep'
245+
var lines =<< trim END
246+
assert_equal([1, 2, 3], extend([1, 2], [3]))
247+
assert_equal([3, 1, 2], extend([1, 2], [3], 0))
248+
assert_equal([1, 3, 2], extend([1, 2], [3], 1))
249+
assert_equal([1, 3, 2], extend([1, 2], [3], g:number_one))
250+
251+
assert_equal({a: 1, b: 2, c: 3}, extend({a: 1, b: 2}, {c: 3}))
252+
assert_equal({a: 1, b: 4}, extend({a: 1, b: 2}, {b: 4}))
253+
assert_equal({a: 1, b: 2}, extend({a: 1, b: 2}, {b: 4}, 'keep'))
254+
assert_equal({a: 1, b: 2}, extend({a: 1, b: 2}, {b: 4}, g:string_keep))
255+
256+
var res: list<dict<any>>
257+
extend(res, mapnew([1, 2], (_, v) => ({})))
258+
assert_equal([{}, {}], res)
259+
END
260+
CheckDefAndScriptSuccess(lines)
256261

257262
CheckDefFailure(['extend([1, 2], 3)'], 'E1013: Argument 2: type mismatch, expected list<number> but got number')
258263
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()
300305
var d: dict<number> = {a: 1}
301306
extend(d, {b: 'x'})
302307
END
303-
CheckDefFailure(lines, 'E1013: Argument 2: type mismatch, expected dict<number> but got dict<string>', 2)
304-
CheckScriptFailure(['vim9script'] + lines, 'E1012:', 3)
308+
CheckDefAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected dict<number> but got dict<string>', 2)
305309

306310
lines =<< trim END
307311
var d: dict<number> = {a: 1}
@@ -326,8 +330,7 @@ def Test_extend_list_item_type()
326330
var l: list<number> = [1]
327331
extend(l, ['x'])
328332
END
329-
CheckDefFailure(lines, 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>', 2)
330-
CheckScriptFailure(['vim9script'] + lines, 'E1012:', 3)
333+
CheckDefAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>', 2)
331334

332335
lines =<< trim END
333336
var l: list<number> = [1]

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,8 @@ static char *(features[]) =
750750

751751
static int included_patches[] =
752752
{ /* Add new patch number below this line */
753+
/**/
754+
2441,
753755
/**/
754756
2440,
755757
/**/

0 commit comments

Comments
 (0)