]> granicus.if.org Git - vim/commitdiff
patch 8.2.1812: Vim9: nested closure throws an internal error v8.2.1812
authorBram Moolenaar <Bram@vim.org>
Wed, 7 Oct 2020 17:08:04 +0000 (19:08 +0200)
committerBram Moolenaar <Bram@vim.org>
Wed, 7 Oct 2020 17:08:04 +0000 (19:08 +0200)
Problem:    Vim9: nested closure throws an internal error.
Solution:   Do not skip a local variable with a partial. (closes #7065)

src/testdir/test_vim9_func.vim
src/version.c
src/vim9execute.c

index f3352453fe9557e6ba781f547a1d3e661d078bb5..c3687cf20aacb6fc6c48ce4c47a576e78ff68c08 100644 (file)
@@ -1388,6 +1388,20 @@ def Test_double_closure_fails()
   CheckScriptSuccess(lines)
 enddef
 
+def Test_nested_closure_used()
+  var lines =<< trim END
+      vim9script
+      def Func()
+        var x = 'hello'
+        var Closure = {-> x}
+        g:Myclosure = {-> Closure()}
+      enddef
+      Func()
+      assert_equal('hello', g:Myclosure())
+  END
+  CheckScriptSuccess(lines)
+enddef
+
 def Test_nested_closure_fails()
   var lines =<< trim END
     vim9script
index a2929bc3f79daa0e8933763edce77e6d65f709fa..1c8629dd80c6c0cb4a3e33fae58345c256edc240 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1812,
 /**/
     1811,
 /**/
index 7afc5c27cdec53d5cd73e69374601191f68ed026..2387ac9061e744863f05832139f98163b96fb96d 100644 (file)
@@ -377,10 +377,11 @@ handle_closure_in_use(ectx_T *ectx, int free_arguments)
            tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE + idx);
 
            // Do not copy a partial created for a local function.
-           // TODO: this won't work if the closure actually uses it.  But when
+           // TODO: This won't work if the closure actually uses it.  But when
            // keeping it it gets complicated: it will create a reference cycle
            // inside the partial, thus needs special handling for garbage
            // collection.
+           // For now, decide on the reference count.
            if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL)
            {
                int i;
@@ -389,7 +390,8 @@ handle_closure_in_use(ectx_T *ectx, int free_arguments)
                {
                    partial_T *pt = ((partial_T **)gap->ga_data)[gap->ga_len
                                                          - closure_count + i];
-                   if (tv->vval.v_partial == pt)
+
+                   if (tv->vval.v_partial == pt && pt->pt_refcount < 2)
                        break;
                }
                if (i < closure_count)