From e5826687d137981b9b105403dc3a913cf8682745 Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Mon, 26 Oct 2026 10:30:20 +0000 Subject: [PATCH] patch 9.2.1242: Vim9: list instead of tuple for rest of tuple in a :for loop Problem: Vim9: In a compiled function, when unpacking a tuple in a :for loop, the variable after ";" gets a list with the remaining items instead of a tuple. Solution: Create a tuple with the remaining items (Yegappan Lakshmanan). The help says that the variable after ";" gets a tuple, this was already the case when not in a compiled function. fixes: #21587 closes: #21588 Assisted-by: Claude Code (Claude Opus 5.5) Signed-off-by: Yegappan Lakshmanan Signed-off-by: Christian Brabandt --- src/testdir/test_tuple.vim | 14 ++++++++++++++ src/version.c | 2 ++ src/vim9execute.c | 16 ++++++++-------- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/testdir/test_tuple.vim b/src/testdir/test_tuple.vim index 3fb0a342e8..140066679d 100644 --- a/src/testdir/test_tuple.vim +++ b/src/testdir/test_tuple.vim @@ -787,6 +787,20 @@ func Test_multi_assign_from_tuple() call v9.CheckSourceFailure(lines, 'E1093: Expected 2 items but got 0') endfunc +" Test for the value of the variable after ";" when unpacking a tuple in a +" :for loop. It must be a tuple, also in a compiled function. +def Test_tuple_for_unpack_rest_is_tuple() + var lines =<< trim END + var r = [] + for [a; b] in ((1, 2, 3), (4,)) + assert_equal(v:t_tuple, type(b)) + r->add(b) + endfor + assert_equal([(2, 3), ()], r) + END + v9.CheckSourceDefAndScriptSuccess(lines) +enddef + " Test for performing an arithmetic operation on multiple variables using " items from a tuple func Test_multi_arithmetic_op_from_tuple() diff --git a/src/version.c b/src/version.c index 3240c2704f..919646d9ac 100644 --- a/src/version.c +++ b/src/version.c @@ -743,6 +743,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1242, /**/ 1241, /**/ diff --git a/src/vim9execute.c b/src/vim9execute.c index c3d9ec1adc..46cb72dbc0 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -3583,26 +3583,26 @@ exec_unpack_tuple(ectx_T *ectx, isn_T *iptr, typval_T *tv) return EXEC_DONE; ectx->ec_stack.ga_len += count - 1; - // Variable after semicolon gets a list with the remaining + // Variable after semicolon gets a tuple with the remaining // items. if (semicolon) { - list_T *rem_list = - list_alloc_with_items(TUPLE_LEN(tuple) - count + 1); + tuple_T *rem_tuple = + tuple_alloc_with_items(TUPLE_LEN(tuple) - count + 1); - if (rem_list == NULL) + if (rem_tuple == NULL) return EXEC_DONE; tv = STACK_TV_BOT(-count); - tv->v_type = VAR_LIST; - tv->vval.v_list = rem_list; - ++rem_list->lv_refcount; + tv->v_type = VAR_TUPLE; + tv->vval.v_tuple = rem_tuple; + ++rem_tuple->tv_refcount; tv->v_lock = 0; for (i = count - 1; i < TUPLE_LEN(tuple); ++i) { typval_T tvcopy; copy_tv(TUPLE_ITEM(tuple, i), &tvcopy); - list_set_item(rem_list, i - (count - 1), &tvcopy); + tuple_set_item(rem_tuple, i - (count - 1), &tvcopy); } --count; }