Commit: patch 9.2.0902: Vim9: iterating over a tuple leaks memory
Christian Brabandt <[email protected]> Mon, 3 Aug 2026 22:00:09 +0200
| Newsgroups | gmane.editors.vim.devel |
|---|---|
| Message-ID | <[email protected]> |
patch 9.2.0902: Vim9: iterating over a tuple leaks memory Commit: https://github.com/vim/vim/commit/6d2f94baa38751fe1d42c2654c049b740a96b335 Author: Samuel Schlesinger <[email protected]> Date: Mon Aug 3 19:54:50 2026 +0000 patch 9.2.0902: Vim9: iterating over a tuple leaks memory Problem: Looping over a tuple with ":for" copies each item with copy_tv() but never clears the copy, leaking the value on every iteration (26MB over 100k iterations of a two-string tuple). Container items keep an extra reference forever, also defeating garbage collection. Solution: Clear the copied typval on both return paths, like the string branch of next_for_item() already does (Samuel Schlesinger). closes: #20914 Supported by AI. Signed-off-by: Samuel Schlesinger <[email protected]> Signed-off-by: Christian Brabandt <[email protected]> diff --git a/src/eval.c b/src/eval.c index 7d212b5b3..d5373c099 100644 --- a/src/eval.c +++ b/src/eval.c @@ -3005,9 +3005,12 @@ next_for_item(void *fi_void, char_u *arg) ++fi->fi_tuple_idx; ++fi->fi_bi; if (skip_assign) - return TRUE; - return ex_let_vars(arg, &tv, TRUE, fi->fi_semicolon, + result = TRUE; + else + result = ex_let_vars(arg, &tv, TRUE, fi->fi_semicolon, fi->fi_varcount, flag, NULL) == OK; + clear_tv(&tv); + return result; } item = fi->fi_lw.lw_item; diff --git a/src/testdir/test_tuple.vim b/src/testdir/test_tuple.vim index 68bdca08c..ace890c04 100644 --- a/src/testdir/test_tuple.vim +++ b/src/testdir/test_tuple.vim @@ -778,6 +778,20 @@ func Test_tuple_for() LET sum += v2 endfor call assert_equal(0, sum) + + #" iterating over string items; the copied item must not be leaked + VAR res = '' + for v3 in ('a', 'bb', 'ccc') + LET res ..= v3 + endfor + call assert_equal('abbccc', res) + + #" iterating over container items must not leak a reference + VAR flat = [] + for v4 in (['a'], ['b', 'c']) + LET flat += v4 + endfor + call assert_equal(['a', 'b', 'c'], flat) END call v9.CheckSourceLegacyAndVim9Success(lines) @@ -792,6 +806,18 @@ func Test_tuple_for() END call v9.CheckSourceSuccess(lines) + " ignoring the for loop assignment using '_'; string items must not be + " leaked + let lines =<< trim END + vim9script + var count = 0 + for _ in ('a', 'bb', 'ccc') + count += 1 + endfor + assert_equal(3, count) + END + call v9.CheckSourceSuccess(lines) + let lines =<< trim END var sum = 0 for v in null_tuple diff --git a/src/version.c b/src/version.c index dcea5c2ab..851013e9e 100644 --- a/src/version.c +++ b/src/version.c @@ -763,6 +763,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 902, /**/ 901, /**/ -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion visit https://groups.google.com/d/msgid/vim_dev/E1wqypV-00BNY2-51%40256bit.org.