changeset 21469:4d156aead799 v8.2.1285

patch 8.2.1285: Vim9: argument types are not checked on assignment Commit: https://github.com/vim/vim/commit/b8070e31736decfcdf8dd47997882cb8f5a64c9d Author: Bram Moolenaar <Bram@vim.org> Date: Thu Jul 23 20:56:04 2020 +0200 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 https://github.com/vim/vim/issues/6507)
author Bram Moolenaar <Bram@vim.org>
date Thu, 23 Jul 2020 21:00:04 +0200
parents df10f1df515d
children f0304ef8ac7d
files src/testdir/test_vim9_func.vim src/version.c src/vim9compile.c
diffstat 3 files changed, 34 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- 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')
--- 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,
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -638,6 +638,18 @@ check_type(type_T *expected, type_T *act
 		    && (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 *n
     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
 	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
 	    // 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
 		goto erret;
 	}
 	ufunc->uf_def_arg_idx[count] = instr->ga_len;
+
+	if (did_set_arg_type)
+	    set_function_type(ufunc);
     }
 
     /*