# HG changeset patch # User Bram Moolenaar # Date 1616781604 -3600 # Node ID 3058ed6db36fdefc4992e684e062c8a5cd92fe22 # Parent 5b44b43998292f57e6730b3581e3963d83c249b4 patch 8.2.2657: Vim9: error message for declaring variable in for loop Commit: https://github.com/vim/vim/commit/522eefd9a247c574a51bfe9bf73467a8dc3bac42 Author: Bram Moolenaar Date: Fri Mar 26 18:49:22 2021 +0100 patch 8.2.2657: Vim9: error message for declaring variable in for loop Problem: Vim9: error message for declaring variable in for loop. Solution: Clear variables when entering block again. (closes https://github.com/vim/vim/issues/8012) diff --git a/src/ex_eval.c b/src/ex_eval.c --- a/src/ex_eval.c +++ b/src/ex_eval.c @@ -1154,6 +1154,32 @@ ex_while(exarg_T *eap) ++cstack->cs_looplevel; cstack->cs_line[cstack->cs_idx] = -1; } + else + { + if (in_vim9script() && SCRIPT_ID_VALID(current_sctx.sc_sid)) + { + scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); + int i; + + // Any variables defined in the previous round are no longer + // visible. + for (i = cstack->cs_script_var_len[cstack->cs_idx]; + i < si->sn_var_vals.ga_len; ++i) + { + svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + i; + + // sv_name is set to NULL if it was already removed. This + // happens when it was defined in an inner block and no + // functions were defined there. + if (sv->sv_name != NULL) + // Remove a variable declared inside the block, if it + // still exists, from sn_vars. + hide_script_var(si, i, FALSE); + } + cstack->cs_script_var_len[cstack->cs_idx] = + si->sn_var_vals.ga_len; + } + } cstack->cs_flags[cstack->cs_idx] = eap->cmdidx == CMD_while ? CSF_WHILE : CSF_FOR; @@ -1175,6 +1201,9 @@ ex_while(exarg_T *eap) void *fi; evalarg_T evalarg; + /* + * ":for var in list-expr" + */ CLEAR_FIELD(evalarg); evalarg.eval_flags = skip ? 0 : EVAL_EVALUATE; if (getline_equal(eap->getline, eap->cookie, getsourceline)) @@ -1183,9 +1212,6 @@ ex_while(exarg_T *eap) evalarg.eval_cookie = eap->cookie; } - /* - * ":for var in list-expr" - */ if ((cstack->cs_lflags & CSL_HAD_LOOP) != 0) { // Jumping here from a ":continue" or ":endfor": use the @@ -1384,10 +1410,8 @@ ex_endwhile(exarg_T *eap) && dbg_check_skipped(eap)) (void)do_intthrow(cstack); - /* - * Set loop flag, so do_cmdline() will jump back to the matching - * ":while" or ":for". - */ + // Set loop flag, so do_cmdline() will jump back to the matching + // ":while" or ":for". cstack->cs_lflags |= CSL_HAD_ENDLOOP; } } diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -2263,6 +2263,13 @@ def Test_for_outside_of_function() endfor assert_equal(['', '0', '1', '2', '3'], getline(1, '$')) bwipe! + + var result = '' + for i in [1, 2, 3] + var loop = ' loop ' .. i + result ..= loop + endfor + assert_equal(' loop 1 loop 2 loop 3', result) END writefile(lines, 'Xvim9for.vim') source Xvim9for.vim diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2657, +/**/ 2656, /**/ 2655,