Patch 8.2.2306
Problem:    Vim9: when using function reference type is not checked.
Solution:   When using a function reference lookup the type and check the
            argument types. (issue #7629)
Files:      src/userfunc.c, src/proto/userfunc.pro, src/eval.c, src/structs.h,
            src/vim9type.c, src/proto/vim9type.pro, src/vim9compile.c,
            src/vim9execute.c, src/evalvars.c, src/evalfunc.c,
            src/testdir/test_vim9_func.vim


*** ../vim-8.2.2305/src/userfunc.c      2021-01-04 14:09:40.053795023 +0100
--- src/userfunc.c      2021-01-06 21:36:27.686016340 +0100
***************
*** 727,773 ****
   * name it contains, otherwise return "name".
   * If "partialp" is not NULL, and "name" is of type VAR_PARTIAL also set
   * "partialp".
   */
      char_u *
! deref_func_name(char_u *name, int *lenp, partial_T **partialp, int 
no_autoload)
  {
      dictitem_T        *v;
      int               cc;
!     char_u    *s;
  
      if (partialp != NULL)
        *partialp = NULL;
  
      cc = name[*lenp];
      name[*lenp] = NUL;
!     v = find_var(name, NULL, no_autoload);
      name[*lenp] = cc;
!     if (v != NULL && v->di_tv.v_type == VAR_FUNC)
      {
!       if (v->di_tv.vval.v_string == NULL)
        {
!           *lenp = 0;
!           return (char_u *)"";        // just in case
        }
-       s = v->di_tv.vval.v_string;
-       *lenp = (int)STRLEN(s);
-       return s;
-     }
  
!     if (v != NULL && v->di_tv.v_type == VAR_PARTIAL)
!     {
!       partial_T *pt = v->di_tv.vval.v_partial;
  
!       if (pt == NULL)
        {
!           *lenp = 0;
!           return (char_u *)"";        // just in case
        }
-       if (partialp != NULL)
-           *partialp = pt;
-       s = partial_name(pt);
-       *lenp = (int)STRLEN(s);
-       return s;
      }
  
      return name;
--- 727,794 ----
   * name it contains, otherwise return "name".
   * If "partialp" is not NULL, and "name" is of type VAR_PARTIAL also set
   * "partialp".
+  * If "type" is not NULL and a Vim9 script-local variable is found look up the
+  * type of the variable.
   */
      char_u *
! deref_func_name(
!       char_u      *name,
!       int         *lenp,
!       partial_T   **partialp,
!       type_T      **type,
!       int         no_autoload)
  {
      dictitem_T        *v;
      int               cc;
!     char_u    *s = NULL;
!     hashtab_T *ht;
  
      if (partialp != NULL)
        *partialp = NULL;
  
      cc = name[*lenp];
      name[*lenp] = NUL;
!     v = find_var(name, &ht, no_autoload);
      name[*lenp] = cc;
!     if (v != NULL)
      {
!       if (v->di_tv.v_type == VAR_FUNC)
        {
!           if (v->di_tv.vval.v_string == NULL)
!           {
!               *lenp = 0;
!               return (char_u *)"";    // just in case
!           }
!           s = v->di_tv.vval.v_string;
!           *lenp = (int)STRLEN(s);
        }
  
!       if (v->di_tv.v_type == VAR_PARTIAL)
!       {
!           partial_T *pt = v->di_tv.vval.v_partial;
  
!           if (pt == NULL)
!           {
!               *lenp = 0;
!               return (char_u *)"";    // just in case
!           }
!           if (partialp != NULL)
!               *partialp = pt;
!           s = partial_name(pt);
!           *lenp = (int)STRLEN(s);
!       }
! 
!       if (s != NULL)
        {
!           if (type != NULL && ht == get_script_local_ht())
!           {
!               svar_T  *sv = find_typval_in_script(&v->di_tv);
! 
!               if (sv != NULL)
!                   *type = sv->sv_type;
!           }
!           return s;
        }
      }
  
      return name;
***************
*** 2387,2392 ****
--- 2408,2421 ----
        }
      }
  
+     if (error == FCERR_NONE && funcexe->check_type != NULL && 
funcexe->evaluate)
+     {
+       // Check that the argument types are OK for the types of the funcref.
+       if (check_argument_types(funcexe->check_type, argvars, argcount,
+                                                                name) == FAIL)
+           error = FCERR_OTHER;
+     }
+ 
      if (error == FCERR_NONE && funcexe->evaluate)
      {
        char_u *rfname = fname;
***************
*** 2629,2635 ****
      int               skip,           // only find the end, don't evaluate
      int               flags,
      funcdict_T        *fdp,           // return: info about dictionary used
!     partial_T **partial)      // return: partial of a FuncRef
  {
      char_u    *name = NULL;
      char_u    *start;
--- 2658,2665 ----
      int               skip,           // only find the end, don't evaluate
      int               flags,
      funcdict_T        *fdp,           // return: info about dictionary used
!     partial_T **partial,      // return: partial of a FuncRef
!     type_T    **type)         // return: type of funcref if not NULL
  {
      char_u    *name = NULL;
      char_u    *start;
***************
*** 2733,2739 ****
      if (lv.ll_exp_name != NULL)
      {
        len = (int)STRLEN(lv.ll_exp_name);
!       name = deref_func_name(lv.ll_exp_name, &len, partial,
                                                     flags & TFN_NO_AUTOLOAD);
        if (name == lv.ll_exp_name)
            name = NULL;
--- 2763,2769 ----
      if (lv.ll_exp_name != NULL)
      {
        len = (int)STRLEN(lv.ll_exp_name);
!       name = deref_func_name(lv.ll_exp_name, &len, partial, type,
                                                     flags & TFN_NO_AUTOLOAD);
        if (name == lv.ll_exp_name)
            name = NULL;
***************
*** 2741,2747 ****
      else if (!(flags & TFN_NO_DEREF))
      {
        len = (int)(end - *pp);
!       name = deref_func_name(*pp, &len, partial, flags & TFN_NO_AUTOLOAD);
        if (name == *pp)
            name = NULL;
      }
--- 2771,2778 ----
      else if (!(flags & TFN_NO_DEREF))
      {
        len = (int)(end - *pp);
!       name = deref_func_name(*pp, &len, partial, type,
!                                                     flags & TFN_NO_AUTOLOAD);
        if (name == *pp)
            name = NULL;
      }
***************
*** 3064,3070 ****
      else
      {
        name = trans_function_name(&p, &is_global, eap->skip,
!                                                TFN_NO_AUTOLOAD, &fudi, NULL);
        paren = (vim_strchr(p, '(') != NULL);
        if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip)
        {
--- 3095,3101 ----
      else
      {
        name = trans_function_name(&p, &is_global, eap->skip,
!                                          TFN_NO_AUTOLOAD, &fudi, NULL, NULL);
        paren = (vim_strchr(p, '(') != NULL);
        if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip)
        {
***************
*** 3479,3485 ****
                if (*p == '!')
                    p = skipwhite(p + 1);
                p += eval_fname_script(p);
!               vim_free(trans_function_name(&p, NULL, TRUE, 0, NULL, NULL));
                if (*skipwhite(p) == '(')
                {
                    if (nesting == MAX_FUNC_NESTING - 1)
--- 3510,3517 ----
                if (*p == '!')
                    p = skipwhite(p + 1);
                p += eval_fname_script(p);
!               vim_free(trans_function_name(&p, NULL, TRUE, 0, NULL,
!                                                                 NULL, NULL));
                if (*skipwhite(p) == '(')
                {
                    if (nesting == MAX_FUNC_NESTING - 1)
***************
*** 3616,3622 ****
      {
        hashtab_T       *ht;
  
!       v = find_var(name, &ht, FALSE);
        if (v != NULL && v->di_tv.v_type == VAR_FUNC)
        {
            emsg_funcname(N_("E707: Function name conflicts with variable: %s"),
--- 3648,3654 ----
      {
        hashtab_T       *ht;
  
!       v = find_var(name, &ht, TRUE);
        if (v != NULL && v->di_tv.v_type == VAR_FUNC)
        {
            emsg_funcname(N_("E707: Function name conflicts with variable: %s"),
***************
*** 4007,4013 ****
      flag = TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD;
      if (no_deref)
        flag |= TFN_NO_DEREF;
!     p = trans_function_name(&nm, &is_global, FALSE, flag, NULL, NULL);
      nm = skipwhite(nm);
  
      // Only accept "funcname", "funcname ", "funcname (..." and
--- 4039,4045 ----
      flag = TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD;
      if (no_deref)
        flag |= TFN_NO_DEREF;
!     p = trans_function_name(&nm, &is_global, FALSE, flag, NULL, NULL, NULL);
      nm = skipwhite(nm);
  
      // Only accept "funcname", "funcname ", "funcname (..." and
***************
*** 4027,4033 ****
      int               is_global = FALSE;
  
      p = trans_function_name(&nm, &is_global, FALSE,
!                                               TFN_INT|TFN_QUIET, NULL, NULL);
  
      if (p != NULL && *nm == NUL
                       && (!check || translated_function_exists(p, is_global)))
--- 4059,4065 ----
      int               is_global = FALSE;
  
      p = trans_function_name(&nm, &is_global, FALSE,
!                                         TFN_INT|TFN_QUIET, NULL, NULL, NULL);
  
      if (p != NULL && *nm == NUL
                       && (!check || translated_function_exists(p, is_global)))
***************
*** 4097,4103 ****
      int               is_global = FALSE;
  
      p = eap->arg;
!     name = trans_function_name(&p, &is_global, eap->skip, 0, &fudi, NULL);
      vim_free(fudi.fd_newkey);
      if (name == NULL)
      {
--- 4129,4136 ----
      int               is_global = FALSE;
  
      p = eap->arg;
!     name = trans_function_name(&p, &is_global, eap->skip, 0, &fudi,
!                                                                  NULL, NULL);
      vim_free(fudi.fd_newkey);
      if (name == NULL)
      {
***************
*** 4328,4333 ****
--- 4361,4367 ----
      funcdict_T        fudi;
      partial_T *partial = NULL;
      evalarg_T evalarg;
+     type_T    *type = NULL;
  
      fill_evalarg_from_eap(&evalarg, eap, eap->skip);
      if (eap->skip)
***************
*** 4343,4350 ****
        return;
      }
  
!     tofree = trans_function_name(&arg, NULL, eap->skip,
!                                                    TFN_INT, &fudi, &partial);
      if (fudi.fd_newkey != NULL)
      {
        // Still need to give an error message for missing key.
--- 4377,4384 ----
        return;
      }
  
!     tofree = trans_function_name(&arg, NULL, eap->skip, TFN_INT,
!                             &fudi, &partial, in_vim9script() ? &type : NULL);
      if (fudi.fd_newkey != NULL)
      {
        // Still need to give an error message for missing key.
***************
*** 4363,4370 ****
      // contents.  For VAR_PARTIAL get its partial, unless we already have one
      // from trans_function_name().
      len = (int)STRLEN(tofree);
!     name = deref_func_name(tofree, &len,
!                                   partial != NULL ? NULL : &partial, FALSE);
  
      // Skip white space to allow ":call func ()".  Not good, but required for
      // backward compatibility.
--- 4397,4404 ----
      // contents.  For VAR_PARTIAL get its partial, unless we already have one
      // from trans_function_name().
      len = (int)STRLEN(tofree);
!     name = deref_func_name(tofree, &len, partial != NULL ? NULL : &partial,
!                       in_vim9script() && type == NULL ? &type : NULL, FALSE);
  
      // Skip white space to allow ":call func ()".  Not good, but required for
      // backward compatibility.
***************
*** 4416,4421 ****
--- 4450,4456 ----
        funcexe.evaluate = !eap->skip;
        funcexe.partial = partial;
        funcexe.selfdict = fudi.fd_dict;
+       funcexe.check_type = type;
        if (get_func_tv(name, -1, &rettv, &arg, &evalarg, &funcexe) == FAIL)
        {
            failed = TRUE;
*** ../vim-8.2.2305/src/proto/userfunc.pro      2021-01-04 14:09:40.053795023 
+0100
--- src/proto/userfunc.pro      2021-01-06 21:37:44.985807661 +0100
***************
*** 4,10 ****
  char_u *get_lambda_name(void);
  char_u *register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state);
  int get_lambda_tv(char_u **arg, typval_T *rettv, int types_optional, 
evalarg_T *evalarg);
! char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, int 
no_autoload);
  void emsg_funcname(char *ermsg, char_u *name);
  int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, 
evalarg_T *evalarg, funcexe_T *funcexe);
  char_u *fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int 
*error);
--- 4,10 ----
  char_u *get_lambda_name(void);
  char_u *register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state);
  int get_lambda_tv(char_u **arg, typval_T *rettv, int types_optional, 
evalarg_T *evalarg);
! char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, type_T 
**type, int no_autoload);
  void emsg_funcname(char *ermsg, char_u *name);
  int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, 
evalarg_T *evalarg, funcexe_T *funcexe);
  char_u *fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int 
*error);
***************
*** 31,37 ****
  void user_func_error(int error, char_u *name);
  int call_func(char_u *funcname, int len, typval_T *rettv, int argcount_in, 
typval_T *argvars_in, funcexe_T *funcexe);
  char_u *printable_func_name(ufunc_T *fp);
! char_u *trans_function_name(char_u **pp, int *is_global, int skip, int flags, 
funcdict_T *fdp, partial_T **partial);
  char_u *untrans_function_name(char_u *name);
  void list_functions(regmatch_T *regmatch);
  ufunc_T *define_function(exarg_T *eap, char_u *name_arg);
--- 31,37 ----
  void user_func_error(int error, char_u *name);
  int call_func(char_u *funcname, int len, typval_T *rettv, int argcount_in, 
typval_T *argvars_in, funcexe_T *funcexe);
  char_u *printable_func_name(ufunc_T *fp);
! char_u *trans_function_name(char_u **pp, int *is_global, int skip, int flags, 
funcdict_T *fdp, partial_T **partial, type_T **type);
  char_u *untrans_function_name(char_u *name);
  void list_functions(regmatch_T *regmatch);
  ufunc_T *define_function(exarg_T *eap, char_u *name_arg);
*** ../vim-8.2.2305/src/eval.c  2021-01-05 22:08:17.205806639 +0100
--- src/eval.c  2021-01-06 21:25:44.895464060 +0100
***************
*** 721,728 ****
  
  #ifdef FEAT_FOLDING
  /*
!  * Evaluate 'foldexpr'.  Returns the foldlevel, and any character preceding
!  * it in "*cp".  Doesn't give error messages.
   */
      int
  eval_foldexpr(char_u *arg, int *cp)
--- 721,730 ----
  
  #ifdef FEAT_FOLDING
  /*
!  * Evaluate "arg", which is 'foldexpr'.
!  * Note: caller must set "curwin" to match "arg".
!  * Returns the foldlevel, and any character preceding it in "*cp".  Doesn't
!  * give error messages.
   */
      int
  eval_foldexpr(char_u *arg, int *cp)
***************
*** 809,814 ****
--- 811,817 ----
      int               len;
      hashtab_T *ht = NULL;
      int               quiet = flags & GLV_QUIET;
+     int               writing;
  
      // Clear everything in "lp".
      CLEAR_POINTER(lp);
***************
*** 882,891 ****
  
      cc = *p;
      *p = NUL;
!     // Only pass &ht when we would write to the variable, it prevents autoload
!     // as well.
!     v = find_var(lp->ll_name, (flags & GLV_READ_ONLY) ? NULL : &ht,
!                                                     flags & GLV_NO_AUTOLOAD);
      if (v == NULL && !quiet)
        semsg(_(e_undefined_variable_str), lp->ll_name);
      *p = cc;
--- 885,894 ----
  
      cc = *p;
      *p = NUL;
!     // When we would write to the variable pass &ht and prevent autoload.
!     writing = !(flags & GLV_READ_ONLY);
!     v = find_var(lp->ll_name, writing ? &ht : NULL,
!                                        (flags & GLV_NO_AUTOLOAD) || writing);
      if (v == NULL && !quiet)
        semsg(_(e_undefined_variable_str), lp->ll_name);
      *p = cc;
***************
*** 1972,1984 ****
      int               len = name_len;
      partial_T *partial;
      int               ret = OK;
  
      if (!evaluate)
        check_vars(s, len);
  
      // If "s" is the name of a variable of type VAR_FUNC
      // use its contents.
!     s = deref_func_name(s, &len, &partial, !evaluate);
  
      // Need to make a copy, in case evaluating the arguments makes
      // the name invalid.
--- 1975,1989 ----
      int               len = name_len;
      partial_T *partial;
      int               ret = OK;
+     type_T    *type = NULL;
  
      if (!evaluate)
        check_vars(s, len);
  
      // If "s" is the name of a variable of type VAR_FUNC
      // use its contents.
!     s = deref_func_name(s, &len, &partial,
!                                   in_vim9script() ? &type : NULL, !evaluate);
  
      // Need to make a copy, in case evaluating the arguments makes
      // the name invalid.
***************
*** 1996,2001 ****
--- 2001,2007 ----
        funcexe.evaluate = evaluate;
        funcexe.partial = partial;
        funcexe.basetv = basetv;
+       funcexe.check_type = type;
        ret = get_func_tv(s, len, rettv, arg, evalarg, &funcexe);
      }
      vim_free(s);
*** ../vim-8.2.2305/src/structs.h       2021-01-04 12:41:49.507891351 +0100
--- src/structs.h       2021-01-06 20:23:54.283683093 +0100
***************
*** 1944,1949 ****
--- 1944,1950 ----
      partial_T *partial;       // for extra arguments
      dict_T    *selfdict;      // Dictionary for "self"
      typval_T  *basetv;        // base for base->method()
+     type_T    *check_type;    // type from funcref or NULL
  } funcexe_T;
  
  /*
*** ../vim-8.2.2305/src/vim9type.c      2021-01-03 13:09:48.226390595 +0100
--- src/vim9type.c      2021-01-06 21:11:59.509421778 +0100
***************
*** 528,533 ****
--- 528,573 ----
  }
  
  /*
+  * Check that the arguments of "type" match "argvars[argcount]".
+  * Return OK/FAIL.
+  */
+     int
+ check_argument_types(type_T *type, typval_T *argvars, int argcount, char_u 
*name)
+ {
+     int           varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
+     int           i;
+ 
+     if (type->tt_type != VAR_FUNC && type->tt_type != VAR_PARTIAL)
+       return OK;  // just in case
+     if (argcount < type->tt_min_argcount - varargs)
+     {
+       semsg(_(e_toofewarg), name);
+       return FAIL;
+     }
+     if (!varargs && type->tt_argcount >= 0 && argcount > type->tt_argcount)
+     {
+       semsg(_(e_toomanyarg), name);
+       return FAIL;
+     }
+     if (type->tt_args == NULL)
+       return OK;  // cannot check
+ 
+ 
+     for (i = 0; i < argcount; ++i)
+     {
+       type_T  *expected;
+ 
+       if (varargs && i >= type->tt_argcount - 1)
+           expected = type->tt_args[type->tt_argcount - 1]->tt_member;
+       else
+           expected = type->tt_args[i];
+       if (check_typval_type(expected, &argvars[i], i + 1) == FAIL)
+           return FAIL;
+     }
+     return OK;
+ }
+ 
+ /*
   * Skip over a type definition and return a pointer to just after it.
   * When "optional" is TRUE then a leading "?" is accepted.
   */
*** ../vim-8.2.2305/src/proto/vim9type.pro      2020-12-26 20:09:11.282465257 
+0100
--- src/proto/vim9type.pro      2021-01-06 20:48:43.780691288 +0100
***************
*** 16,21 ****
--- 16,22 ----
  void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
  int check_type(type_T *expected, type_T *actual, int give_msg, int argidx);
  int check_arg_type(type_T *expected, type_T *actual, int argidx);
+ int check_argument_types(type_T *type, typval_T *argvars, int argcount, 
char_u *name);
  char_u *skip_type(char_u *start, int optional);
  type_T *parse_type(char_u **arg, garray_T *type_gap, int give_error);
  int equal_type(type_T *type1, type_T *type2);
*** ../vim-8.2.2305/src/vim9compile.c   2021-01-05 22:08:17.201806649 +0100
--- src/vim9compile.c   2021-01-06 21:12:38.253324361 +0100
***************
*** 1790,1798 ****
                                                       stack->ga_len + offset];
                    type_T *expected;
  
!                   if (varargs && i >= type->tt_min_argcount - 1)
                        expected = type->tt_args[
!                                        type->tt_min_argcount - 1]->tt_member;
                    else
                        expected = type->tt_args[i];
                    if (need_type(actual, expected, offset,
--- 1790,1798 ----
                                                       stack->ga_len + offset];
                    type_T *expected;
  
!                   if (varargs && i >= type->tt_argcount - 1)
                        expected = type->tt_args[
!                                            type->tt_argcount - 1]->tt_member;
                    else
                        expected = type->tt_args[i];
                    if (need_type(actual, expected, offset,
*** ../vim-8.2.2305/src/vim9execute.c   2021-01-05 20:58:20.851037690 +0100
--- src/vim9execute.c   2021-01-06 21:37:10.413920902 +0100
***************
*** 3423,3429 ****
      }
      else
        fname = trans_function_name(&arg, &is_global, FALSE,
!                           TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD, NULL, NULL);
      if (fname == NULL)
      {
        semsg(_(e_invarg2), eap->arg);
--- 3423,3429 ----
      }
      else
        fname = trans_function_name(&arg, &is_global, FALSE,
!                     TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD, NULL, NULL, NULL);
      if (fname == NULL)
      {
        semsg(_(e_invarg2), eap->arg);
*** ../vim-8.2.2305/src/evalvars.c      2021-01-04 13:37:50.251107339 +0100
--- src/evalvars.c      2021-01-06 21:23:01.983837281 +0100
***************
*** 2639,2646 ****
   * Find variable "name" in the list of variables.
   * Return a pointer to it if found, NULL if not found.
   * Careful: "a:0" variables don't have a name.
!  * When "htp" is not NULL we are writing to the variable, set "htp" to the
!  * hashtab_T used.
   */
      dictitem_T *
  find_var(char_u *name, hashtab_T **htp, int no_autoload)
--- 2639,2645 ----
   * Find variable "name" in the list of variables.
   * Return a pointer to it if found, NULL if not found.
   * Careful: "a:0" variables don't have a name.
!  * When "htp" is not NULL  set "htp" to the hashtab_T used.
   */
      dictitem_T *
  find_var(char_u *name, hashtab_T **htp, int no_autoload)
***************
*** 2654,2665 ****
        *htp = ht;
      if (ht == NULL)
        return NULL;
!     ret = find_var_in_ht(ht, *name, varname, no_autoload || htp != NULL);
      if (ret != NULL)
        return ret;
  
      // Search in parent scope for lambda
!     ret = find_var_in_scoped_ht(name, no_autoload || htp != NULL);
      if (ret != NULL)
        return ret;
  
--- 2653,2664 ----
        *htp = ht;
      if (ht == NULL)
        return NULL;
!     ret = find_var_in_ht(ht, *name, varname, no_autoload);
      if (ret != NULL)
        return ret;
  
      // Search in parent scope for lambda
!     ret = find_var_in_scoped_ht(name, no_autoload);
      if (ret != NULL)
        return ret;
  
***************
*** 2669,2676 ****
        ht = get_script_local_ht();
        if (ht != NULL)
        {
!           ret = find_var_in_ht(ht, *name, varname,
!                                                  no_autoload || htp != NULL);
            if (ret != NULL)
            {
                if (htp != NULL)
--- 2668,2674 ----
        ht = get_script_local_ht();
        if (ht != NULL)
        {
!           ret = find_var_in_ht(ht, *name, varname, no_autoload);
            if (ret != NULL)
            {
                if (htp != NULL)
*** ../vim-8.2.2305/src/evalfunc.c      2021-01-03 19:51:01.392063235 +0100
--- src/evalfunc.c      2021-01-06 21:37:01.177941528 +0100
***************
*** 3497,3503 ****
      {
        name = s;
        trans_name = trans_function_name(&name, &is_global, FALSE,
!            TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD | TFN_NO_DEREF, NULL, NULL);
        if (*name != NUL)
            s = NULL;
      }
--- 3497,3504 ----
      {
        name = s;
        trans_name = trans_function_name(&name, &is_global, FALSE,
!            TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD | TFN_NO_DEREF,
!                                                            NULL, NULL, NULL);
        if (*name != NUL)
            s = NULL;
      }
*** ../vim-8.2.2305/src/testdir/test_vim9_func.vim      2021-01-04 
14:09:40.053795023 +0100
--- src/testdir/test_vim9_func.vim      2021-01-06 21:29:46.026917452 +0100
***************
*** 579,584 ****
--- 579,600 ----
  
    CheckScriptFailure(head + ["funcMap['func']('str', 123)"] + tail, 'E119:')
    CheckScriptFailure(head + ["funcMap['func']('str', 123, [1], 4)"] + tail, 
'E118:')
+ 
+   var lines =<< trim END
+       vim9script
+       var Ref: func(number): any
+       Ref = (j) => !j
+       echo Ref(false)
+   END
+   CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected 
number but got bool', 4)
+ 
+   lines =<< trim END
+       vim9script
+       var Ref: func(number): any
+       Ref = (j) => !j
+       call Ref(false)
+   END
+   CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected 
number but got bool', 4)
  enddef
  
  def Test_call_lambda_args()
*** ../vim-8.2.2305/src/version.c       2021-01-05 22:08:17.205806639 +0100
--- src/version.c       2021-01-06 21:58:11.602231840 +0100
***************
*** 752,753 ****
--- 752,755 ----
  {   /* Add new patch number below this line */
+ /**/
+     2306,
  /**/

-- 
Common sense is what tells you that the world is flat.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            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/202101062100.106L0OQY300273%40masaka.moolenaar.net.

Raspunde prin e-mail lui