To: vim_dev@googlegroups.com Subject: Patch 9.0.0724 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 9.0.0724 Problem: Closure in compiled function gets same variable in block. Solution: At the end of a block to not always reset the variable count. (issue #11094) Files: src/vim9cmds.c, src/vim9compile.c, src/testdir/test_vim9_script.vim *** ../vim-9.0.0723/src/vim9cmds.c 2022-10-07 14:31:04.324852691 +0100 --- src/vim9cmds.c 2022-10-11 20:00:20.196554673 +0100 *************** *** 57,78 **** } /* * Remove local variables above "new_top". */ static void ! unwind_locals(cctx_T *cctx, int new_top) { if (cctx->ctx_locals.ga_len > new_top) ! { ! int idx; ! lvar_T *lvar; ! ! for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx) { ! lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx; ! vim_free(lvar->lv_name); } ! } ! cctx->ctx_locals.ga_len = new_top; } /* --- 57,76 ---- } /* * Remove local variables above "new_top". + * Do this by clearing the name. If "keep" is TRUE do not reset the length, a + * closure may still need location of the variable. */ static void ! unwind_locals(cctx_T *cctx, int new_top, int keep) { if (cctx->ctx_locals.ga_len > new_top) ! for (int idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx) { ! lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx; ! VIM_CLEAR(lvar->lv_name); } ! if (!keep) ! cctx->ctx_locals.ga_len = new_top; } /* *************** *** 81,87 **** void free_locals(cctx_T *cctx) { ! unwind_locals(cctx, 0); ga_clear(&cctx->ctx_locals); } --- 79,85 ---- void free_locals(cctx_T *cctx) { ! unwind_locals(cctx, 0, FALSE); ga_clear(&cctx->ctx_locals); } *************** *** 525,531 **** emsg(_(e_elseif_without_if)); return NULL; } ! unwind_locals(cctx, scope->se_local_count); if (!cctx->ctx_had_return) scope->se_u.se_if.is_had_return = FALSE; --- 523,529 ---- emsg(_(e_elseif_without_if)); return NULL; } ! unwind_locals(cctx, scope->se_local_count, TRUE); if (!cctx->ctx_had_return) scope->se_u.se_if.is_had_return = FALSE; *************** *** 672,678 **** emsg(_(e_else_without_if)); return NULL; } ! unwind_locals(cctx, scope->se_local_count); if (!cctx->ctx_had_return) scope->se_u.se_if.is_had_return = FALSE; scope->se_u.se_if.is_seen_else = TRUE; --- 670,676 ---- emsg(_(e_else_without_if)); return NULL; } ! unwind_locals(cctx, scope->se_local_count, TRUE); if (!cctx->ctx_had_return) scope->se_u.se_if.is_had_return = FALSE; scope->se_u.se_if.is_seen_else = TRUE; *************** *** 744,750 **** return NULL; } ifscope = &scope->se_u.se_if; ! unwind_locals(cctx, scope->se_local_count); if (!cctx->ctx_had_return) ifscope->is_had_return = FALSE; --- 742,748 ---- return NULL; } ifscope = &scope->se_u.se_if; ! unwind_locals(cctx, scope->se_local_count, TRUE); if (!cctx->ctx_had_return) ifscope->is_had_return = FALSE; *************** *** 1122,1128 **** if (compile_loop_end(&forscope->fs_loop_info, cctx) == FAIL) return NULL; ! unwind_locals(cctx, scope->se_local_count); // At end of ":for" scope jump back to the FOR instruction. generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label); --- 1120,1126 ---- if (compile_loop_end(&forscope->fs_loop_info, cctx) == FAIL) return NULL; ! unwind_locals(cctx, scope->se_local_count, FALSE); // At end of ":for" scope jump back to the FOR instruction. generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label); *************** *** 1249,1255 **** if (compile_loop_end(&whilescope->ws_loop_info, cctx) == FAIL) return NULL; ! unwind_locals(cctx, scope->se_local_count); #ifdef FEAT_PROFILE // count the endwhile before jumping --- 1247,1253 ---- if (compile_loop_end(&whilescope->ws_loop_info, cctx) == FAIL) return NULL; ! unwind_locals(cctx, scope->se_local_count, FALSE); #ifdef FEAT_PROFILE // count the endwhile before jumping *************** *** 1471,1477 **** scope_T *scope = cctx->ctx_scope; cctx->ctx_scope = scope->se_outer; ! unwind_locals(cctx, scope->se_local_count); vim_free(scope); } --- 1469,1475 ---- scope_T *scope = cctx->ctx_scope; cctx->ctx_scope = scope->se_outer; ! unwind_locals(cctx, scope->se_local_count, TRUE); vim_free(scope); } *** ../vim-9.0.0723/src/vim9compile.c 2022-10-07 22:46:03.686771713 +0100 --- src/vim9compile.c 2022-10-11 19:52:34.337582559 +0100 *************** *** 47,53 **** for (idx = 0; idx < cctx->ctx_locals.ga_len; ++idx) { lvp = ((lvar_T *)cctx->ctx_locals.ga_data) + idx; ! if (STRNCMP(name, lvp->lv_name, len) == 0 && STRLEN(lvp->lv_name) == len) { if (lvar != NULL) --- 47,54 ---- for (idx = 0; idx < cctx->ctx_locals.ga_len; ++idx) { lvp = ((lvar_T *)cctx->ctx_locals.ga_data) + idx; ! if (lvp->lv_name != NULL ! && STRNCMP(name, lvp->lv_name, len) == 0 && STRLEN(lvp->lv_name) == len) { if (lvar != NULL) *** ../vim-9.0.0723/src/testdir/test_vim9_script.vim 2022-10-09 12:55:29.590190644 +0100 --- src/testdir/test_vim9_script.vim 2022-10-11 19:59:02.936709740 +0100 *************** *** 2314,2319 **** --- 2314,2349 ---- END v9.CheckDefAndScriptSuccess(lines) + # also with an extra block level + lines =<< trim END + var flist: list + for i in range(5) + { + var inloop = i + flist[i] = () => inloop + } + endfor + for i in range(5) + assert_equal(i, flist[i]()) + endfor + END + v9.CheckDefAndScriptSuccess(lines) + + # and declaration in higher block + lines =<< trim END + var flist: list + for i in range(5) + var inloop = i + { + flist[i] = () => inloop + } + endfor + for i in range(5) + assert_equal(i, flist[i]()) + endfor + END + v9.CheckDefAndScriptSuccess(lines) + lines =<< trim END var flist: list for i in range(5) *** ../vim-9.0.0723/src/version.c 2022-10-11 16:47:02.038010027 +0100 --- src/version.c 2022-10-11 19:44:40.455049700 +0100 *************** *** 701,702 **** --- 701,704 ---- { /* Add new patch number below this line */ + /**/ + 724, /**/ -- ARTHUR: Be quiet! DENNIS: Well you can't expect to wield supreme executive power just 'cause some watery tart threw a sword at you! ARTHUR: Shut up! DENNIS: I mean, if I went around sayin' I was an empereror just because some moistened bint had lobbed a scimitar at me they'd put me away! The Quest for the Holy Grail (Monty Python) /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///