patch 9.1.1882: Vim9: Not able to use a lambda with :defer

Commit: 
https://github.com/vim/vim/commit/21ef3c6e5972bbe8ab61195f98ccb85048b78985
Author: Yegappan Lakshmanan <[email protected]>
Date:   Mon Oct 27 18:07:52 2025 +0000

    patch 9.1.1882: Vim9: Not able to use a lambda with :defer
    
    Problem:  Vim9: Not able to use a lambda with :defer
              (Maxim Kim)
    Solution: Add support for this (Yegappan Lakshmanan)
    
    fixes: #18626
    closes: #18643
    
    Signed-off-by: Yegappan Lakshmanan <[email protected]>
    Signed-off-by: Christian Brabandt <[email protected]>

diff --git a/runtime/doc/userfunc.txt b/runtime/doc/userfunc.txt
index 5b3605a14..0f008446e 100644
--- a/runtime/doc/userfunc.txt
+++ b/runtime/doc/userfunc.txt
@@ -1,4 +1,4 @@
-*userfunc.txt* For Vim version 9.1.  Last change: 2025 Oct 12
+*userfunc.txt* For Vim version 9.1.  Last change: 2025 Oct 27
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -449,6 +449,15 @@ or altering execution outside of deferred functions.
 No range is accepted.  The function can be a partial with extra arguments, but
 not with a dictionary. *E1300*
 
+In a |:def| function, a lambda can be used with |:defer|.  Example: >
+
+    def Fn()
+      set lazyredraw
+      defer () => {
+        set lazyredraw&
+      }()
+    enddef
+<
 ==============================================================================
 
 4. Automatically loading functions ~
diff --git a/src/proto/vim9expr.pro b/src/proto/vim9expr.pro
index 58c79fc02..4de143917 100644
--- a/src/proto/vim9expr.pro
+++ b/src/proto/vim9expr.pro
@@ -7,6 +7,7 @@ int compile_load(char_u **arg, size_t namelen, char_u *end_arg, 
cctx_T *cctx, in
 int compile_arguments(char_u **arg, cctx_T *cctx, int *argcount, ca_special_T 
special_fn);
 char_u *to_name_end(char_u *arg, int use_namespace);
 char_u *to_name_const_end(char_u *arg);
+int compile_lambda(char_u **arg, cctx_T *cctx);
 int get_lambda_tv_and_compile(char_u **arg, typval_T *rettv, int 
types_optional, evalarg_T *evalarg);
 exprtype_T get_compare_type(char_u *p, int *len, int *type_is);
 void skip_expr_cctx(char_u **arg, cctx_T *cctx);
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index 40832a606..0134956c3 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -5249,6 +5249,102 @@ def Test_defer_lambda_funcref()
   v9.CheckSourceSuccess(lines)
 enddef
 
+" Test for using defer with a lambda and a command block
+def Test_defer_lambda_func()
+  var lines =<< trim END
+    vim9script
+    var result = ''
+    def Foo()
+      result = 'xxx'
+      defer (a: number, b: string): number => {
+        result = $'{a}:{b}'
+        return 0
+      }(10, 'aaa')
+      result = 'yyy'
+    enddef
+    Foo()
+    assert_equal('10:aaa', result)
+  END
+  v9.CheckScriptSuccess(lines)
+
+  # Error: argument type mismatch
+  lines =<< trim END
+    vim9script
+    def Foo()
+      defer (a: number, b: string): number => {
+        return 0
+      }(10, 20)
+    enddef
+    defcompile
+  END
+  v9.CheckScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected 
string but got number', 1)
+
+  # Error: not enough arguments
+  lines =<< trim END
+    vim9script
+    def Foo()
+      defer (a: number) => {
+      }()
+    enddef
+    defcompile
+  END
+  v9.CheckScriptFailure(lines, 'E119: Not enough arguments for function: (a: 
number) => {', 1)
+
+  # Error: too many arguments
+  lines =<< trim END
+    vim9script
+    def Foo()
+      defer () => {
+      }(10)
+    enddef
+    defcompile
+  END
+  v9.CheckScriptFailure(lines, 'E118: Too many arguments for function: () => 
{', 1)
+
+  # Error: invalid command in command-block
+  lines =<< trim END
+    vim9script
+    def Foo()
+      defer () => {
+        xxx
+      }()
+    enddef
+    defcompile
+  END
+  v9.CheckScriptFailure(lines, 'E476: Invalid command: xxx', 1)
+
+  # Error: missing return
+  lines =<< trim END
+    vim9script
+    def Foo()
+      defer (): number => {
+      }()
+    enddef
+    defcompile
+  END
+  v9.CheckScriptFailure(lines, 'E1027: Missing return statement', 1)
+
+  # Error: missing lambda body
+  lines =<< trim END
+    vim9script
+    def Foo()
+      defer (a: number): number
+    enddef
+    defcompile
+  END
+  v9.CheckScriptFailure(lines, 'E1028: Compiling :def function failed', 1)
+
+  # Error: invalid lambda syntax
+  lines =<< trim END
+    vim9script
+    def Foo()
+      defer (
+    enddef
+    defcompile
+  END
+  v9.CheckScriptFailure(lines, 'E1028: Compiling :def function failed', 1)
+enddef
+
 " Test for using an non-existing type in a "for" statement.
 def Test_invalid_type_in_for()
   var lines =<< trim END
diff --git a/src/version.c b/src/version.c
index b837e88f7..ed9059da4 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1882,
 /**/
     1881,
 /**/
diff --git a/src/vim9cmds.c b/src/vim9cmds.c
index fb9f78137..684d2ee66 100644
--- a/src/vim9cmds.c
+++ b/src/vim9cmds.c
@@ -2040,25 +2040,35 @@ compile_defer(char_u *arg_start, cctx_T *cctx)
     int                argcount = 0;
     int                defer_var_idx;
     type_T     *type = NULL;
-    int                func_idx;
+    int                func_idx = -1;
 
-    // Get a funcref for the function name.
-    // TODO: better way to find the "(".
-    paren = vim_strchr(arg, '(');
-    if (paren == NULL)
+    if (*arg == '(')
     {
-       semsg(_(e_missing_parenthesis_str), arg);
-       return NULL;
+       // a lambda function
+       if (compile_lambda(&arg, cctx) != OK)
+           return NULL;
+       paren = arg;
+    }
+    else
+    {
+       // Get a funcref for the function name.
+       // TODO: better way to find the "(".
+       paren = vim_strchr(arg, '(');
+       if (paren == NULL)
+       {
+           semsg(_(e_missing_parenthesis_str), arg);
+           return NULL;
+       }
+       *paren = NUL;
+       func_idx = find_internal_func(arg);
+       if (func_idx >= 0)
+           // TODO: better type
+           generate_PUSHFUNC(cctx, (char_u *)internal_func_name(func_idx),
+                   &t_func_any, FALSE);
+       else if (compile_expr0(&arg, cctx) == FAIL)
+           return NULL;
+       *paren = '(';
     }
-    *paren = NUL;
-    func_idx = find_internal_func(arg);
-    if (func_idx >= 0)
-       // TODO: better type
-       generate_PUSHFUNC(cctx, (char_u *)internal_func_name(func_idx),
-                                                          &t_func_any, FALSE);
-    else if (compile_expr0(&arg, cctx) == FAIL)
-       return NULL;
-    *paren = '(';
 
     // check for function type
     if (cctx->ctx_skip != SKIP_YES)
diff --git a/src/vim9expr.c b/src/vim9expr.c
index ab14afc33..f692eeff3 100644
--- a/src/vim9expr.c
+++ b/src/vim9expr.c
@@ -1747,7 +1747,7 @@ compile_tuple(
  * "*arg" points to the '('.
  * Returns OK/FAIL when a lambda is recognized, NOTDONE if it's not a lambda.
  */
-    static int
+    int
 compile_lambda(char_u **arg, cctx_T *cctx)
 {
     int                r;

-- 
-- 
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/E1vDRkH-00662u-C0%40256bit.org.

Raspunde prin e-mail lui