summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-08-01 15:38:38 +0200
committerBram Moolenaar <Bram@vim.org>2020-08-01 15:38:38 +0200
commit8e4c8c853e3ffbd9258f89180692879ec6bce72b (patch)
tree4c9fffbb135d0f4d2bb150e8467549e97993c88b
parent586268721dd5d6e50903a8a457f02e0dda901856 (diff)
downloadvim-git-8e4c8c853e3ffbd9258f89180692879ec6bce72b.tar.gz
patch 8.2.1338: Vim9: assigning to script-local variable doesn't check typev8.2.1338
Problem: Vim9: assigning to script-local variable doesn't check type. Solution: Use the type. (issue #6591)
-rw-r--r--src/testdir/test_vim9_script.vim23
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c48
-rw-r--r--src/vim9execute.c5
4 files changed, 57 insertions, 21 deletions
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index ec63c6f11..196ddbe0a 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -251,6 +251,29 @@ def Test_assignment_dict()
# type becomes dict<any>
let somedict = rand() > 0 ? #{a: 1, b: 2} : #{a: 'a', b: 'b'}
+
+ # assignment to script-local dict
+ let lines =<< trim END
+ vim9script
+ let test: dict<any> = {}
+ def FillDict(): dict<any>
+ test['a'] = 43
+ return test
+ enddef
+ assert_equal(#{a: 43}, FillDict())
+ END
+ call CheckScriptSuccess(lines)
+
+ lines =<< trim END
+ vim9script
+ let test: dict<any>
+ def FillDict(): dict<any>
+ test['a'] = 43
+ return test
+ enddef
+ FillDict()
+ END
+ call CheckScriptFailure(lines, 'E1103:')
enddef
def Test_assignment_local()
diff --git a/src/version.c b/src/version.c
index 661875a27..fff706fa2 100644
--- a/src/version.c
+++ b/src/version.c
@@ -755,6 +755,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1338,
+/**/
1337,
/**/
1336,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 688f42a9d..cae03d8d2 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -5070,6 +5070,8 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
char_u *ret = NULL;
int var_count = 0;
int var_idx;
+ int scriptvar_sid = 0;
+ int scriptvar_idx = -1;
int semicolon = 0;
garray_T *instr = &cctx->ctx_instr;
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)
}
else
{
- int idx;
+ int idx;
+ imported_T *import = NULL;
for (idx = 0; reserved[idx] != NULL; ++idx)
if (STRCMP(reserved[idx], name) == 0)
@@ -5374,9 +5377,11 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
}
else if ((varlen > 1 && STRNCMP(var_start, "s:", 2) == 0)
|| lookup_script(var_start, varlen) == OK
- || find_imported(var_start, varlen, cctx) != NULL)
+ || (import = find_imported(var_start, varlen, cctx))
+ != NULL)
{
- dest = dest_script;
+ char_u *rawname = name + (name[1] == ':' ? 2 : 0);
+
if (is_decl)
{
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)
name);
goto theend;
}
+ dest = dest_script;
+
+ // existing script-local variables should have a type
+ scriptvar_sid = current_sctx.sc_sid;
+ if (import != NULL)
+ scriptvar_sid = import->imp_sid;
+ scriptvar_idx = get_script_item_idx(scriptvar_sid,
+ rawname, TRUE);
+ if (scriptvar_idx >= 0)
+ {
+ scriptitem_T *si = SCRIPT_ITEM(scriptvar_sid);
+ svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data)
+ + scriptvar_idx;
+ type = sv->sv_type;
+ }
}
else if (name[1] == ':' && name[2] != NUL)
{
@@ -5766,21 +5786,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
break;
case dest_script:
{
- char_u *rawname = name + (name[1] == ':' ? 2 : 0);
- imported_T *import = NULL;
- int sid = current_sctx.sc_sid;
- int idx;
-
- if (name[1] != ':')
- {
- import = find_imported(name, 0, cctx);
- if (import != NULL)
- sid = import->imp_sid;
- }
-
- idx = get_script_item_idx(sid, rawname, TRUE);
- // TODO: specific type
- if (idx < 0)
+ if (scriptvar_idx < 0)
{
char_u *name_s = name;
@@ -5796,14 +5802,14 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
vim_snprintf((char *)name_s, len,
"s:%s", name);
}
- generate_OLDSCRIPT(cctx, ISN_STORES, name_s, sid,
- &t_any);
+ generate_OLDSCRIPT(cctx, ISN_STORES, name_s,
+ scriptvar_sid, type);
if (name_s != name)
vim_free(name_s);
}
else
generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
- sid, idx, &t_any);
+ scriptvar_sid, scriptvar_idx, type);
}
break;
case dest_local:
diff --git a/src/vim9execute.c b/src/vim9execute.c
index de29988be..6e9b53d68 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -1422,6 +1422,11 @@ call_def_function(
dict_T *dict = tv_dict->vval.v_dict;
dictitem_T *di;
+ if (dict == NULL)
+ {
+ emsg(_(e_dictnull));
+ goto on_error;
+ }
if (key == NULL)
key = (char_u *)"";
tv = STACK_TV_BOT(-3);