patch 9.2.0265: unnecessary restrictions for defining dictionary function names

Commit: 
https://github.com/vim/vim/commit/f89662722d3c4b97d55f32ca88a895f246405059
Author: thinca <[email protected]>
Date:   Sat Mar 28 10:07:27 2026 +0000

    patch 9.2.0265: unnecessary restrictions for defining dictionary function 
names
    
    Problem:  unnecessary restrictions for defining dictionary function
              names
    Solution: Allow defining dict function with bracket key that is not a
              valid identifier (thinca)
    
    In Vim script, "function obj.func()" and "function obj['func']()" both
    define a dictionary function.  However, the bracket form required the
    key to match function naming rules (eval_isnamec), so
    "function obj['foo-bar']()" failed with E475.
    
    Assigning and calling already work: "let obj['foo-bar'] = obj.func"
    and "call obj['foo-bar']()" are valid.  Only the definition was
    incorrectly restricted.
    
    Skip the identifier check when the name comes from fd_newkey (i.e. the
    key was given in bracket notation).  Dictionary keys may be any string.
    
    Supported by AI
    
    closes: #19833
    
    Signed-off-by: thinca <[email protected]>
    Signed-off-by: Yegappan Lakshmanan <[email protected]>
    Signed-off-by: Christian Brabandt <[email protected]>

diff --git a/src/testdir/test_user_func.vim b/src/testdir/test_user_func.vim
index d12ad8e40..56b21a481 100644
--- a/src/testdir/test_user_func.vim
+++ b/src/testdir/test_user_func.vim
@@ -584,6 +584,18 @@ func Test_func_dict()
   call assert_fails('call mydict.nonexist()', 'E716:')
 endfunc
 
+func Test_func_dict_bracket_key()
+  " Dictionary function can be defined with bracket notation using a key
+  " that does not follow function naming rules (e.g. containing a hyphen).
+  let obj = {}
+  function obj['foo-bar']() dict
+    return self.value
+  endfunction
+  let obj.value = 42
+  call assert_equal(42, obj['foo-bar']())
+  call assert_equal(42, call(obj['foo-bar'], []))
+endfunc
+
 func Test_func_range()
   new
   call setline(1, range(1, 8))
diff --git a/src/userfunc.c b/src/userfunc.c
index 9de6bdbaf..e861a9eac 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -5253,33 +5253,40 @@ define_function(
            char_u  *name_base = arg;
            int     i;
 
-           if (*arg == K_SPECIAL)
+           // When defining a dictionary function with bracket notation
+           // (e.g. obj['foo-bar']()), the key is a dictionary key and is not
+           // required to follow function naming rules.  Skip the identifier
+           // check in that case.
+           if (arg != fudi.fd_newkey)
            {
-               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(e_invalid_argument_str, arg);
-               goto ret_free;
-           }
+               if (*arg == K_SPECIAL)
+               {
+                   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(e_invalid_argument_str, arg);
+                   goto ret_free;
+               }
 
-           // In Vim9 script a function cannot have the same name as a
-           // variable.
-           if (vim9script && *arg == K_SPECIAL
-               && eval_variable(name_base, i, 0, NULL,
-                   NULL, EVAL_VAR_NOAUTOLOAD + EVAL_VAR_IMPORT
+               // In Vim9 script a function cannot have the same name as a
+               // variable.
+               if (vim9script && *arg == K_SPECIAL
+                   && eval_variable(name_base, i, 0, NULL,
+                       NULL, EVAL_VAR_NOAUTOLOAD + EVAL_VAR_IMPORT
                                                     + EVAL_VAR_NO_FUNC) == OK)
-           {
-               semsg(_(e_redefining_script_item_str), name_base);
-               goto ret_free;
+               {
+                   semsg(_(e_redefining_script_item_str), name_base);
+                   goto ret_free;
+               }
            }
        }
        // Disallow using the g: dict.
diff --git a/src/version.c b/src/version.c
index c63416ee5..775a09daa 100644
--- a/src/version.c
+++ b/src/version.c
@@ -734,6 +734,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    265,
 /**/
     264,
 /**/

-- 
-- 
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 visit 
https://groups.google.com/d/msgid/vim_dev/E1w6Qh7-009wCw-6J%40256bit.org.

Raspunde prin e-mail lui