patch 9.0.2057: Vim9: no strict type checks for funcrefs varargs

Problem:  Vim9: no strict type checks for funcrefs varargs
Solution: Perform strict type checking when declaring funcrefs
          with vararg declaration, add tests

closes: #13397

Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Ernie Rael <errael@raelity.com>
diff --git a/runtime/doc/tags b/runtime/doc/tags
index 77b7d1b..fde5bda 100644
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -11010,6 +11010,7 @@
 vim9-export	vim9.txt	/*vim9-export*
 vim9-false-true	vim9.txt	/*vim9-false-true*
 vim9-final	vim9.txt	/*vim9-final*
+vim9-func-declaration	vim9.txt	/*vim9-func-declaration*
 vim9-function-defined-later	vim9.txt	/*vim9-function-defined-later*
 vim9-gotchas	vim9.txt	/*vim9-gotchas*
 vim9-ignored-argument	vim9.txt	/*vim9-ignored-argument*
diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt
index 6cabb87..58d9ed6 100644
--- a/runtime/doc/vim9.txt
+++ b/runtime/doc/vim9.txt
@@ -1468,7 +1468,7 @@
 There is no array type, use list<{type}> instead.  For a list constant an
 efficient implementation is used that avoids allocating a lot of small pieces
 of memory.
-							*E1005* *E1007*
+				    *vim9-func-declaration* *E1005* *E1007*
 A partial and function can be declared in more or less specific ways:
 func				any kind of function reference, no type
 				checking for arguments or return value
@@ -1669,6 +1669,26 @@
 |flattennew()| instead.  Since |flatten()| is intended to always change the
 type, it can not be used in Vim9 script.
 
+Assigning to a funcref with specified arguments (see |vim9-func-declaration|)
+does strict type checking of the arguments. For variable number of arguments
+the type must match: >
+	var FuncRef: func(string, number, bool): number
+	FuncRef = (v1: string, v2: number, v3: bool) => 777	# OK
+	FuncRef = (v1: string, v2: number, v3: number) => 777	# Error!
+	# variable number of arguments must have same type
+	var FuncVA: func(...list<string>): number
+	FuncVA = (...v: list<number>): number => v  # Error!
+	FuncVA = (...v: list<any>): number => v	    # OK, `any` runtime check
+	FuncVA = (v1: string, v: string2): number => 333     # Error!
+	FuncVA = (v: list<string>): number => 3	    # Error!
+
+If the destinataion funcref has no specified arguments, then there is no
+argument type checking: >
+	var FuncUnknownArgs: func: number
+	FuncUnknownArgs = (v): number => v			# OK
+	FuncUnknownArgs = (v1: string, v2: string): number => 3	# OK
+<	FuncUnknownArgs = (...v1: list<string>): number => 333	# OK
+
 			 *E1211* *E1217* *E1218* *E1219* *E1220* *E1221*
 			 *E1222* *E1223* *E1224* *E1225* *E1226* *E1227*
 			 *E1228* *E1238* *E1250* *E1251* *E1252* *E1256*
diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim
index bff9c9f..6d2858f 100644
--- a/src/testdir/test_vim9_assign.vim
+++ b/src/testdir/test_vim9_assign.vim
@@ -1890,7 +1890,7 @@
     var FuncAnyVA: func(...any): number
     FuncAnyVA = (v): number => v
   END
-  v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected func(...any): number but got func(any): number')
+  v9.CheckScriptFailure(lines, 'E1180: Variable arguments type must be a list: any')
 
   # varargs must match
   lines =<< trim END
@@ -1898,7 +1898,7 @@
     var FuncAnyVA: func(...any): number
     FuncAnyVA = (v1, v2): number => v1 + v2
   END
-  v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected func(...any): number but got func(any, any): number')
+  v9.CheckScriptFailure(lines, 'E1180: Variable arguments type must be a list: any')
 
   # varargs must match
   lines =<< trim END
@@ -1906,7 +1906,7 @@
     var FuncAnyVA: func(...any): number
     FuncAnyVA = (v1: list<any>): number => 3
   END
-  v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected func(...any): number but got func(list<any>): number')
+  v9.CheckScriptFailure(lines, 'E1180: Variable arguments type must be a list: any')
 enddef
 
 def Test_assign_funcref_arg_any()
diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim
index 701a2f0..cbbd572 100644
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
Binary files differ
diff --git a/src/version.c b/src/version.c
index 7584e45..fbf2999 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2057,
+/**/
     2056,
 /**/
     2055,
diff --git a/src/vim9type.c b/src/vim9type.c
index 6a58487..c31e51b 100644
--- a/src/vim9type.c
+++ b/src/vim9type.c
@@ -1231,6 +1231,15 @@
 			type = parse_type(&p, type_gap, give_error);
 			if (type == NULL)
 			    return NULL;
+			if ((flags & TTFLAG_VARARGS) != 0
+				&& type->tt_type != VAR_LIST)
+			{
+			    char *tofree;
+			    semsg(_(e_variable_arguments_type_must_be_list_str),
+				  type_name(type, &tofree));
+			    vim_free(tofree);
+			    return NULL;
+			}
 			arg_type[argcount++] = type;
 
 			// Nothing comes after "...{type}".