Skip to content

Commit cdc40c4

Browse files
committed
patch 8.2.2223: Vim9: Reloading marks a :def function as deleted
Problem: Vim9: Reloading marks a :def function as deleted. Solution: Clear the function contents but keep the index.
1 parent 2b32700 commit cdc40c4

5 files changed

Lines changed: 18 additions & 38 deletions

File tree

runtime/doc/vim9.txt

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -219,23 +219,6 @@ some point when loaded again. E.g. when a buffer local option is set: >
219219
def g:SomeFunc()
220220
....
221221
222-
There is one gotcha: If a compiled function is replaced and it is called from
223-
another compiled function that is not replaced, it will try to call the
224-
function from before it was replaced, which no longer exists. This doesn't
225-
work: >
226-
vimscript noclear
227-
228-
def ReplaceMe()
229-
echo 'function redefined every time'
230-
enddef
231-
232-
if exists('s:loaded') | finish | endif
233-
var s:loaded = true
234-
235-
def NotReplaced()
236-
ReplaceMe() # Error if ReplaceMe() was redefined
237-
enddef
238-
239222
240223
Variable declarations with :var, :final and :const ~
241224
*vim9-declaration* *:var*

src/testdir/test_vim9_script.vim

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,10 +1174,7 @@ def Test_vim9script_reload_noclear()
11741174
var s:notReloaded = 'yes'
11751175
s:reloaded = 'first'
11761176
def g:Values(): list<string>
1177-
return [s:reloaded, s:notReloaded, Once()]
1178-
enddef
1179-
def g:CallAgain(): string
1180-
return Again()
1177+
return [s:reloaded, s:notReloaded, Again(), Once()]
11811178
enddef
11821179

11831180
def Once(): string
@@ -1188,20 +1185,16 @@ def Test_vim9script_reload_noclear()
11881185
g:loadCount = 0
11891186
source XReloaded
11901187
assert_equal(1, g:loadCount)
1191-
assert_equal(['first', 'yes', 'once'], g:Values())
1192-
assert_equal('again', g:CallAgain())
1188+
assert_equal(['first', 'yes', 'again', 'once'], g:Values())
11931189
source XReloaded
11941190
assert_equal(2, g:loadCount)
1195-
assert_equal(['init', 'yes', 'once'], g:Values())
1196-
assert_fails('call g:CallAgain()', 'E933:')
1191+
assert_equal(['init', 'yes', 'again', 'once'], g:Values())
11971192
source XReloaded
11981193
assert_equal(3, g:loadCount)
1199-
assert_equal(['init', 'yes', 'once'], g:Values())
1200-
assert_fails('call g:CallAgain()', 'E933:')
1194+
assert_equal(['init', 'yes', 'again', 'once'], g:Values())
12011195

12021196
delete('Xreloaded')
12031197
delfunc g:Values
1204-
delfunc g:CallAgain
12051198
unlet g:loadCount
12061199
enddef
12071200

src/userfunc.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3628,7 +3628,7 @@ define_function(exarg_T *eap, char_u *name_arg)
36283628
fp->uf_profiling = FALSE;
36293629
fp->uf_prof_initialized = FALSE;
36303630
#endif
3631-
unlink_def_function(fp);
3631+
fp->uf_def_status = UF_NOT_COMPILED;
36323632
}
36333633
}
36343634
}
@@ -3694,8 +3694,6 @@ define_function(exarg_T *eap, char_u *name_arg)
36943694
fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(name) + 1);
36953695
if (fp == NULL)
36963696
goto erret;
3697-
fp->uf_def_status = eap->cmdidx == CMD_def ? UF_TO_BE_COMPILED
3698-
: UF_NOT_COMPILED;
36993697

37003698
if (fudi.fd_dict != NULL)
37013699
{

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,8 @@ static char *(features[]) =
750750

751751
static int included_patches[] =
752752
{ /* Add new patch number below this line */
753+
/**/
754+
2223,
753755
/**/
754756
2222,
755757
/**/

src/vim9compile.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ struct cctx_S {
145145
int ctx_has_cmdmod; // ISN_CMDMOD was generated
146146
};
147147

148-
static void delete_def_function_contents(dfunc_T *dfunc);
148+
static void delete_def_function_contents(dfunc_T *dfunc, int mark_deleted);
149149

150150
/*
151151
* Lookup variable "name" in the local scope and return it in "lvar".
@@ -7498,12 +7498,12 @@ compile_def_function(ufunc_T *ufunc, int check_return_type, cctx_T *outer_cctx)
74987498
int new_def_function = FALSE;
74997499

75007500
// When using a function that was compiled before: Free old instructions.
7501-
// Otherwise add a new entry in "def_functions".
7501+
// The index is reused. Otherwise add a new entry in "def_functions".
75027502
if (ufunc->uf_dfunc_idx > 0)
75037503
{
75047504
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
75057505
+ ufunc->uf_dfunc_idx;
7506-
delete_def_function_contents(dfunc);
7506+
delete_def_function_contents(dfunc, FALSE);
75077507
}
75087508
else
75097509
{
@@ -8344,7 +8344,7 @@ delete_instr(isn_T *isn)
83448344
* Free all instructions for "dfunc" except df_name.
83458345
*/
83468346
static void
8347-
delete_def_function_contents(dfunc_T *dfunc)
8347+
delete_def_function_contents(dfunc_T *dfunc, int mark_deleted)
83488348
{
83498349
int idx;
83508350

@@ -8355,9 +8355,13 @@ delete_def_function_contents(dfunc_T *dfunc)
83558355
for (idx = 0; idx < dfunc->df_instr_count; ++idx)
83568356
delete_instr(dfunc->df_instr + idx);
83578357
VIM_CLEAR(dfunc->df_instr);
8358+
dfunc->df_instr = NULL;
83588359
}
83598360

8360-
dfunc->df_deleted = TRUE;
8361+
if (mark_deleted)
8362+
dfunc->df_deleted = TRUE;
8363+
if (dfunc->df_ufunc != NULL)
8364+
dfunc->df_ufunc->uf_def_status = UF_NOT_COMPILED;
83618365
}
83628366

83638367
/*
@@ -8374,7 +8378,7 @@ unlink_def_function(ufunc_T *ufunc)
83748378
+ ufunc->uf_dfunc_idx;
83758379

83768380
if (--dfunc->df_refcount <= 0)
8377-
delete_def_function_contents(dfunc);
8381+
delete_def_function_contents(dfunc, TRUE);
83788382
ufunc->uf_def_status = UF_NOT_COMPILED;
83798383
ufunc->uf_dfunc_idx = 0;
83808384
if (dfunc->df_ufunc == ufunc)
@@ -8410,7 +8414,7 @@ free_def_functions(void)
84108414
{
84118415
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
84128416

8413-
delete_def_function_contents(dfunc);
8417+
delete_def_function_contents(dfunc, TRUE);
84148418
vim_free(dfunc->df_name);
84158419
}
84168420

0 commit comments

Comments
 (0)