summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-07-23 20:56:04 +0200
committerBram Moolenaar <Bram@vim.org>2020-07-23 20:56:04 +0200
commitb8070e31736decfcdf8dd47997882cb8f5a64c9d (patch)
tree1ec82d4dd046ee21a6763f5af678aad96831549a
parentbfba8651a51b66fdc52848f32c77aa925586e250 (diff)
patch 8.2.1285: Vim9: argument types are not checked on assignmentv8.2.1285
Problem: Vim9: argument types are not checked on assignment. Solution: Check function argument types. (issue #6507)
-rw-r--r--src/testdir/test_vim9_func.vim9
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c23
3 files changed, 34 insertions, 0 deletions
diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim
index c8c6afee09..b0bbab3fdf 100644
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -293,6 +293,15 @@ def Test_call_funcref()
Funcref(123)
END
CheckScriptSuccess(lines)
+
+ lines =<< trim END
+ vim9script
+ def UseNumber(nr: number)
+ echo nr
+ enddef
+ let Funcref: func(string) = function('UseNumber')
+ END
+ CheckScriptFailure(lines, 'E1013: type mismatch, expected func(string) but got func(number)')
enddef
let SomeFunc = function('len')
diff --git a/src/version.c b/src/version.c
index 91edd4ad85..5563bd1fa6 100644
--- a/src/version.c
+++ b/src/version.c
@@ -755,6 +755,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1285,
+/**/
1284,
/**/
1283,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index e032e23a92..52841de6bd 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -638,6 +638,18 @@ check_type(type_T *expected, type_T *actual, int give_msg)
&& (actual->tt_argcount < expected->tt_min_argcount
|| actual->tt_argcount > expected->tt_argcount))
ret = FAIL;
+ if (expected->tt_args != NULL && actual->tt_args != NULL)
+ {
+ int i;
+
+ for (i = 0; i < expected->tt_argcount; ++i)
+ if (check_type(expected->tt_args[i], actual->tt_args[i],
+ FALSE) == FAIL)
+ {
+ ret = FAIL;
+ break;
+ }
+ }
}
if (ret == FAIL && give_msg)
type_mismatch(expected, actual);
@@ -2819,6 +2831,10 @@ generate_funcref(cctx_T *cctx, char_u *name)
if (ufunc == NULL)
return FAIL;
+ // Need to compile any default values to get the argument types.
+ if (ufunc->uf_def_status == UF_TO_BE_COMPILED)
+ if (compile_def_function(ufunc, TRUE, NULL) == FAIL)
+ return FAIL;
return generate_PUSHFUNC(cctx, vim_strsave(ufunc->uf_name),
ufunc->uf_func_type);
}
@@ -6995,6 +7011,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
int i;
char_u *arg;
int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
+ int did_set_arg_type = FALSE;
// Produce instructions for the default values of optional arguments.
// Store the instruction index in uf_def_arg_idx[] so that we know
@@ -7019,7 +7036,10 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
// specified type.
val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
+ {
+ did_set_arg_type = TRUE;
ufunc->uf_arg_types[arg_idx] = val_type;
+ }
else if (check_type(ufunc->uf_arg_types[arg_idx], val_type, FALSE)
== FAIL)
{
@@ -7032,6 +7052,9 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
goto erret;
}
ufunc->uf_def_arg_idx[count] = instr->ga_len;
+
+ if (did_set_arg_type)
+ set_function_type(ufunc);
}
/*