]> granicus.if.org Git - vim/commitdiff
patch 8.2.3945: Vim9: partial variable argument types are wrong v8.2.3945
authorBram Moolenaar <Bram@vim.org>
Thu, 30 Dec 2021 13:29:00 +0000 (13:29 +0000)
committerBram Moolenaar <Bram@vim.org>
Thu, 30 Dec 2021 13:29:00 +0000 (13:29 +0000)
Problem:    Vim9: partial variable argument types are wrong, leading to a
            crash.
Solution:   When adjusting the argument count also adjust the argument types.
            (closes #9433)

src/testdir/test_vim9_assign.vim
src/userfunc.c
src/version.c
src/vim9type.c

index 9a26d55fd7bbbd937427dd4755de32afbe285795..f02da7fe4a610ce9e5c26c759f05a26fdced7a19 100644 (file)
@@ -847,6 +847,36 @@ def Test_assignment_partial()
       Ref()
   END
   CheckScriptSuccess(lines)
+
+  lines =<< trim END
+      vim9script
+
+      var nres: any
+      var sres: any
+      def Func(n: number, s = '')
+        nres = n
+        sres = s
+      enddef
+
+      var n: number
+      var Ref = function(Func, [n])
+      Ref('x')
+      assert_equal(0, nres)
+      assert_equal('x', sres)
+  END
+  CheckScriptSuccess(lines)
+
+  lines =<< trim END
+      vim9script
+
+      def Func(n: number, s = '')
+      enddef
+
+      var n: number
+      var Ref = function(Func, [n])
+      Ref(0)
+  END
+  CheckScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected string but got number')
 enddef
 
 def Test_assignment_list_any_index()
index d4d28c52975372b7bfdc9fb4c3905ca35fbfef26..85a1cd315c045d7b37ac89a297a4d154865b2bf5 100644 (file)
@@ -3326,6 +3326,7 @@ call_func(
     int                argv_base = 0;
     partial_T  *partial = funcexe->fe_partial;
     type_T     check_type;
+    type_T     *check_type_args[MAX_FUNC_ARGS];
 
     // Initialize rettv so that it is safe for caller to invoke clear_tv(rettv)
     // even when call_func() returns FAIL.
@@ -3377,6 +3378,11 @@ call_func(
                // make a copy of the type with the correction.
                check_type = *funcexe->fe_check_type;
                funcexe->fe_check_type = &check_type;
+               check_type.tt_args = check_type_args;
+               CLEAR_FIELD(check_type_args);
+               for (i = 0; i < check_type.tt_argcount; ++i)
+                   check_type_args[i + partial->pt_argc] =
+                                                        check_type.tt_args[i];
                check_type.tt_argcount += partial->pt_argc;
                check_type.tt_min_argcount += partial->pt_argc;
            }
index f5f3c30343dd5a56b58e96a8cff0666a93cd7784..a04c91cbd4fa8fd0bbbe0fb832c5e1acbb9ef3ce 100644 (file)
@@ -749,6 +749,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    3945,
 /**/
     3944,
 /**/
index 4542e1e081ccffdbb60fa29e89891e4757b29a9f..a9fb5b0e7875c407b2cadc4ea519cacc662ef1dd 100644 (file)
@@ -371,6 +371,18 @@ typval2type_int(typval_T *tv, int copyID, garray_T *type_gap, int do_member)
                    *type = *ufunc->uf_func_type;
                    type->tt_argcount -= tv->vval.v_partial->pt_argc;
                    type->tt_min_argcount -= tv->vval.v_partial->pt_argc;
+                   if (type->tt_argcount == 0)
+                       type->tt_args = NULL;
+                   else
+                   {
+                       int i;
+
+                       func_type_add_arg_types(type, type->tt_argcount,
+                                                                    type_gap);
+                       for (i = 0; i < type->tt_argcount; ++i)
+                           type->tt_args[i] = ufunc->uf_func_type->tt_args[
+                                             i + tv->vval.v_partial->pt_argc];
+                   }
                    return type;
                }
                return ufunc->uf_func_type;
@@ -464,6 +476,9 @@ check_typval_type(type_T *expected, typval_T *actual_tv, where_T where)
     type_T     *actual_type;
     int                res = FAIL;
 
+    if (expected == NULL)
+       return OK;  // didn't expect anything.
+
     // For some values there is no type, assume an error will be given later
     // for an invalid value.
     if ((actual_tv->v_type == VAR_FUNC && actual_tv->vval.v_string == NULL)