changeset 23691:0d56d4f107d8 v8.2.2387

patch 8.2.2387: runtime type check does not mention argument index Commit: https://github.com/vim/vim/commit/e32e516dfa46e9c5965d278f96aaf57573de8ac4 Author: Bram Moolenaar <Bram@vim.org> Date: Thu Jan 21 20:21:29 2021 +0100 patch 8.2.2387: runtime type check does not mention argument index Problem: Runtime type check does not mention argument index. Solution: Add ct_arg_idx. (closes https://github.com/vim/vim/issues/7720)
author Bram Moolenaar <Bram@vim.org>
date Thu, 21 Jan 2021 20:30:04 +0100
parents 90a28e0d556f
children 3a9a361e6219
files src/testdir/test_vim9_builtin.vim src/testdir/test_vim9_disassemble.vim src/testdir/test_vim9_func.vim src/version.c src/vim9.h src/vim9compile.c src/vim9execute.c
diffstat 7 files changed, 41 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/testdir/test_vim9_builtin.vim
+++ b/src/testdir/test_vim9_builtin.vim
@@ -263,7 +263,7 @@ def Test_extend_arg_types()
   CheckDefFailure(['extend({a: 1}, {b: 2}, 1)'], 'E1013: Argument 3: type mismatch, expected string but got number')
 
   CheckDefFailure(['extend([1], ["b"])'], 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>')
-  CheckDefExecFailure(['extend([1], ["b", 1])'], 'E1012: Type mismatch; expected list<number> but got list<any>')
+  CheckDefExecFailure(['extend([1], ["b", 1])'], 'E1013: Argument 2: type mismatch, expected list<number> but got list<any>')
 enddef
 
 def Test_extendnew()
--- a/src/testdir/test_vim9_disassemble.vim
+++ b/src/testdir/test_vim9_disassemble.vim
@@ -934,7 +934,7 @@ def Test_disassemble_lambda_with_type()
         'return Ref(g:value)\_s*' ..
         '\d LOADG g:value\_s*' ..
         '\d LOAD $0\_s*' ..
-        '\d CHECKTYPE number stack\[-2\]\_s*' ..
+        '\d CHECKTYPE number stack\[-2\] arg 1\_s*' ..
         '\d PCALL (argc 1)\_s*' ..
         '\d RETURN',
         instr)
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -144,6 +144,22 @@ def Test_return_something()
   assert_fails('ReturnGlobal()', 'E1012: Type mismatch; expected number but got string', '', 1, 'ReturnGlobal')
 enddef
 
+def Test_check_argument_type()
+  var lines =<< trim END
+      vim9script
+      def Val(a: number, b: number): number
+        return 0
+      enddef
+      def Func()
+        var x: any = true
+        Val(0, x)
+      enddef
+      disass Func
+      Func()
+  END
+  CheckScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected number but got bool', 2)
+enddef
+
 def Test_missing_return()
   CheckDefFailure(['def Missing(): number',
                    '  if g:cond',
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2387,
+/**/
     2386,
 /**/
     2385,
--- a/src/vim9.h
+++ b/src/vim9.h
@@ -224,7 +224,8 @@ typedef struct {
 // arguments to ISN_CHECKTYPE
 typedef struct {
     type_T	*ct_type;
-    int		ct_off;	    // offset in stack, -1 is bottom
+    char	ct_off;		// offset in stack, -1 is bottom
+    char	ct_arg_idx;	// argument index or zero
 } checktype_T;
 
 // arguments to ISN_STORENR
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -816,7 +816,8 @@ generate_COND2BOOL(cctx_T *cctx)
 generate_TYPECHECK(
 	cctx_T	    *cctx,
 	type_T	    *expected,
-	int	    offset)
+	int	    offset,
+	int	    argidx)
 {
     isn_T	*isn;
     garray_T	*stack = &cctx->ctx_type_stack;
@@ -826,6 +827,7 @@ generate_TYPECHECK(
 	return FAIL;
     isn->isn_arg.type.ct_type = alloc_type(expected);
     isn->isn_arg.type.ct_off = offset;
+    isn->isn_arg.type.ct_arg_idx = argidx;
 
     // type becomes expected
     ((type_T **)stack->ga_data)[stack->ga_len + offset] = expected;
@@ -904,7 +906,7 @@ need_type(
     // If it's a constant a runtime check makes no sense.
     if (!actual_is_const && use_typecheck(actual, expected))
     {
-	generate_TYPECHECK(cctx, expected, offset);
+	generate_TYPECHECK(cctx, expected, offset, arg_idx);
 	return OK;
     }
 
@@ -1637,7 +1639,7 @@ generate_BCALL(cctx_T *cctx, int func_id
     if (maptype != NULL && maptype->tt_member != NULL
 					       && maptype->tt_member != &t_any)
 	// Check that map() didn't change the item types.
-	generate_TYPECHECK(cctx, maptype, -1);
+	generate_TYPECHECK(cctx, maptype, -1, 1);
 
     return OK;
 }
@@ -1735,7 +1737,7 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufu
 	    else
 		expected = ufunc->uf_va_type->tt_member;
 	    actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
-	    if (need_type(actual, expected, -argcount + i, 0, cctx,
+	    if (need_type(actual, expected, -argcount + i, i + 1, cctx,
 							  TRUE, FALSE) == FAIL)
 	    {
 		arg_type_mismatch(expected, actual, i + 1);
@@ -1852,7 +1854,7 @@ generate_PCALL(
 					     type->tt_argcount - 1]->tt_member;
 		    else
 			expected = type->tt_args[i];
-		    if (need_type(actual, expected, offset, 0,
+		    if (need_type(actual, expected, offset, i + 1,
 						    cctx, TRUE, FALSE) == FAIL)
 		    {
 			arg_type_mismatch(expected, actual, i + 1);
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -3242,7 +3242,8 @@ call_def_function(
 
 		    tv = STACK_TV_BOT(ct->ct_off);
 		    SOURCING_LNUM = iptr->isn_lnum;
-		    if (check_typval_type(ct->ct_type, tv, 0) == FAIL)
+		    if (check_typval_type(ct->ct_type, tv, ct->ct_arg_idx)
+								       == FAIL)
 			goto on_error;
 
 		    // number 0 is FALSE, number 1 is TRUE
@@ -4235,11 +4236,18 @@ ex_disassemble(exarg_T *eap)
 	    case ISN_CHECKNR: smsg("%4d CHECKNR", current); break;
 	    case ISN_CHECKTYPE:
 		  {
+		      checktype_T *ct = &iptr->isn_arg.type;
 		      char *tofree;
 
-		      smsg("%4d CHECKTYPE %s stack[%d]", current,
-			      type_name(iptr->isn_arg.type.ct_type, &tofree),
-			      iptr->isn_arg.type.ct_off);
+		      if (ct->ct_arg_idx == 0)
+			  smsg("%4d CHECKTYPE %s stack[%d]", current,
+					  type_name(ct->ct_type, &tofree),
+					  (int)ct->ct_off);
+		      else
+			  smsg("%4d CHECKTYPE %s stack[%d] arg %d", current,
+					  type_name(ct->ct_type, &tofree),
+					  (int)ct->ct_off,
+					  (int)ct->ct_arg_idx);
 		      vim_free(tofree);
 		      break;
 		  }