diff options
author | Bram Moolenaar <Bram@vim.org> | 2022-09-21 18:59:14 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2022-09-21 18:59:14 +0100 |
commit | e8e369a796e110760d033e937b40c84e0c5e8b36 (patch) | |
tree | aaf71aeb71f9bf17a914a8c56322394fe6f30484 | |
parent | ec5e1483ebda577e0b7f638c485203cd0e479c47 (diff) | |
download | vim-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.c | 4 | ||||
-rw-r--r-- | src/ex_eval.c | 10 | ||||
-rw-r--r-- | src/structs.h | 2 | ||||
-rw-r--r-- | src/testdir/test_vim9_script.vim | 21 | ||||
-rw-r--r-- | src/version.c | 2 |
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, |