From f5bfc48c0596aead6dd30438930d2cb621b18a35 Mon Sep 17 00:00:00 2001 From: Hirohito Higashi Date: Thu, 1 May 2025 08:56:39 +0200 Subject: [PATCH] patch 9.1.1356: Vim9: crash when unletting variable Problem: Vim9: crash when unletting variable Solution: fix crash, allow to use :unlet (Hirohito Higashi) closes: #17226 Signed-off-by: Hirohito Higashi Signed-off-by: Christian Brabandt --- src/proto/vim9compile.pro | 1 - src/testdir/test_vim9_assign.vim | 19 +++++++++++++------ src/version.c | 2 ++ src/vim9cmds.c | 2 +- src/vim9compile.c | 11 +---------- 5 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/proto/vim9compile.pro b/src/proto/vim9compile.pro index 080a2ffaaf..6d91bc86a0 100644 --- a/src/proto/vim9compile.pro +++ b/src/proto/vim9compile.pro @@ -2,7 +2,6 @@ int lookup_local(char_u *name, size_t len, lvar_T *lvar, cctx_T *cctx); int arg_exists(char_u *name, size_t len, int *idxp, type_T **type, int *gen_load_outer, cctx_T *cctx); void update_script_var_block_id(char_u *name, int block_id); -int script_is_vim9(void); int script_var_exists(char_u *name, size_t len, cctx_T *cctx, cstack_T *cstack); int cctx_class_method_idx(cctx_T *cctx, char_u *name, size_t len, class_T **cl_ret); int cctx_class_member_idx(cctx_T *cctx, char_u *name, size_t len, class_T **cl_ret); diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim index 960dd7116f..3b0838430c 100644 --- a/src/testdir/test_vim9_assign.vim +++ b/src/testdir/test_vim9_assign.vim @@ -2499,12 +2499,11 @@ def Test_unlet() assert_false(exists('g:somevar')) unlet! g:somevar - # also works for script-local variable in legacy Vim script - s:somevar = 'legacy' + # script-local variable cannot be removed in Vim9 script + s:somevar = 'local' assert_true(exists('s:somevar')) - unlet s:somevar - assert_false(exists('s:somevar')) - unlet! s:somevar + v9.CheckDefExecFailure(['unlet s:somevar'], 'E1081:', 1) + v9.CheckDefExecFailure(['unlet! s:somevar'], 'E1081:', 1) if 0 unlet g:does_not_exist @@ -2677,13 +2676,21 @@ def Test_unlet() 'enddef', 'defcompile', ], 'E1081:') - v9.CheckScriptFailure([ + v9.CheckScriptSuccess([ 'vim9script', 'var svar = 123', 'func Func()', ' unlet s:svar', 'endfunc', 'Func()', + ]) + v9.CheckScriptFailure([ + 'vim9script', + 'var svar = 123', + 'def Func()', + ' vim9cmd unlet s:svar', + 'enddef', + 'defcompile', ], 'E1081:') v9.CheckScriptFailure([ 'vim9script', diff --git a/src/version.c b/src/version.c index 0c731a88dd..d82060838a 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1356, /**/ 1355, /**/ diff --git a/src/vim9cmds.c b/src/vim9cmds.c index 6295090110..d4ffb93313 100644 --- a/src/vim9cmds.c +++ b/src/vim9cmds.c @@ -99,7 +99,7 @@ check_vim9_unlet(char_u *name) if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL) { // "unlet s:var" is allowed in legacy script. - if (*name == 's' && !script_is_vim9()) + if (*name == 's' && !in_vim9script()) return OK; semsg(_(e_cannot_unlet_str), name); return FAIL; diff --git a/src/vim9compile.c b/src/vim9compile.c index 0a4c3facb6..b3cf86c98d 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -287,15 +287,6 @@ update_script_var_block_id(char_u *name, int block_id) sav->sav_block_id = block_id; } -/* - * Return TRUE if the script context is Vim9 script. - */ - int -script_is_vim9(void) -{ - return SCRIPT_ITEM(current_sctx.sc_sid)->sn_version == SCRIPT_VERSION_VIM9; -} - /* * Lookup a variable (without s: prefix) in the current script. * "cctx" is NULL at the script level, "cstack" is NULL in a function. @@ -306,7 +297,7 @@ script_var_exists(char_u *name, size_t len, cctx_T *cctx, cstack_T *cstack) { if (current_sctx.sc_sid <= 0) return FAIL; - if (script_is_vim9()) + if (current_script_is_vim9()) { // Check script variables that were visible where the function was // defined.