changeset 20532:cb4831fa7e25 v8.2.0820

patch 8.2.0820: Vim9: function type isn't set until compiled Commit: https://github.com/vim/vim/commit/6ff71d8b7fbdf667a2f119a2487302e240961816 Author: Bram Moolenaar <Bram@vim.org> Date: Sun May 24 23:45:24 2020 +0200 patch 8.2.0820: Vim9: function type isn't set until compiled Problem: Vim9: function type isn't set until compiled. Solution: Set function type early.
author Bram Moolenaar <Bram@vim.org>
date Mon, 25 May 2020 00:00:04 +0200
parents 6eb8347bcf1a
children 5ab9d71dc5f7
files src/proto/vim9compile.pro src/testdir/test_vim9_func.vim src/userfunc.c src/version.c src/vim9compile.c
diffstat 5 files changed, 58 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- a/src/proto/vim9compile.pro
+++ b/src/proto/vim9compile.pro
@@ -10,6 +10,7 @@ char_u *to_name_const_end(char_u *arg);
 int assignment_len(char_u *p, int *heredoc);
 int check_vim9_unlet(char_u *name);
 int compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx);
+void set_function_type(ufunc_T *ufunc);
 void delete_instr(isn_T *isn);
 void delete_def_function(ufunc_T *ufunc);
 void free_def_functions(void);
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -560,8 +560,7 @@ def Test_func_type_part()
   RefVoid = FuncNoArgNoRet
   RefVoid = FuncOneArgNoRet
   CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number')
-"  TODO: these should fail
-"  CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1013: type mismatch, expected func() but got func(): string')
+  CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1013: type mismatch, expected func() but got func(): string')
 
   let RefAny: func(): any
   RefAny = FuncNoArgRetNumber
@@ -573,8 +572,7 @@ def Test_func_type_part()
   RefNr = FuncNoArgRetNumber
   RefNr = FuncOneArgRetNumber
   CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): number but got func()')
-"  TODO: should fail
-"  CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1013: type mismatch, expected func(): number but got func(): string')
+  CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1013: type mismatch, expected func(): number but got func(): string')
 
   let RefStr: func: string
   RefStr = FuncNoArgRetString
@@ -589,10 +587,9 @@ def Test_func_type_fails()
   CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number')
   CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1013: type mismatch, expected func() but got func(number)')
   CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1013: type mismatch, expected func() but got func(number): number')
-"  TODO: these don't fail
-"  CheckDefFailure(['let Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(bool) but got func(bool, number)')
-"  CheckDefFailure(['let Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(?bool) but got func(bool, number)')
-"  CheckDefFailure(['let Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(...bool) but got func(bool, number)')
+  CheckDefFailure(['let Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(bool) but got func(bool, number)')
+  CheckDefFailure(['let Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(?bool) but got func(bool, number)')
+  CheckDefFailure(['let Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(...bool) but got func(bool, number)')
 
   call CheckDefFailure(['let RefWrong: func(string ,number)'], 'E1068:')
   call CheckDefFailure(['let RefWrong: func(string,number)'], 'E1069:')
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -3284,6 +3284,9 @@ def_function(exarg_T *eap, char_u *name_
 	is_export = FALSE;
     }
 
+    if (eap->cmdidx == CMD_def)
+	set_function_type(fp);
+
     goto ret_free;
 
 erret:
--- a/src/version.c
+++ b/src/version.c
@@ -747,6 +747,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    820,
+/**/
     819,
 /**/
     818,
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -6763,54 +6763,6 @@ compile_def_function(ufunc_T *ufunc, int
 	    ufunc->uf_flags |= FC_CLOSURE;
     }
 
-    {
-	int varargs = ufunc->uf_va_name != NULL;
-	int argcount = ufunc->uf_args.ga_len;
-
-	// Create a type for the function, with the return type and any
-	// argument types.
-	// A vararg is included in uf_args.ga_len but not in uf_arg_types.
-	// The type is included in "tt_args".
-	if (argcount > 0 || varargs)
-	{
-	    ufunc->uf_func_type = alloc_func_type(ufunc->uf_ret_type,
-					       argcount, &ufunc->uf_type_list);
-	    // Add argument types to the function type.
-	    if (func_type_add_arg_types(ufunc->uf_func_type,
-					argcount + varargs,
-					&ufunc->uf_type_list) == FAIL)
-	    {
-		ret = FAIL;
-		goto erret;
-	    }
-	    ufunc->uf_func_type->tt_argcount = argcount + varargs;
-	    ufunc->uf_func_type->tt_min_argcount =
-					  argcount - ufunc->uf_def_args.ga_len;
-	    if (ufunc->uf_arg_types == NULL)
-	    {
-		int i;
-
-		// lambda does not have argument types.
-		for (i = 0; i < argcount; ++i)
-		    ufunc->uf_func_type->tt_args[i] = &t_any;
-	    }
-	    else
-		mch_memmove(ufunc->uf_func_type->tt_args,
-			     ufunc->uf_arg_types, sizeof(type_T *) * argcount);
-	    if (varargs)
-	    {
-		ufunc->uf_func_type->tt_args[argcount] =
-			ufunc->uf_va_type == NULL ? &t_any : ufunc->uf_va_type;
-		ufunc->uf_func_type->tt_flags = TTFLAG_VARARGS;
-	    }
-	}
-	else
-	    // No arguments, can use a predefined type.
-	    ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
-					       argcount, &ufunc->uf_type_list);
-
-    }
-
     ret = OK;
 
 erret:
@@ -6847,6 +6799,53 @@ erret:
     return ret;
 }
 
+    void
+set_function_type(ufunc_T *ufunc)
+{
+    int varargs = ufunc->uf_va_name != NULL;
+    int argcount = ufunc->uf_args.ga_len;
+
+    // Create a type for the function, with the return type and any
+    // argument types.
+    // A vararg is included in uf_args.ga_len but not in uf_arg_types.
+    // The type is included in "tt_args".
+    if (argcount > 0 || varargs)
+    {
+	ufunc->uf_func_type = alloc_func_type(ufunc->uf_ret_type,
+					   argcount, &ufunc->uf_type_list);
+	// Add argument types to the function type.
+	if (func_type_add_arg_types(ufunc->uf_func_type,
+				    argcount + varargs,
+				    &ufunc->uf_type_list) == FAIL)
+	    return;
+	ufunc->uf_func_type->tt_argcount = argcount + varargs;
+	ufunc->uf_func_type->tt_min_argcount =
+				      argcount - ufunc->uf_def_args.ga_len;
+	if (ufunc->uf_arg_types == NULL)
+	{
+	    int i;
+
+	    // lambda does not have argument types.
+	    for (i = 0; i < argcount; ++i)
+		ufunc->uf_func_type->tt_args[i] = &t_any;
+	}
+	else
+	    mch_memmove(ufunc->uf_func_type->tt_args,
+			 ufunc->uf_arg_types, sizeof(type_T *) * argcount);
+	if (varargs)
+	{
+	    ufunc->uf_func_type->tt_args[argcount] =
+		    ufunc->uf_va_type == NULL ? &t_any : ufunc->uf_va_type;
+	    ufunc->uf_func_type->tt_flags = TTFLAG_VARARGS;
+	}
+    }
+    else
+	// No arguments, can use a predefined type.
+	ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
+					   argcount, &ufunc->uf_type_list);
+}
+
+
 /*
  * Delete an instruction, free what it contains.
  */