Skip to content

Commit 8e4c8c8

Browse files
committed
patch 8.2.1338: Vim9: assigning to script-local variable doesn't check type
Problem: Vim9: assigning to script-local variable doesn't check type. Solution: Use the type. (issue #6591)
1 parent 5862687 commit 8e4c8c8

4 files changed

Lines changed: 57 additions & 21 deletions

File tree

src/testdir/test_vim9_script.vim

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,29 @@ def Test_assignment_dict()
251251

252252
# type becomes dict<any>
253253
let somedict = rand() > 0 ? #{a: 1, b: 2} : #{a: 'a', b: 'b'}
254+
255+
# assignment to script-local dict
256+
let lines =<< trim END
257+
vim9script
258+
let test: dict<any> = {}
259+
def FillDict(): dict<any>
260+
test['a'] = 43
261+
return test
262+
enddef
263+
assert_equal(#{a: 43}, FillDict())
264+
END
265+
call CheckScriptSuccess(lines)
266+
267+
lines =<< trim END
268+
vim9script
269+
let test: dict<any>
270+
def FillDict(): dict<any>
271+
test['a'] = 43
272+
return test
273+
enddef
274+
FillDict()
275+
END
276+
call CheckScriptFailure(lines, 'E1103:')
254277
enddef
255278

256279
def Test_assignment_local()

src/version.c

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

755755
static int included_patches[] =
756756
{ /* Add new patch number below this line */
757+
/**/
758+
1338,
757759
/**/
758760
1337,
759761
/**/

src/vim9compile.c

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5070,6 +5070,8 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
50705070
char_u *ret = NULL;
50715071
int var_count = 0;
50725072
int var_idx;
5073+
int scriptvar_sid = 0;
5074+
int scriptvar_idx = -1;
50735075
int semicolon = 0;
50745076
garray_T *instr = &cctx->ctx_instr;
50755077
garray_T *stack = &cctx->ctx_type_stack;
@@ -5333,7 +5335,8 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
53335335
}
53345336
else
53355337
{
5336-
int idx;
5338+
int idx;
5339+
imported_T *import = NULL;
53375340

53385341
for (idx = 0; reserved[idx] != NULL; ++idx)
53395342
if (STRCMP(reserved[idx], name) == 0)
@@ -5374,9 +5377,11 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
53745377
}
53755378
else if ((varlen > 1 && STRNCMP(var_start, "s:", 2) == 0)
53765379
|| lookup_script(var_start, varlen) == OK
5377-
|| find_imported(var_start, varlen, cctx) != NULL)
5380+
|| (import = find_imported(var_start, varlen, cctx))
5381+
!= NULL)
53785382
{
5379-
dest = dest_script;
5383+
char_u *rawname = name + (name[1] == ':' ? 2 : 0);
5384+
53805385
if (is_decl)
53815386
{
53825387
if ((varlen > 1 && STRNCMP(var_start, "s:", 2) == 0))
@@ -5387,6 +5392,21 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
53875392
name);
53885393
goto theend;
53895394
}
5395+
dest = dest_script;
5396+
5397+
// existing script-local variables should have a type
5398+
scriptvar_sid = current_sctx.sc_sid;
5399+
if (import != NULL)
5400+
scriptvar_sid = import->imp_sid;
5401+
scriptvar_idx = get_script_item_idx(scriptvar_sid,
5402+
rawname, TRUE);
5403+
if (scriptvar_idx >= 0)
5404+
{
5405+
scriptitem_T *si = SCRIPT_ITEM(scriptvar_sid);
5406+
svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data)
5407+
+ scriptvar_idx;
5408+
type = sv->sv_type;
5409+
}
53905410
}
53915411
else if (name[1] == ':' && name[2] != NUL)
53925412
{
@@ -5766,21 +5786,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
57665786
break;
57675787
case dest_script:
57685788
{
5769-
char_u *rawname = name + (name[1] == ':' ? 2 : 0);
5770-
imported_T *import = NULL;
5771-
int sid = current_sctx.sc_sid;
5772-
int idx;
5773-
5774-
if (name[1] != ':')
5775-
{
5776-
import = find_imported(name, 0, cctx);
5777-
if (import != NULL)
5778-
sid = import->imp_sid;
5779-
}
5780-
5781-
idx = get_script_item_idx(sid, rawname, TRUE);
5782-
// TODO: specific type
5783-
if (idx < 0)
5789+
if (scriptvar_idx < 0)
57845790
{
57855791
char_u *name_s = name;
57865792

@@ -5796,14 +5802,14 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
57965802
vim_snprintf((char *)name_s, len,
57975803
"s:%s", name);
57985804
}
5799-
generate_OLDSCRIPT(cctx, ISN_STORES, name_s, sid,
5800-
&t_any);
5805+
generate_OLDSCRIPT(cctx, ISN_STORES, name_s,
5806+
scriptvar_sid, type);
58015807
if (name_s != name)
58025808
vim_free(name_s);
58035809
}
58045810
else
58055811
generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
5806-
sid, idx, &t_any);
5812+
scriptvar_sid, scriptvar_idx, type);
58075813
}
58085814
break;
58095815
case dest_local:

src/vim9execute.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,6 +1422,11 @@ call_def_function(
14221422
dict_T *dict = tv_dict->vval.v_dict;
14231423
dictitem_T *di;
14241424

1425+
if (dict == NULL)
1426+
{
1427+
emsg(_(e_dictnull));
1428+
goto on_error;
1429+
}
14251430
if (key == NULL)
14261431
key = (char_u *)"";
14271432
tv = STACK_TV_BOT(-3);

0 commit comments

Comments
 (0)