]> granicus.if.org Git - vim/commitdiff
patch 9.0.0535: closure gets wrong value in for loop with two loop variables v9.0.0535
authorBram Moolenaar <Bram@vim.org>
Wed, 21 Sep 2022 17:59:14 +0000 (18:59 +0100)
committerBram Moolenaar <Bram@vim.org>
Wed, 21 Sep 2022 17:59:14 +0000 (18:59 +0100)
Problem:    Closure gets wrong value in for loop with two loop variables.
Solution:   Correctly compute the number of loop variables to clear.

src/evalvars.c
src/ex_eval.c
src/structs.h
src/testdir/test_vim9_script.vim
src/version.c

index e4cf40945ae053bbd4b29afacf7ed767e9ce6a89..3c5b28a982c9db7ac256589da8b4fd5cd06d961d 100644 (file)
@@ -1315,8 +1315,8 @@ skip_var_list(
        }
        return p + 1;
     }
-    else
-       return skip_var_one(arg, include_type);
+    return skip_var_one(arg, include_type);
 }
 
 /*
index 9afcb56940a74ae818735962c74e9f9500085b7b..5721b766ee541d43e6d2a75fb795440b2eb00e6a 100644 (file)
@@ -1240,8 +1240,14 @@ ex_while(exarg_T *eap)
                // variable that we reuse every time around.
                // Do this backwards, so that vars defined in a later round are
                // found first.
-               first = cstack->cs_script_var_len[cstack->cs_idx]
-                                         + (eap->cmdidx == CMD_while ? 0 : 1);
+               first = cstack->cs_script_var_len[cstack->cs_idx];
+               if (eap->cmdidx == CMD_for)
+               {
+                   forinfo_T   *fi = cstack->cs_forinfo[cstack->cs_idx];
+
+                   first += fi == NULL || fi->fi_varcount == 0
+                                                        ? 1 : fi->fi_varcount;
+               }
                for (i = si->sn_var_vals.ga_len - 1; i >= first; --i)
                {
                    svar_T      *sv = ((svar_T *)si->sn_var_vals.ga_data) + i;
index e46446d4d4ee5eb0d02ad6e7f2f35100c4f0ac6e..19dc5507513999cb169c90f1a5ea364f2cfc2d6b 100644 (file)
@@ -1630,7 +1630,7 @@ typedef struct svar_S svar_T;
 typedef struct
 {
     int                fi_semicolon;   // TRUE if ending in '; var]'
-    int                fi_varcount;    // nr of variables in the list
+    int                fi_varcount;    // nr of variables in [] or zero
     int                fi_break_count; // nr of line breaks encountered
     listwatch_T        fi_lw;          // keep an eye on the item used.
     list_T     *fi_list;       // list being used
index 3ee7e2e8322ef9938fb397facf484fa8ad37d9f1..54b4ea16d06282199d6d39c44ae194317191800d 100644 (file)
@@ -2323,6 +2323,27 @@ def Test_for_loop_with_closure()
       endfor
   END
   v9.CheckDefAndScriptSuccess(lines)
+
+  # using two loop variables
+  lines =<< trim END
+      var lv_list: list<func>
+      var copy_list: list<func>
+      for [idx, c] in items('word')
+        var lidx = idx
+        var lc = c
+        lv_list[idx] = () => {
+              return idx .. c
+            }
+        copy_list[idx] = () => {
+              return lidx .. lc
+            }
+      endfor
+      for [i, c] in items('word')
+        assert_equal(3 .. 'd', lv_list[i]())
+        assert_equal(i .. c, copy_list[i]())
+      endfor
+  END
+  v9.CheckDefAndScriptSuccess(lines)
 enddef
 
 def Test_define_global_closure_in_loops()
index 1b1628e6fd8b74c39fe60ecec42de2200c350885..f7ef299eabae6e3163138e6e6864828338470c6c 100644 (file)
@@ -699,6 +699,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    535,
 /**/
     534,
 /**/