]> granicus.if.org Git - vim/commitdiff
patch 8.2.1338: Vim9: assigning to script-local variable doesn't check type v8.2.1338
authorBram Moolenaar <Bram@vim.org>
Sat, 1 Aug 2020 13:38:38 +0000 (15:38 +0200)
committerBram Moolenaar <Bram@vim.org>
Sat, 1 Aug 2020 13:38:38 +0000 (15:38 +0200)
Problem:    Vim9: assigning to script-local variable doesn't check type.
Solution:   Use the type. (issue #6591)

src/testdir/test_vim9_script.vim
src/version.c
src/vim9compile.c
src/vim9execute.c

index ec63c6f11c590b17d0e9baffffde90d06d00167e..196ddbe0a25a7620752fdf30875bab6ef9670b5b 100644 (file)
@@ -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()
index 661875a27661a548823a430a123a6638e6ec3ad2..fff706fa212dd5d71be245f891ba3f771a7cf49d 100644 (file)
@@ -754,6 +754,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1338,
 /**/
     1337,
 /**/
index 688f42a9de109b26012cd461b04c30f87ff822aa..cae03d8d2ac5bec38949f50e5e5f957553070b0a 100644 (file)
@@ -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:
index de29988be123508ca1bba9e3f273f5248e6c19f9..6e9b53d689ee231289797c86d0094c3595139038 100644 (file)
@@ -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);