From 8e4c8c853e3ffbd9258f89180692879ec6bce72b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 1 Aug 2020 15:38:38 +0200 Subject: 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) --- src/testdir/test_vim9_script.vim | 23 +++++++++++++++++++ src/version.c | 2 ++ src/vim9compile.c | 48 ++++++++++++++++++++++------------------ src/vim9execute.c | 5 +++++ 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 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 = {} + def FillDict(): dict + test['a'] = 43 + return test + enddef + assert_equal(#{a: 43}, FillDict()) + END + call CheckScriptSuccess(lines) + + lines =<< trim END + vim9script + let test: dict + def FillDict(): dict + 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 @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1338, /**/ 1337, /**/ 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); -- cgit v1.2.1