changeset 19993:efe864a7ce4f v8.2.0552

patch 8.2.0552: Vim9: some errors not covered by tests Commit: https://github.com/vim/vim/commit/99aaf0ce7cc23b0e759eab2369e266cdc8d46af8 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Apr 12 14:39:53 2020 +0200 patch 8.2.0552: Vim9: some errors not covered by tests Problem: Vim9: some errors not covered by tests. Solution: Add more tests. Check Funcref argument types.
author Bram Moolenaar <Bram@vim.org>
date Sun, 12 Apr 2020 14:45:04 +0200
parents 6dad0fd5b8e6
children 4fccb4ea3f42
files src/testdir/test_vim9_func.vim src/version.c src/vim9compile.c
diffstat 3 files changed, 60 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -96,6 +96,7 @@ def Test_call_default_args()
   assert_fails('call MyDefaultArgs("one", "two")', 'E118:')
 
   call CheckScriptFailure(['def Func(arg: number = asdf)', 'enddef'], 'E1001:')
+  call CheckScriptFailure(['def Func(arg: number = "text")', 'enddef'], 'E1013: argument 1: type mismatch, expected number but got string')
 enddef
 
 func Test_call_default_args_from_func()
@@ -196,6 +197,26 @@ def Test_call_func_defined_later()
   call assert_fails('call NotDefined("one")', 'E117:')
 enddef
 
+def CombineFuncrefTypes()
+  " same arguments, different return type
+  let Ref1: func(bool): string
+  let Ref2: func(bool): number
+  let Ref3: func(bool): any
+  Ref3 = g:cond ? Ref1 : Ref2
+
+  " different number of arguments
+  let Refa1: func(bool): number
+  let Refa2: func(bool, number): number
+  let Refa3: func: number
+  Refa3 = g:cond ? Refa1 : Refa2
+
+  " different argument types
+  let Refb1: func(bool, string): number
+  let Refb2: func(string, number): number
+  let Refb3: func(any, any): number
+  Refb3 = g:cond ? Refb1 : Refb2
+enddef
+
 func DefinedLater(arg)
   return a:arg
 endfunc
--- a/src/version.c
+++ b/src/version.c
@@ -739,6 +739,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    552,
+/**/
     551,
 /**/
     550,
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -1746,6 +1746,8 @@ parse_type(char_u **arg, garray_T *type_
     static int
 equal_type(type_T *type1, type_T *type2)
 {
+    int i;
+
     if (type1->tt_type != type2->tt_type)
 	return FALSE;
     switch (type1->tt_type)
@@ -1767,9 +1769,16 @@ equal_type(type_T *type1, type_T *type2)
 	    return equal_type(type1->tt_member, type2->tt_member);
 	case VAR_FUNC:
 	case VAR_PARTIAL:
-	    // TODO; check argument types.
-	    return equal_type(type1->tt_member, type2->tt_member)
-		&& type1->tt_argcount == type2->tt_argcount;
+	    if (!equal_type(type1->tt_member, type2->tt_member)
+		    || type1->tt_argcount != type2->tt_argcount)
+		return FALSE;
+	    if (type1->tt_argcount < 0
+			   || type1->tt_args == NULL || type2->tt_args == NULL)
+		return TRUE;
+	    for (i = 0; i < type1->tt_argcount; ++i)
+		if (!equal_type(type1->tt_args[i], type2->tt_args[i]))
+		    return FALSE;
+	    return TRUE;
     }
     return TRUE;
 }
@@ -1800,8 +1809,31 @@ common_type(type_T *type1, type_T *type2
 		*dest = get_dict_type(common, type_gap);
 	    return;
 	}
-	// TODO: VAR_FUNC and VAR_PARTIAL
-	*dest = type1;
+	if (type1->tt_type == VAR_FUNC)
+	{
+	    type_T *common;
+
+	    common_type(type1->tt_member, type2->tt_member, &common, type_gap);
+	    if (type1->tt_argcount == type2->tt_argcount
+						    && type1->tt_argcount >= 0)
+	    {
+		int argcount = type1->tt_argcount;
+		int i;
+
+		*dest = alloc_func_type(common, argcount, type_gap);
+		if (type1->tt_args != NULL && type2->tt_args != NULL)
+		{
+		    (*dest)->tt_args = ALLOC_CLEAR_MULT(type_T *, argcount);
+		    if ((*dest)->tt_args != NULL)
+			for (i = 0; i < argcount; ++i)
+			    common_type(type1->tt_args[i], type2->tt_args[i],
+					       &(*dest)->tt_args[i], type_gap);
+		}
+	    }
+	    else
+		*dest = alloc_func_type(common, -1, type_gap);
+	    return;
+	}
     }
 
     *dest = &t_any;