# HG changeset patch # User Bram Moolenaar # Date 1639231203 -3600 # Node ID 7821550ba3a8f7ea5b99ff22d6e2028d226a7a75 # Parent ae12de84377655d851e96649f96ae81ac2df709e patch 8.2.3782: Vim9: no error if a function shadows a script variable Commit: https://github.com/vim/vim/commit/052ff291d72bc9c176f9562f021d7e8e030e74c0 Author: Bram Moolenaar Date: Sat Dec 11 13:54:46 2021 +0000 patch 8.2.3782: Vim9: no error if a function shadows a script variable Problem: Vim9: no error if a function shadows a script variable. Solution: Check the function doesn't shadow a variable. (closes https://github.com/vim/vim/issues/9310) diff --git a/src/evalvars.c b/src/evalvars.c --- a/src/evalvars.c +++ b/src/evalvars.c @@ -2712,7 +2712,7 @@ eval_variable( type = sv->sv_type; } } - else if (in_vim9script()) + else if (in_vim9script() && (flags & EVAL_VAR_NO_FUNC) == 0) { ufunc_T *ufunc = find_func(name, FALSE, NULL); diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -1896,6 +1896,17 @@ def Test_script_var_shadows_function() CheckScriptFailure(lines, 'E1041:', 5) enddef +def Test_function_shadows_script_var() + var lines =<< trim END + vim9script + var Func = 1 + def Func(): number + return 123 + enddef + END + CheckScriptFailure(lines, 'E1041:', 3) +enddef + def Test_script_var_shadows_command() var lines =<< trim END var undo = 1 @@ -2198,7 +2209,7 @@ def Test_func_overrules_import_fails() echo 'local to function' enddef END - CheckScriptFailure(lines, 'E1073:') + CheckScriptFailure(lines, 'E1041:') lines =<< trim END vim9script @@ -2231,7 +2242,7 @@ def Test_func_redefine_fails() vim9script def Foo(): string return 'foo' - enddef + enddef def Func() var Foo = {-> 'lambda'} enddef diff --git a/src/userfunc.c b/src/userfunc.c --- a/src/userfunc.c +++ b/src/userfunc.c @@ -4134,19 +4134,41 @@ define_function(exarg_T *eap, char_u *na || (fudi.fd_di->di_tv.v_type != VAR_FUNC && fudi.fd_di->di_tv.v_type != VAR_PARTIAL))) { + char_u *name_base = arg; + int i; + if (*arg == K_SPECIAL) - j = 3; - else - j = 0; - while (arg[j] != NUL && (j == 0 ? eval_isnamec1(arg[j]) - : eval_isnamec(arg[j]))) - ++j; - if (arg[j] != NUL) + { + name_base = vim_strchr(arg, '_'); + if (name_base == NULL) + name_base = arg + 3; + else + ++name_base; + } + for (i = 0; name_base[i] != NUL && (i == 0 + ? eval_isnamec1(name_base[i]) + : eval_isnamec(name_base[i])); ++i) + ; + if (name_base[i] != NUL) emsg_funcname((char *)e_invarg2, arg); + + // In Vim9 script a function cannot have the same name as a + // variable. + if (vim9script && *arg == K_SPECIAL + && eval_variable(name_base, STRLEN(name_base), NULL, NULL, + EVAL_VAR_NOAUTOLOAD + EVAL_VAR_IMPORT + + EVAL_VAR_NO_FUNC) == OK) + { + semsg(_(e_redefining_script_item_str), name_base); + goto ret_free; + } } // Disallow using the g: dict. if (fudi.fd_dict != NULL && fudi.fd_dict->dv_scope == VAR_DEF_SCOPE) + { emsg(_("E862: Cannot use g: here")); + goto ret_free; + } } // This may get more lines and make the pointers into the first line 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 */ /**/ + 3782, +/**/ 3781, /**/ 3780, diff --git a/src/vim.h b/src/vim.h --- a/src/vim.h +++ b/src/vim.h @@ -2782,6 +2782,7 @@ long elapsed(DWORD start_tick); #define EVAL_VAR_VERBOSE 1 // may give error message #define EVAL_VAR_NOAUTOLOAD 2 // do not use script autoloading #define EVAL_VAR_IMPORT 4 // may return special variable for import +#define EVAL_VAR_NO_FUNC 8 // do not look for a function // Maximum number of characters that can be fuzzy matched #define MAX_FUZZY_MATCHES 256