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.