# HG changeset patch # User Bram Moolenaar # Date 1638297005 -3600 # Node ID bf1a7ce3f14a05abdc334000dbb1aa8ffb12840f # Parent cd04fa8a6d919ecfc62be6e30cefa82049f58493 patch 8.2.3705: cannot pass a lambda name to function() or funcref() Commit: https://github.com/vim/vim/commit/eba3b7f6645c8f856132b4c06a009a3b0a44e21c Author: Bram Moolenaar Date: Tue Nov 30 18:25:08 2021 +0000 patch 8.2.3705: cannot pass a lambda name to function() or funcref() Problem: Cannot pass a lambda name to function() or funcref(). (Yegappan Lakshmanan) Solution: Handle a lambda name differently. diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -3955,9 +3955,8 @@ common_function(typval_T *argvars, typva if ((use_string && vim_strchr(s, AUTOLOAD_CHAR) == NULL) || is_funcref) { name = s; - trans_name = trans_function_name(&name, &is_global, FALSE, - TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD | TFN_NO_DEREF, - NULL, NULL, NULL); + trans_name = save_function_name(&name, &is_global, FALSE, + TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD | TFN_NO_DEREF, NULL); if (*name != NUL) s = NULL; } diff --git a/src/proto/userfunc.pro b/src/proto/userfunc.pro --- a/src/proto/userfunc.pro +++ b/src/proto/userfunc.pro @@ -33,6 +33,7 @@ int call_func(char_u *funcname, int len, 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); +char_u *save_function_name(char_u **name, int *is_global, int skip, int flags, funcdict_T *fudi); void list_functions(regmatch_T *regmatch); ufunc_T *define_function(exarg_T *eap, char_u *name_arg); void ex_function(exarg_T *eap); diff --git a/src/testdir/test_expr.vim b/src/testdir/test_expr.vim --- a/src/testdir/test_expr.vim +++ b/src/testdir/test_expr.vim @@ -547,6 +547,13 @@ func Test_function_with_funcref() call assert_fails("call function('foo()')", 'E475:') call assert_fails("call function('foo()')", 'foo()') call assert_fails("function('')", 'E129:') + + let Len = {s -> strlen(s)} + call assert_equal(6, Len('foobar')) + let name = string(Len) + " can evaluate "function('99')" + call execute('let Ref = ' .. name) + call assert_equal(4, Ref('text')) endfunc func Test_funcref() diff --git a/src/userfunc.c b/src/userfunc.c --- a/src/userfunc.c +++ b/src/userfunc.c @@ -3811,6 +3811,36 @@ untrans_function_name(char_u *name) } /* + * Call trans_function_name(), except that a lambda is returned as-is. + * Returns the name in allocated memory. + */ + char_u * +save_function_name( + char_u **name, + int *is_global, + int skip, + int flags, + funcdict_T *fudi) +{ + char_u *p = *name; + char_u *saved; + + if (STRNCMP(p, "", 8) == 0) + { + p += 8; + (void)getdigits(&p); + saved = vim_strnsave(*name, p - *name); + if (fudi != NULL) + CLEAR_POINTER(fudi); + } + else + saved = trans_function_name(&p, is_global, skip, + flags, fudi, NULL, NULL); + *name = p; + return saved; +} + +/* * List functions. When "regmatch" is NULL all of then. * Otherwise functions matching "regmatch". */ @@ -3950,16 +3980,8 @@ define_function(exarg_T *eap, char_u *na } else { - if (STRNCMP(p, "", 8) == 0) - { - p += 8; - (void)getdigits(&p); - name = vim_strnsave(eap->arg, p - eap->arg); - CLEAR_FIELD(fudi); - } - else - name = trans_function_name(&p, &is_global, eap->skip, - TFN_NO_AUTOLOAD, &fudi, NULL, NULL); + name = save_function_name(&p, &is_global, eap->skip, + TFN_NO_AUTOLOAD, &fudi); paren = (vim_strchr(p, '(') != NULL); if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip) { diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3705, +/**/ 3704, /**/ 3703,