]> granicus.if.org Git - vim/commitdiff
patch 8.2.0529: Vim9: function argument with default not checked v8.2.0529
authorBram Moolenaar <Bram@vim.org>
Tue, 7 Apr 2020 20:45:00 +0000 (22:45 +0200)
committerBram Moolenaar <Bram@vim.org>
Tue, 7 Apr 2020 20:45:00 +0000 (22:45 +0200)
Problem:    Vim9: function argument with default not checked.
Solution:   Check type of argument with default value.

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

index 558f23cb4718a1c6456c3e41c7d504e6f76d1f69..6f9aa0cca4846eeb19a3fc0fdd8c75709d9ec88f 100644 (file)
@@ -128,6 +128,7 @@ def Test_call_def_varargs()
   assert_equal('one,foo', MyDefVarargs('one'))
   assert_equal('one,two', MyDefVarargs('one', 'two'))
   assert_equal('one,two,three', MyDefVarargs('one', 'two', 'three'))
+  call CheckDefFailure(['MyDefVarargs("one", 22)'], 'E1013: argument 2: type mismatch, expected string but got number')
 enddef
 
 " Only varargs
index 69a57c28d1f0d84a57dafe96a1636cb4fd918eb5..316eac6aa0837252dd96651eae4ef65715a17a2c 100644 (file)
@@ -3045,8 +3045,8 @@ ex_function(exarg_T *eap)
                {
                    p = ((char_u **)argtypes.ga_data)[i];
                    if (p == NULL)
-                       // todo: get type from default value
-                       type = &t_any;
+                       // will get the type from the default value
+                       type = &t_unknown;
                    else
                        type = parse_type(&p, &fp->uf_type_list);
                    if (type == NULL)
index 3518aecab84db5603f9a4e3498c86a7f162eac98..a3c54cb85c7d9ca6a5edaaea94b72dc40ccb434b 100644 (file)
@@ -738,6 +738,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    529,
 /**/
     528,
 /**/
index fb0adb3b42a1ee26868de38ceb7b5e134a544f7f..a8a7647468bd2e70d3181fa4d28a7eac8c25b55c 100644 (file)
@@ -5548,6 +5548,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type)
     if (ufunc->uf_def_args.ga_len > 0)
     {
        int     count = ufunc->uf_def_args.ga_len;
+       int     first_def_arg = ufunc->uf_args.ga_len - count;
        int     i;
        char_u  *arg;
        int     off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
@@ -5561,11 +5562,30 @@ compile_def_function(ufunc_T *ufunc, int set_return_type)
            goto erret;
        for (i = 0; i < count; ++i)
        {
+           garray_T    *stack = &cctx.ctx_type_stack;
+           type_T      *val_type;
+           int         arg_idx = first_def_arg + i;
+
            ufunc->uf_def_arg_idx[i] = instr->ga_len;
            arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
-           if (compile_expr1(&arg, &cctx) == FAIL
-                   || generate_STORE(&cctx, ISN_STORE,
-                                               i - count - off, NULL) == FAIL)
+           if (compile_expr1(&arg, &cctx) == FAIL)
+               goto erret;
+
+           // If no type specified use the type of the default value.
+           // Otherwise check that the default value type matches the
+           // specified type.
+           val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
+           if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
+               ufunc->uf_arg_types[arg_idx] = val_type;
+           else if (check_type(ufunc->uf_arg_types[i], val_type, FALSE)
+                                                                      == FAIL)
+           {
+               arg_type_mismatch(ufunc->uf_arg_types[arg_idx], val_type,
+                                                                 arg_idx + 1);
+               goto erret;
+           }
+
+           if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
                goto erret;
        }