Patch 9.0.1119
Problem:    Type of arguments not checked when calling a partial.
Solution:   Give an error for a wrong argument type. (closes #11753)
Files:      src/vim9execute.c, src/testdir/test_vim9_func.vim


*** ../vim-9.0.1118/src/vim9execute.c   2022-12-29 20:56:20.025538293 +0000
--- src/vim9execute.c   2022-12-31 13:54:32.586955681 +0000
***************
*** 377,382 ****
--- 377,417 ----
  }
  
  /*
+  * Check "argcount" arguments on the stack against what "ufunc" expects.
+  * "off" is the offset of arguments on the stack.
+  * Return OK or FAIL.
+  */
+     static int
+ check_ufunc_arg_types(ufunc_T *ufunc, int argcount, int off, ectx_T *ectx)
+ {
+     if (ufunc->uf_arg_types != NULL || ufunc->uf_va_type != NULL)
+     {
+       typval_T        *argv = STACK_TV_BOT(0) - argcount - off;
+ 
+       // The function can change at runtime, check that the argument
+       // types are correct.
+       for (int i = 0; i < argcount; ++i)
+       {
+           type_T *type = NULL;
+ 
+           // assume a v:none argument, using the default value, is always OK
+           if (argv[i].v_type == VAR_SPECIAL
+                                        && argv[i].vval.v_number == VVAL_NONE)
+               continue;
+ 
+           if (i < ufunc->uf_args.ga_len && ufunc->uf_arg_types != NULL)
+               type = ufunc->uf_arg_types[i];
+           else if (ufunc->uf_va_type != NULL)
+               type = ufunc->uf_va_type->tt_member;
+           if (type != NULL && check_typval_arg_type(type,
+                                           &argv[i], NULL, i + 1) == FAIL)
+               return FAIL;
+       }
+     }
+     return OK;
+ }
+ 
+ /*
   * Call compiled function "cdf_idx" from compiled code.
   * This adds a stack frame and sets the instruction pointer to the start of 
the
   * called function.
***************
*** 498,503 ****
--- 533,542 ----
        return FAIL;
      }
  
+     // Check the argument types.
+     if (check_ufunc_arg_types(ufunc, argcount, vararg_count, ectx) == FAIL)
+       return FAIL;
+ 
      // Reserve space for:
      // - missing arguments
      // - stack frame
***************
*** 1345,1370 ****
  
      if (ufunc != NULL)
      {
!       if (ufunc->uf_arg_types != NULL || ufunc->uf_va_type != NULL)
!       {
!           int i;
!           typval_T    *argv = STACK_TV_BOT(0) - argcount;
! 
!           // The function can change at runtime, check that the argument
!           // types are correct.
!           for (i = 0; i < argcount; ++i)
!           {
!               type_T *type = NULL;
! 
!               if (i < ufunc->uf_args.ga_len && ufunc->uf_arg_types != NULL)
!                   type = ufunc->uf_arg_types[i];
!               else if (ufunc->uf_va_type != NULL)
!                   type = ufunc->uf_va_type->tt_member;
!               if (type != NULL && check_typval_arg_type(type,
!                                               &argv[i], NULL, i + 1) == FAIL)
!                   return FAIL;
!           }
!       }
  
        return call_ufunc(ufunc, NULL, argcount, ectx, iptr, selfdict);
      }
--- 1384,1391 ----
  
      if (ufunc != NULL)
      {
!       if (check_ufunc_arg_types(ufunc, argcount, 0, ectx) == FAIL)
!           return FAIL;
  
        return call_ufunc(ufunc, NULL, argcount, ectx, iptr, selfdict);
      }
*** ../vim-9.0.1118/src/testdir/test_vim9_func.vim      2022-12-27 
17:24:55.270083348 +0000
--- src/testdir/test_vim9_func.vim      2022-12-31 13:59:36.086769681 +0000
***************
*** 4277,4282 ****
--- 4277,4308 ----
    bw!
  endfunc
  
+ def Test_lambda_argument_type_check()
+   var lines =<< trim END
+       vim9script
+ 
+       def Scan(ll: list<any>): func(func(any))
+         return (Emit: func(any)) => {
+           for e in ll
+             Emit(e)
+           endfor
+         }
+       enddef
+ 
+       def Sum(Cont: func(func(any))): any
+         var sum = 0.0
+         Cont((v: float) => {  # <== NOTE: the lambda expects a float
+           sum += v
+         })
+         return sum
+       enddef
+ 
+       const ml = [3.0, 2, 7]
+       echo Scan(ml)->Sum()
+   END
+   v9.CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected 
float but got number')
+ enddef
+ 
  def Test_multiple_funcref()
    # This was using a NULL pointer
    var lines =<< trim END
*** ../vim-9.0.1118/src/version.c       2022-12-31 11:44:51.549772464 +0000
--- src/version.c       2022-12-31 13:33:14.947608978 +0000
***************
*** 697,698 ****
--- 697,700 ----
  {   /* Add new patch number below this line */
+ /**/
+     1119,
  /**/

-- 
So when I saw the post to comp.editors, I rushed over to the FTP site to
grab it.  So I yank apart the tarball, light x candles, where x= the
vim version multiplied by the md5sum of the source divided by the MAC of
my NIC (8A3FA78155A8A1D346C3C4A), put on black robes, dim the lights,
wave a dead chicken over the hard drive, and summon the power of GNU GCC
with the magic words "make config ; make!".
                [Jason Spence, compiling Vim 5.0]

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20221231140200.4DF7F1C0AA4%40moolenaar.net.

Raspunde prin e-mail lui