summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2022-09-21 18:59:14 +0100
committerBram Moolenaar <Bram@vim.org>2022-09-21 18:59:14 +0100
commite8e369a796e110760d033e937b40c84e0c5e8b36 (patch)
treeaaf71aeb71f9bf17a914a8c56322394fe6f30484
parentec5e1483ebda577e0b7f638c485203cd0e479c47 (diff)
downloadvim-git-e8e369a796e110760d033e937b40c84e0c5e8b36.tar.gz
patch 9.0.0535: closure gets wrong value in for loop with two loop variablesv9.0.0535
Problem: Closure gets wrong value in for loop with two loop variables. Solution: Correctly compute the number of loop variables to clear.
-rw-r--r--src/evalvars.c4
-rw-r--r--src/ex_eval.c10
-rw-r--r--src/structs.h2
-rw-r--r--src/testdir/test_vim9_script.vim21
-rw-r--r--src/version.c2
5 files changed, 34 insertions, 5 deletions
diff --git a/src/evalvars.c b/src/evalvars.c
index e4cf40945..3c5b28a98 100644
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -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);
}
/*
diff --git a/src/ex_eval.c b/src/ex_eval.c
index 9afcb5694..5721b766e 100644
--- a/src/ex_eval.c
+++ b/src/ex_eval.c
@@ -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;
diff --git a/src/structs.h b/src/structs.h
index e46446d4d..19dc55075 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -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
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index 3ee7e2e83..54b4ea16d 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -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()
diff --git a/src/version.c b/src/version.c
index 1b1628e6f..f7ef299ea 100644
--- a/src/version.c
+++ b/src/version.c
@@ -700,6 +700,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 535,
+/**/
534,
/**/
533,