]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0878: Vim9: cannot use a script variable of an enclosing block in a lambda v9.2.0878
authorHirohito Higashi <h.east.727@gmail.com>
Thu, 30 Jul 2026 18:49:22 +0000 (18:49 +0000)
committerChristian Brabandt <cb@256bit.org>
Thu, 30 Jul 2026 18:49:22 +0000 (18:49 +0000)
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) <noreply@anthropic.com>
Signed-off-by: Hirohito Higashi <h.east.727@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/testdir/test_vim9_script.vim
src/version.c
src/vim9expr.c

index 91873845d83b638469c5f325ab21e3654be2963f..b86acd071ea01f09203cf5871f6e0eeff3d99283 100644 (file)
@@ -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
index 3fba5845f92da02d74c189b92b6f9a84c23795b7..0e5c697ec9180ae8dc1da6c62203d41b2396b791 100644 (file)
@@ -758,6 +758,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    878,
 /**/
     877,
 /**/
index f69488d5bdbf899e1f218de6ca363c1b11e28c86..7f47d82fb664513f3a9b0c8202c333ac80951ee5 100644 (file)
@@ -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().