# HG changeset patch # User Bram Moolenaar # Date 1642706103 -3600 # Node ID 322b79b002b777041698907cfdb73286b25ea6a0 # Parent 06a2610c1661564393fda50fee5f615ad44d9597 patch 8.2.4162: Vim9: no error for redefining function with export Commit: https://github.com/vim/vim/commit/9c7cae66bc21a3dc5c6e60cd64216ce7c9073003 Author: Bram Moolenaar Date: Thu Jan 20 19:10:25 2022 +0000 patch 8.2.4162: Vim9: no error for redefining function with export Problem: Vim9: no error for redefining function with export. Solution: Check for existing function with/without prefix. (closes https://github.com/vim/vim/issues/9577) diff --git a/src/scriptfile.c b/src/scriptfile.c --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -2190,7 +2190,7 @@ get_autoload_prefix(scriptitem_T *si) /* * If in a Vim9 autoload script return "name" with the autoload prefix for the - * script. If successful "name" is freed, the returned name is allocated. + * script. If successful the returned name is allocated. * Otherwise it returns "name" unmodified. */ char_u * @@ -2221,7 +2221,6 @@ may_prefix_autoload(char_u *name) { vim_snprintf((char *)res, len, "%s%s", si->sn_autoload_prefix, basename); - vim_free(name); return res; } } diff --git a/src/testdir/test_vim9_import.vim b/src/testdir/test_vim9_import.vim --- a/src/testdir/test_vim9_import.vim +++ b/src/testdir/test_vim9_import.vim @@ -1440,6 +1440,80 @@ def Test_vim9script_autoload_call() &rtp = save_rtp enddef +def Test_vim9script_autoload_duplicate() + mkdir('Xdir/autoload', 'p') + + var lines =<< trim END + vim9script + + export def Func() + enddef + + def Func() + enddef + END + writefile(lines, 'Xdir/autoload/dupfunc.vim') + assert_fails('source Xdir/autoload/dupfunc.vim', 'E1073:') + + lines =<< trim END + vim9script + + def Func() + enddef + + export def Func() + enddef + END + writefile(lines, 'Xdir/autoload/dup2func.vim') + assert_fails('source Xdir/autoload/dup2func.vim', 'E1073:') + + lines =<< trim END + vim9script + + def Func() + enddef + + export var Func = 'asdf' + END + writefile(lines, 'Xdir/autoload/dup3func.vim') + assert_fails('source Xdir/autoload/dup3func.vim', 'E1041: Redefining script item Func') + + lines =<< trim END + vim9script + + export var Func = 'asdf' + + def Func() + enddef + END + writefile(lines, 'Xdir/autoload/dup4func.vim') + assert_fails('source Xdir/autoload/dup4func.vim', 'E707:') + + lines =<< trim END + vim9script + + var Func = 'asdf' + + export def Func() + enddef + END + writefile(lines, 'Xdir/autoload/dup5func.vim') + assert_fails('source Xdir/autoload/dup5func.vim', 'E707:') + + lines =<< trim END + vim9script + + export def Func() + enddef + + var Func = 'asdf' + END + writefile(lines, 'Xdir/autoload/dup6func.vim') + assert_fails('source Xdir/autoload/dup6func.vim', 'E1041: Redefining script item Func') + + delete('Xdir', 'rf') +enddef + def Test_import_autoload_postponed() mkdir('Xdir/autoload', 'p') var save_rtp = &rtp diff --git a/src/userfunc.c b/src/userfunc.c --- a/src/userfunc.c +++ b/src/userfunc.c @@ -1911,6 +1911,12 @@ find_func_with_prefix(char_u *name, int { size_t len = STRLEN(si->sn_autoload_prefix) + STRLEN(name) + 1; char_u *auto_name; + char_u *namep; + + // skip a "99_" prefix + namep = untrans_function_name(name); + if (namep == NULL) + namep = name; // An exported function in an autoload script is stored as // "dir#path#name". @@ -1921,7 +1927,7 @@ find_func_with_prefix(char_u *name, int if (auto_name != NULL) { vim_snprintf((char *)auto_name, len, "%s%s", - si->sn_autoload_prefix, name); + si->sn_autoload_prefix, namep); hi = hash_find(&func_hashtab, auto_name); if (auto_name != buffer) vim_free(auto_name); @@ -4175,7 +4181,15 @@ define_function(exarg_T *eap, char_u *na // is stored with the legacy autoload name "dir#script#FuncName" so // that it can also be found in legacy script. if (is_export && name != NULL) - name = may_prefix_autoload(name); + { + char_u *prefixed = may_prefix_autoload(name); + + if (prefixed != NULL && prefixed != name) + { + vim_free(name); + name = prefixed; + } + } } // An error in a function call during evaluation of an expression in magic @@ -4447,20 +4461,53 @@ define_function(exarg_T *eap, char_u *na if (fudi.fd_dict == NULL) { hashtab_T *ht; + char_u *find_name = name; + int var_conflict = FALSE; v = find_var(name, &ht, TRUE); - if (v != NULL && v->di_tv.v_type == VAR_FUNC) + if (v != NULL) + var_conflict = TRUE; + + if (SCRIPT_ID_VALID(current_sctx.sc_sid)) + { + scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); + + if (si->sn_autoload_prefix != NULL) + { + if (is_export) + { + find_name = name + STRLEN(si->sn_autoload_prefix); + v = find_var(find_name, &ht, TRUE); + if (v != NULL) + var_conflict = TRUE; + } + else + { + char_u *prefixed = may_prefix_autoload(name); + + if (prefixed != NULL) + { + v = find_var(prefixed, &ht, TRUE); + if (v != NULL) + var_conflict = TRUE; + vim_free(prefixed); + } + } + } + } + if (var_conflict) { emsg_funcname(e_function_name_conflicts_with_variable_str, name); goto erret; } - fp = find_func_even_dead(name, is_global); + fp = find_func_even_dead(find_name, is_global); if (vim9script) { char_u *uname = untrans_function_name(name); - import = find_imported(uname == NULL ? name : uname, 0, FALSE, NULL); + import = find_imported(uname == NULL ? name : uname, 0, + FALSE, NULL); } if (fp != NULL || import != NULL) diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4162, +/**/ 4161, /**/ 4160,