Commit: patch 9.2.0878: Vim9: cannot use a script variable of an enclosing block in a lambda

Christian Brabandt <[email protected]> Thu, 30 Jul 2026 21:00:06 +0200
Newsgroups gmane.editors.vim.devel
Message-ID <[email protected]>
patch 9.2.0878: Vim9: cannot use a script variable of an enclosing block in a lambda

Commit: https://github.com/vim/vim/commit/ce55a4910dc7a1de95d828ddce916d2d2bd4d6d6
Author: Hirohito Higashi <[email protected]>
Date:   Thu Jul 30 18:49:22 2026 +0000

    patch 9.2.0878: Vim9: cannot use a script variable of an enclosing block in a lambda
    
    Problem:  Vim9: E1001 when a lambda inside a :def function uses a script
              variable that was declared in an enclosing block, while the :def
              function itself can use it (neoharju)
    Solution: Copy the block scope IDs to the lambda, like it is done for a
              nested function (Hirohito Higashi).
    
    fixes:  #20876
    closes: #PR
    
    Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
    Signed-off-by: Hirohito Higashi <[email protected]>
    Signed-off-by: Christian Brabandt <[email protected]>

diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index 91873845d..b86acd071 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -449,6 +449,24 @@ def Test_block_local_vars_with_func()
       assert_equal(['foo', 'bar'], Func())
   END
   v9.CheckScriptSuccess(lines)
+
+  # also when the variables are used in a lambda inside the function
+  lines =<< trim END
+      vim9script
+      if true
+        var foo = 'foo'
+        if true
+          var bar = 'bar'
+          def Func(): list<string>
+            var Lambda = () => [foo, bar]
+            return Lambda()
+          enddef
+          defcompile
+        endif
+      endif
+      assert_equal(['foo', 'bar'], Func())
+  END
+  v9.CheckScriptSuccess(lines)
 enddef
 
 " legacy func for command that's defined later
diff --git a/src/version.c b/src/version.c
index 3fba5845f..0e5c697ec 100644
--- a/src/version.c
+++ b/src/version.c
@@ -758,6 +758,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    878,
 /**/
     877,
 /**/
diff --git a/src/vim9expr.c b/src/vim9expr.c
index f69488d5b..7f47d82fb 100644
--- a/src/vim9expr.c
+++ b/src/vim9expr.c
@@ -1795,10 +1795,27 @@ compile_lambda(char_u **arg, cctx_T *cctx)
     clear_tv(&rettv);
 
     if (cctx->ctx_ufunc != NULL)
+    {
 	// This lambda might be defined in a class method.  Inherit the class
 	// from the current function.
 	ufunc->uf_defclass = cctx->ctx_ufunc->uf_defclass;
 
+	// Copy over the block scope IDs, so that a script variable declared in
+	// an enclosing block can be found.
+	int block_depth = cctx->ctx_ufunc->uf_block_depth;
+
+	if (block_depth > 0)
+	{
+	    ufunc->uf_block_ids = ALLOC_MULT(int, block_depth);
+	    if (ufunc->uf_block_ids != NULL)
+	    {
+		mch_memmove(ufunc->uf_block_ids, cctx->ctx_ufunc->uf_block_ids,
+						    sizeof(int) * block_depth);
+		ufunc->uf_block_depth = block_depth;
+	    }
+	}
+    }
+
     // Compile it here to get the return type.  The return type is optional,
     // when it's missing use t_unknown.  This is recognized in
     // compile_return().

-- 
-- 
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/E1wpVzC-004Zfc-6i%40256bit.org.