patch 9.2.0071: Vim9: lambda function deleted on re-sourcing
Commit:
https://github.com/vim/vim/commit/c598c4de275e9075583bc7fe628bb2a50868acfd
Author: Hirohito Higashi <[email protected]>
Date: Fri Feb 27 19:03:18 2026 +0000
patch 9.2.0071: Vim9: lambda function deleted on re-sourcing
Problem: Vim9: lambda function deleted on re-sourcing
(Mao-Yining)
Solution: Use ISN_UCALL for script-local def calls inside a lambda
(Hirohito Higashi).
fixes: #19509
closes: #19519
Signed-off-by: Hirohito Higashi <[email protected]>
Signed-off-by: Christian Brabandt <[email protected]>
diff --git a/src/testdir/test_vim9_disassemble.vim
b/src/testdir/test_vim9_disassemble.vim
index 83499999d..759226a41 100644
--- a/src/testdir/test_vim9_disassemble.vim
+++ b/src/testdir/test_vim9_disassemble.vim
@@ -1473,6 +1473,31 @@ def Test_disassemble_lambda()
instr)
enddef
+def s:ScriptLocalDefForLambda()
+enddef
+
+def GlobalDefForLambda()
+enddef
+
+def s:OuterWithLambdaCalls()
+ timer_start(0, (_) => {
+ ScriptLocalDefForLambda()
+ g:GlobalDefForLambda()
+ })
+enddef
+
+def Test_disassemble_lambda_call_types()
+ # Verify that inside a lambda:
+ # - script-local def function call → ISN_UCALL (safe after re-sourcing)
+ # - global def function call → ISN_DCALL (optimal, not deleted on
re-source)
+ OuterWithLambdaCalls()
+ var instr = execute('disassemble OuterWithLambdaCalls')
+ var name = substitute(instr, '.*\(<lambda>\d\+\).*', ' ', '')
+ instr = execute('disassemble ' .. name)
+ assert_match('\d UCALL <80><fd>R\d\+_ScriptLocalDefForLambda(argc 0)', instr)
+ assert_match('\d DCALL GlobalDefForLambda(argc 0)', instr)
+enddef
+
def s:LambdaWithType(): number
var Ref = (a: number) => a + 10
return Ref(g:value)
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index ed946d85d..022bdeb12 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -1847,6 +1847,41 @@ def Test_vim9script_reload_delfunc()
g:DoCheck(false)
enddef
+def Test_vim9script_reload_lambda_def_func()
+ CheckFeature timers
+
+ var lines =<< trim END
+ vim9script
+
+ def F()
+ g:call_result += 1
+ enddef
+
+ augroup Xtest933
+ au!
+ au CmdlineLeave : timer_start(0, (_) => F())
+ augroup END
+ END
+
+ g:call_result = 0
+ writefile(lines, 'Xtest933.vim', 'D')
+ source Xtest933.vim
+
+ # Simulate the CmdlineLeave event that fires before the second :so
+ doautocmd CmdlineLeave :
+
+ # Re-source: F is redefined; without the fix this causes E933 when timer
fires
+ source Xtest933.vim
+
+ # Allow the 0ms timer to fire
+ sleep 10m
+
+ assert_equal(1, g:call_result)
+
+ augroup Xtest933 | au! | augroup END
+ unlet! g:call_result
+enddef
+
def Test_vim9script_reload_delvar()
# write the script with a script-local variable
var lines =<< trim END
diff --git a/src/version.c b/src/version.c
index 0fde64014..4524be1da 100644
--- a/src/version.c
+++ b/src/version.c
@@ -734,6 +734,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 71,
/**/
70,
/**/
diff --git a/src/vim9instr.c b/src/vim9instr.c
index c11e913b0..90156bfa0 100644
--- a/src/vim9instr.c
+++ b/src/vim9instr.c
@@ -1909,6 +1909,23 @@ generate_BLOBAPPEND(cctx_T *cctx)
return OK;
}
+/*
+ * get the instruction type for a function call: ISN_METHODCALL, ISN_DCALL, or
+ * ISN_UCALL.
+ */
+ static isntype_T
+isn_get_calltype(
+ cctx_T *cctx,
+ ufunc_T *ufunc,
+ class_T *cl)
+{
+ return cl != NULL ? ISN_METHODCALL
+ : (ufunc->uf_def_status != UF_NOT_COMPILED
+ && ((cctx->ctx_ufunc->uf_flags & FC_LAMBDA) == 0
+ || ufunc->uf_name[0] != K_SPECIAL))
+ ? ISN_DCALL : ISN_UCALL;
+}
+
/*
* Generate an ISN_DCALL, ISN_UCALL or ISN_METHODCALL instruction.
* When calling a method on an object, of which we know the interface only,
@@ -1996,9 +2013,7 @@ generate_CALL(
return FAIL;
}
- if ((isn = generate_instr(cctx, cl != NULL ? ISN_METHODCALL
- : ufunc->uf_def_status != UF_NOT_COMPILED
- ? ISN_DCALL : ISN_UCALL)) == NULL)
+ if ((isn = generate_instr(cctx, isn_get_calltype(cctx, ufunc, cl))) ==
NULL)
return FAIL;
if (cl != NULL /* isn->isn_type == ISN_METHODCALL */)
{
--
--
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/E1vw3Il-00G6gO-1l%40256bit.org.