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.
diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim
index fb2180f..558f23c 100644
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -130,6 +130,19 @@
   assert_equal('one,two,three', MyDefVarargs('one', 'two', 'three'))
 enddef
 
+" Only varargs
+def MyVarargsOnly(...args: list<string>): string
+  return join(args, ',')
+enddef
+
+def Test_call_varargs_only()
+  assert_equal('', MyVarargsOnly())
+  assert_equal('one', MyVarargsOnly('one'))
+  assert_equal('one,two', MyVarargsOnly('one', 'two'))
+  call CheckDefFailure(['MyVarargsOnly(1)'], 'E1013: argument 1: type mismatch, expected string but got number')
+  call CheckDefFailure(['MyVarargsOnly("one", 2)'], 'E1013: argument 2: type mismatch, expected string but got number')
+enddef
+
 def Test_using_var_as_arg()
   call writefile(['def Func(x: number)',  'let x = 234', 'enddef'], 'Xdef')
   call assert_fails('so Xdef', 'E1006:')
diff --git a/src/userfunc.c b/src/userfunc.c
index f93c149..69a57c2 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -3020,7 +3020,7 @@
 
     if (eap->cmdidx == CMD_def)
     {
-	int lnum_save = SOURCING_LNUM;
+	int	lnum_save = SOURCING_LNUM;
 
 	// error messages are for the first function line
 	SOURCING_LNUM = sourcing_lnum_top;
@@ -3034,7 +3034,8 @@
 	    // and uf_va_type.
 	    int len = argtypes.ga_len - (varargs ? 1 : 0);
 
-	    fp->uf_arg_types = ALLOC_CLEAR_MULT(type_T *, len);
+	    if (len > 0)
+		fp->uf_arg_types = ALLOC_CLEAR_MULT(type_T *, len);
 	    if (fp->uf_arg_types != NULL)
 	    {
 		int	i;
diff --git a/src/version.c b/src/version.c
index f08ca11..3518aec 100644
--- a/src/version.c
+++ b/src/version.c
@@ -739,6 +739,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    528,
+/**/
     527,
 /**/
     526,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 18fbdd3..fb0adb3 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -130,6 +130,8 @@
 static int compile_expr2(char_u **arg,  cctx_T *cctx);
 static int compile_expr3(char_u **arg,  cctx_T *cctx);
 static void delete_def_function_contents(dfunc_T *dfunc);
+static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
+static int check_type(type_T *expected, type_T *actual, int give_msg);
 
 /*
  * Lookup variable "name" in the local scope and return the index.
@@ -1240,6 +1242,32 @@
 	return FAIL;
     }
 
+    if (ufunc->uf_dfunc_idx >= 0)
+    {
+	int		i;
+
+	for (i = 0; i < argcount; ++i)
+	{
+	    type_T *expected;
+	    type_T *actual;
+
+	    if (i < regular_args)
+	    {
+		if (ufunc->uf_arg_types == NULL)
+		    continue;
+		expected = ufunc->uf_arg_types[i];
+	    }
+	    else
+		expected = ufunc->uf_va_type->tt_member;
+	    actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
+	    if (check_type(expected, actual, FALSE) == FAIL)
+	    {
+		arg_type_mismatch(expected, actual, i + 1);
+		return FAIL;
+	    }
+	}
+    }
+
     // Turn varargs into a list.
     if (ufunc->uf_va_name != NULL)
     {
@@ -2403,6 +2431,18 @@
     vim_free(tofree2);
 }
 
+    static void
+arg_type_mismatch(type_T *expected, type_T *actual, int argidx)
+{
+    char *tofree1, *tofree2;
+
+    semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"),
+	    argidx,
+	    type_name(expected, &tofree1), type_name(actual, &tofree2));
+    vim_free(tofree1);
+    vim_free(tofree2);
+}
+
 /*
  * Check if the expected and actual types match.
  */