]> granicus.if.org Git - vim/commitdiff
patch 8.2.1285: Vim9: argument types are not checked on assignment v8.2.1285
authorBram Moolenaar <Bram@vim.org>
Thu, 23 Jul 2020 18:56:04 +0000 (20:56 +0200)
committerBram Moolenaar <Bram@vim.org>
Thu, 23 Jul 2020 18:56:04 +0000 (20:56 +0200)
Problem:    Vim9: argument types are not checked on assignment.
Solution:   Check function argument types. (issue #6507)

src/testdir/test_vim9_func.vim
src/version.c
src/vim9compile.c

index c8c6afee09df2e1a083af3dea9b55a3054cf04ef..b0bbab3fdf6a007c2c51892a29650bfef467155c 100644 (file)
@@ -293,6 +293,15 @@ def Test_call_funcref()
     Funcref(123)
   END
   CheckScriptSuccess(lines)
+
+  lines =<< trim END
+    vim9script
+    def UseNumber(nr: number)
+      echo nr
+    enddef
+    let Funcref: func(string) = function('UseNumber')
+  END
+  CheckScriptFailure(lines, 'E1013: type mismatch, expected func(string) but got func(number)')
 enddef
 
 let SomeFunc = function('len')
index 91edd4ad85f219080b8c9f576fdf8b88de2c4f55..5563bd1fa647138e406da7e1d4282395b005f0c8 100644 (file)
@@ -754,6 +754,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1285,
 /**/
     1284,
 /**/
index e032e23a92e0cdb1e63b624ce7981e3195fbf28a..52841de6bddc0ace2b1615b2cf5bbb49c7eecfd3 100644 (file)
@@ -638,6 +638,18 @@ check_type(type_T *expected, type_T *actual, int give_msg)
                    && (actual->tt_argcount < expected->tt_min_argcount
                        || actual->tt_argcount > expected->tt_argcount))
                    ret = FAIL;
+           if (expected->tt_args != NULL && actual->tt_args != NULL)
+           {
+               int i;
+
+               for (i = 0; i < expected->tt_argcount; ++i)
+                   if (check_type(expected->tt_args[i], actual->tt_args[i],
+                                                               FALSE) == FAIL)
+                   {
+                       ret = FAIL;
+                       break;
+                   }
+           }
        }
        if (ret == FAIL && give_msg)
            type_mismatch(expected, actual);
@@ -2819,6 +2831,10 @@ generate_funcref(cctx_T *cctx, char_u *name)
     if (ufunc == NULL)
        return FAIL;
 
+    // Need to compile any default values to get the argument types.
+    if (ufunc->uf_def_status == UF_TO_BE_COMPILED)
+       if (compile_def_function(ufunc, TRUE, NULL) == FAIL)
+           return FAIL;
     return generate_PUSHFUNC(cctx, vim_strsave(ufunc->uf_name),
                                                          ufunc->uf_func_type);
 }
@@ -6995,6 +7011,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
        int     i;
        char_u  *arg;
        int     off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
+       int     did_set_arg_type = FALSE;
 
        // Produce instructions for the default values of optional arguments.
        // Store the instruction index in uf_def_arg_idx[] so that we know
@@ -7019,7 +7036,10 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
            // specified type.
            val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
            if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
+           {
+               did_set_arg_type = TRUE;
                ufunc->uf_arg_types[arg_idx] = val_type;
+           }
            else if (check_type(ufunc->uf_arg_types[arg_idx], val_type, FALSE)
                                                                       == FAIL)
            {
@@ -7032,6 +7052,9 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
                goto erret;
        }
        ufunc->uf_def_arg_idx[count] = instr->ga_len;
+
+       if (did_set_arg_type)
+           set_function_type(ufunc);
     }
 
     /*