From b8070e31736decfcdf8dd47997882cb8f5a64c9d Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 23 Jul 2020 20:56:04 +0200 Subject: patch 8.2.1285: Vim9: argument types are not checked on assignment Problem: Vim9: argument types are not checked on assignment. Solution: Check function argument types. (issue #6507) --- src/testdir/test_vim9_func.vim | 9 +++++++++ src/version.c | 2 ++ src/vim9compile.c | 23 +++++++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index c8c6afee0..b0bbab3fd 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 91edd4ad8..5563bd1fa 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1285, /**/ 1284, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index e032e23a9..52841de6b 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); } /* -- cgit v1.2.1