Patch 8.2.3783
Problem:    Confusing error for using a variable as a function.
Solution:   If a function is not found but there is a variable, give a more
            useful error. (issue #9310)
Files:      src/eval.c, src/userfunc.c, src/proto/userfunc.pro,
            src/structs.h, src/vim9execute.c, src/testdir/test_functions.vim,
            src/testdir/test_vim9_script.vim, src/testdir/test_vim9_func.vim


*** ../vim-8.2.3782/src/eval.c  2021-12-09 17:43:53.847057125 +0000
--- src/eval.c  2021-12-11 16:03:34.776046478 +0000
***************
*** 1988,1993 ****
--- 1988,1994 ----
      partial_T *partial;
      int               ret = OK;
      type_T    *type = NULL;
+     int               found_var = FALSE;
  
      if (!evaluate)
        check_vars(s, len);
***************
*** 1995,2001 ****
      // 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,2002 ----
      // 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, &found_var);
  
      // Need to make a copy, in case evaluating the arguments makes
      // the name invalid.
***************
*** 2014,2019 ****
--- 2015,2021 ----
        funcexe.partial = partial;
        funcexe.basetv = basetv;
        funcexe.check_type = type;
+       funcexe.fe_found_var = found_var;
        ret = get_func_tv(s, len, rettv, arg, evalarg, &funcexe);
      }
      vim_free(s);
*** ../vim-8.2.3782/src/userfunc.c      2021-12-11 13:54:43.123245009 +0000
--- src/userfunc.c      2021-12-11 16:06:39.940010971 +0000
***************
*** 1544,1549 ****
--- 1544,1550 ----
   * "partialp".
   * If "type" is not NULL and a Vim9 script-local variable is found look up the
   * type of the variable.
+  * If "found_var" is not NULL and a variable was found set it to TRUE.
   */
      char_u *
  deref_func_name(
***************
*** 1551,1557 ****
        int         *lenp,
        partial_T   **partialp,
        type_T      **type,
!       int         no_autoload)
  {
      dictitem_T        *v;
      typval_T  *tv = NULL;
--- 1552,1559 ----
        int         *lenp,
        partial_T   **partialp,
        type_T      **type,
!       int         no_autoload,
!       int         *found_var)
  {
      dictitem_T        *v;
      typval_T  *tv = NULL;
***************
*** 1609,1614 ****
--- 1611,1618 ----
  
      if (tv != NULL)
      {
+       if (found_var != NULL)
+           *found_var = TRUE;
        if (tv->v_type == VAR_FUNC)
        {
            if (tv->vval.v_string == NULL)
***************
*** 3199,3210 ****
   * Nothing if "error" is FCERR_NONE.
   */
      void
! user_func_error(int error, char_u *name)
  {
      switch (error)
      {
        case FCERR_UNKNOWN:
!               emsg_funcname(e_unknownfunc, name);
                break;
        case FCERR_NOTMETHOD:
                emsg_funcname(
--- 3203,3217 ----
   * Nothing if "error" is FCERR_NONE.
   */
      void
! user_func_error(int error, char_u *name, funcexe_T *funcexe)
  {
      switch (error)
      {
        case FCERR_UNKNOWN:
!               if (funcexe->fe_found_var)
!                   semsg(_(e_not_callable_type_str), name);
!               else
!                   emsg_funcname(e_unknownfunc, name);
                break;
        case FCERR_NOTMETHOD:
                emsg_funcname(
***************
*** 3448,3454 ****
       */
      if (!aborting())
      {
!       user_func_error(error, (name != NULL) ? name : funcname);
      }
  
      // clear the copies made from the partial
--- 3455,3461 ----
       */
      if (!aborting())
      {
!       user_func_error(error, (name != NULL) ? name : funcname, funcexe);
      }
  
      // clear the copies made from the partial
***************
*** 3677,3683 ****
      {
        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;
      }
--- 3684,3690 ----
      {
        len = (int)STRLEN(lv.ll_exp_name);
        name = deref_func_name(lv.ll_exp_name, &len, partial, type,
!                                               flags & TFN_NO_AUTOLOAD, NULL);
        if (name == lv.ll_exp_name)
            name = NULL;
      }
***************
*** 3685,3691 ****
      {
        len = (int)(end - *pp);
        name = deref_func_name(*pp, &len, partial, type,
!                                                     flags & TFN_NO_AUTOLOAD);
        if (name == *pp)
            name = NULL;
      }
--- 3692,3698 ----
      {
        len = (int)(end - *pp);
        name = deref_func_name(*pp, &len, partial, type,
!                                               flags & TFN_NO_AUTOLOAD, NULL);
        if (name == *pp)
            name = NULL;
      }
***************
*** 5004,5009 ****
--- 5011,5017 ----
      partial_T *partial = NULL;
      evalarg_T evalarg;
      type_T    *type = NULL;
+     int               found_var = FALSE;
  
      fill_evalarg_from_eap(&evalarg, eap, eap->skip);
      if (eap->skip)
***************
*** 5040,5046 ****
      // 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.
--- 5048,5054 ----
      // 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, &found_var);
  
      // Skip white space to allow ":call func ()".  Not good, but required for
      // backward compatibility.
***************
*** 5096,5101 ****
--- 5104,5110 ----
        funcexe.partial = partial;
        funcexe.selfdict = fudi.fd_dict;
        funcexe.check_type = type;
+       funcexe.fe_found_var = found_var;
        rettv.v_type = VAR_UNKNOWN;     // clear_tv() uses this
        if (get_func_tv(name, -1, &rettv, &arg, &evalarg, &funcexe) == FAIL)
        {
*** ../vim-8.2.3782/src/proto/userfunc.pro      2021-12-06 15:06:49.335517805 
+0000
--- src/proto/userfunc.pro      2021-12-11 16:00:54.644001292 +0000
***************
*** 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);
--- 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, int *found_var);
  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);
***************
*** 30,36 ****
  int get_callback_depth(void);
  int call_callback(callback_T *callback, int len, typval_T *rettv, int 
argcount, typval_T *argvars);
  varnumber_T call_callback_retnr(callback_T *callback, int argcount, typval_T 
*argvars);
! 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);
--- 30,36 ----
  int get_callback_depth(void);
  int call_callback(callback_T *callback, int len, typval_T *rettv, int 
argcount, typval_T *argvars);
  varnumber_T call_callback_retnr(callback_T *callback, int argcount, typval_T 
*argvars);
! void user_func_error(int error, char_u *name, funcexe_T *funcexe);
  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);
*** ../vim-8.2.3782/src/structs.h       2021-12-10 13:40:05.060213928 +0000
--- src/structs.h       2021-12-11 15:58:50.743900913 +0000
***************
*** 2001,2006 ****
--- 2001,2008 ----
      dict_T    *selfdict;      // Dictionary for "self"
      typval_T  *basetv;        // base for base->method()
      type_T    *check_type;    // type from funcref or NULL
+     int               fe_found_var;   // if the function is not found then 
give an
+                               // error that a variable is not callable.
  } funcexe_T;
  
  /*
*** ../vim-8.2.3782/src/vim9execute.c   2021-12-09 14:23:40.261634977 +0000
--- src/vim9execute.c   2021-12-11 16:01:25.788016783 +0000
***************
*** 890,896 ****
  
      if (error != FCERR_NONE)
      {
!       user_func_error(error, ufunc->uf_name);
        return FAIL;
      }
      if (did_emsg > did_emsg_before)
--- 890,896 ----
  
      if (error != FCERR_NONE)
      {
!       user_func_error(error, ufunc->uf_name, &funcexe);
        return FAIL;
      }
      if (did_emsg > did_emsg_before)
***************
*** 2343,2349 ****
                    long        n = 0;
                    char_u      *s = NULL;
                    char        *msg;
!                   callback_T  cb = {NULL, NULL, 0};
  
                    --ectx->ec_stack.ga_len;
                    tv = STACK_TV_BOT(0);
--- 2343,2350 ----
                    long        n = 0;
                    char_u      *s = NULL;
                    char        *msg;
!                   char_u      numbuf[NUMBUFLEN];
!                   char_u      *tofree = NULL;
  
                    --ectx->ec_stack.ga_len;
                    tv = STACK_TV_BOT(0);
***************
*** 2356,2383 ****
                    else if (iptr->isn_type == ISN_STOREFUNCOPT)
                    {
                        SOURCING_LNUM = iptr->isn_lnum;
!                       cb = get_callback(tv);
!                       if (cb.cb_name == NULL || *cb.cb_name == NUL)
                        {
                            clear_tv(tv);
-                           free_callback(&cb);
                            goto on_error;
                        }
-                       s = cb.cb_name;
                    }
                    else
                        // must be VAR_NUMBER, CHECKTYPE makes sure
                        n = tv->vval.v_number;
                    msg = set_option_value(opt_name, n, s, opt_flags);
                    clear_tv(tv);
                    if (msg != NULL)
                    {
                        SOURCING_LNUM = iptr->isn_lnum;
                        emsg(_(msg));
                        goto on_error;
                    }
-                   if (cb.cb_name != NULL)
-                       free_callback(&cb);
                }
                break;
  
--- 2357,2385 ----
                    else if (iptr->isn_type == ISN_STOREFUNCOPT)
                    {
                        SOURCING_LNUM = iptr->isn_lnum;
!                       // If the option can be set to a function reference or
!                       // a lambda and the passed value is a function
!                       // reference, then convert it to the name (string) of
!                       // the function reference.
!                       s = tv2string(tv, &tofree, numbuf, 0);
!                       if (s == NULL || *s == NUL)
                        {
                            clear_tv(tv);
                            goto on_error;
                        }
                    }
                    else
                        // must be VAR_NUMBER, CHECKTYPE makes sure
                        n = tv->vval.v_number;
                    msg = set_option_value(opt_name, n, s, opt_flags);
                    clear_tv(tv);
+                   vim_free(tofree);
                    if (msg != NULL)
                    {
                        SOURCING_LNUM = iptr->isn_lnum;
                        emsg(_(msg));
                        goto on_error;
                    }
                }
                break;
  
*** ../vim-8.2.3782/src/testdir/test_functions.vim      2021-12-09 
16:40:14.541024052 +0000
--- src/testdir/test_functions.vim      2021-12-11 16:08:25.003959665 +0000
***************
*** 2234,2239 ****
--- 2234,2245 ----
    call call(test_null_partial(), [])
    call assert_fails('call test_null_function()()', 'E1192:')
    call assert_fails('call test_null_partial()()', 'E117:')
+ 
+   let lines =<< trim END
+       let Time = 'localtime'
+       call Time()
+   END
+   CheckScriptFailure(lines, 'E1085:')
  endfunc
  
  func Test_char2nr()
*** ../vim-8.2.3782/src/testdir/test_vim9_script.vim    2021-12-11 
13:54:43.123245009 +0000
--- src/testdir/test_vim9_script.vim    2021-12-11 16:09:41.655910979 +0000
***************
*** 1922,1927 ****
--- 1922,1936 ----
    CheckDefAndScriptFailure(lines, 'E1207:', 2)
  enddef
  
+ def Test_vim9script_call_wrong_type()
+   var lines =<< trim END
+       vim9script
+       var Time = 'localtime'
+       Time()
+   END
+   CheckScriptFailure(lines, 'E1085:')
+ enddef
+ 
  def s:RetSome(): string
    return 'some'
  enddef
*** ../vim-8.2.3782/src/testdir/test_vim9_func.vim      2021-12-10 
10:37:30.855830802 +0000
--- src/testdir/test_vim9_func.vim      2021-12-11 16:11:48.911813318 +0000
***************
*** 1459,1465 ****
  def Test_call_funcref()
    g:SomeFunc('abc')->assert_equal(3)
    assert_fails('NotAFunc()', 'E117:', '', 2, 'Test_call_funcref') # comment 
after call
!   assert_fails('g:NotAFunc()', 'E117:', '', 3, 'Test_call_funcref')
  
    var lines =<< trim END
      vim9script
--- 1459,1465 ----
  def Test_call_funcref()
    g:SomeFunc('abc')->assert_equal(3)
    assert_fails('NotAFunc()', 'E117:', '', 2, 'Test_call_funcref') # comment 
after call
!   assert_fails('g:NotAFunc()', 'E1085:', '', 3, 'Test_call_funcref')
  
    var lines =<< trim END
      vim9script
*** ../vim-8.2.3782/src/version.c       2021-12-11 13:54:43.123245009 +0000
--- src/version.c       2021-12-11 16:12:53.703756731 +0000
***************
*** 755,756 ****
--- 755,758 ----
  {   /* Add new patch number below this line */
+ /**/
+     3783,
  /**/

-- 
How To Keep A Healthy Level Of Insanity:
8. Don't use any punctuation marks.

 /// 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/20211211161445.CDB421C09EE%40moolenaar.net.

Raspunde prin e-mail lui