Skip to content

Commit 0b76b42

Browse files
committed
patch 8.2.0528: Vim9: function arguments insufficiently tested
Problem: Vim9: function arguments insufficiently tested. Solution: Check types. Add more tests. Fix function with varargs only.
1 parent ec5929d commit 0b76b42

4 files changed

Lines changed: 58 additions & 2 deletions

File tree

src/testdir/test_vim9_func.vim

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,19 @@ def Test_call_def_varargs()
130130
assert_equal('one,two,three', MyDefVarargs('one', 'two', 'three'))
131131
enddef
132132

133+
" Only varargs
134+
def MyVarargsOnly(...args: list<string>): string
135+
return join(args, ',')
136+
enddef
137+
138+
def Test_call_varargs_only()
139+
assert_equal('', MyVarargsOnly())
140+
assert_equal('one', MyVarargsOnly('one'))
141+
assert_equal('one,two', MyVarargsOnly('one', 'two'))
142+
call CheckDefFailure(['MyVarargsOnly(1)'], 'E1013: argument 1: type mismatch, expected string but got number')
143+
call CheckDefFailure(['MyVarargsOnly("one", 2)'], 'E1013: argument 2: type mismatch, expected string but got number')
144+
enddef
145+
133146
def Test_using_var_as_arg()
134147
call writefile(['def Func(x: number)', 'let x = 234', 'enddef'], 'Xdef')
135148
call assert_fails('so Xdef', 'E1006:')

src/userfunc.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3020,7 +3020,7 @@ ex_function(exarg_T *eap)
30203020

30213021
if (eap->cmdidx == CMD_def)
30223022
{
3023-
int lnum_save = SOURCING_LNUM;
3023+
int lnum_save = SOURCING_LNUM;
30243024

30253025
// error messages are for the first function line
30263026
SOURCING_LNUM = sourcing_lnum_top;
@@ -3034,7 +3034,8 @@ ex_function(exarg_T *eap)
30343034
// and uf_va_type.
30353035
int len = argtypes.ga_len - (varargs ? 1 : 0);
30363036

3037-
fp->uf_arg_types = ALLOC_CLEAR_MULT(type_T *, len);
3037+
if (len > 0)
3038+
fp->uf_arg_types = ALLOC_CLEAR_MULT(type_T *, len);
30383039
if (fp->uf_arg_types != NULL)
30393040
{
30403041
int i;

src/version.c

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

739739
static int included_patches[] =
740740
{ /* Add new patch number below this line */
741+
/**/
742+
528,
741743
/**/
742744
527,
743745
/**/

src/vim9compile.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ static int compile_expr1(char_u **arg, cctx_T *cctx);
130130
static int compile_expr2(char_u **arg, cctx_T *cctx);
131131
static int compile_expr3(char_u **arg, cctx_T *cctx);
132132
static void delete_def_function_contents(dfunc_T *dfunc);
133+
static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
134+
static int check_type(type_T *expected, type_T *actual, int give_msg);
133135

134136
/*
135137
* Lookup variable "name" in the local scope and return the index.
@@ -1240,6 +1242,32 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
12401242
return FAIL;
12411243
}
12421244

1245+
if (ufunc->uf_dfunc_idx >= 0)
1246+
{
1247+
int i;
1248+
1249+
for (i = 0; i < argcount; ++i)
1250+
{
1251+
type_T *expected;
1252+
type_T *actual;
1253+
1254+
if (i < regular_args)
1255+
{
1256+
if (ufunc->uf_arg_types == NULL)
1257+
continue;
1258+
expected = ufunc->uf_arg_types[i];
1259+
}
1260+
else
1261+
expected = ufunc->uf_va_type->tt_member;
1262+
actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1263+
if (check_type(expected, actual, FALSE) == FAIL)
1264+
{
1265+
arg_type_mismatch(expected, actual, i + 1);
1266+
return FAIL;
1267+
}
1268+
}
1269+
}
1270+
12431271
// Turn varargs into a list.
12441272
if (ufunc->uf_va_name != NULL)
12451273
{
@@ -2403,6 +2431,18 @@ type_mismatch(type_T *expected, type_T *actual)
24032431
vim_free(tofree2);
24042432
}
24052433

2434+
static void
2435+
arg_type_mismatch(type_T *expected, type_T *actual, int argidx)
2436+
{
2437+
char *tofree1, *tofree2;
2438+
2439+
semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"),
2440+
argidx,
2441+
type_name(expected, &tofree1), type_name(actual, &tofree2));
2442+
vim_free(tofree1);
2443+
vim_free(tofree2);
2444+
}
2445+
24062446
/*
24072447
* Check if the expected and actual types match.
24082448
*/

0 commit comments

Comments
 (0)