]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.2.2268: Vim9: list unpack seen as declaration v8.2.2268
authorBram Moolenaar <Bram@vim.org>
Fri, 1 Jan 2021 20:05:55 +0000 (21:05 +0100)
committerBram Moolenaar <Bram@vim.org>
Fri, 1 Jan 2021 20:05:55 +0000 (21:05 +0100)
Problem:    Vim9: list unpack seen as declaration.
Solution:   Check for "var". (closes #7594)

src/eval.c
src/evalvars.c
src/testdir/test_vim9_assign.vim
src/version.c
src/vim.h
src/vim9compile.c
src/vim9execute.c

index b4b04eb6391629a3ae40bfdbb4b3434a2429c283..ca1c55b4db82f261218a3c48a1f9574e6a34ff3d 100644 (file)
@@ -1748,7 +1748,7 @@ next_for_item(void *fi_void, char_u *arg)
 {
     forinfo_T  *fi = (forinfo_T *)fi_void;
     int                result;
-    int                flag = in_vim9script() ?  ASSIGN_NO_DECL : 0;
+    int                flag = in_vim9script() ? ASSIGN_DECL : 0;
     listitem_T *item;
 
     if (fi->fi_blob != NULL)
index 73b9f3d0fc58ee73bc5e9c1af34cee4e60c98b8a..94b857ed9bcfe2cf2d1753ccecee844c331b80bd 100644 (file)
@@ -912,7 +912,7 @@ ex_let_vars(
     int                copy,           // copy values from "tv", don't move
     int                semicolon,      // from skip_var_list()
     int                var_count,      // from skip_var_list()
-    int                flags,          // ASSIGN_FINAL, ASSIGN_CONST, ASSIGN_NO_DECL
+    int                flags,          // ASSIGN_FINAL, ASSIGN_CONST, etc.
     char_u     *op)
 {
     char_u     *arg = arg_start;
@@ -1267,7 +1267,7 @@ ex_let_one(
     char_u     *arg,           // points to variable name
     typval_T   *tv,            // value to assign to variable
     int                copy,           // copy value from "tv"
-    int                flags,          // ASSIGN_CONST, ASSIGN_FINAL, ASSIGN_NO_DECL
+    int                flags,          // ASSIGN_CONST, ASSIGN_FINAL, etc.
     char_u     *endchars,      // valid chars after variable name  or NULL
     char_u     *op)            // "+", "-", "."  or NULL
 {
@@ -1279,7 +1279,7 @@ ex_let_one(
     int                opt_flags;
     char_u     *tofree = NULL;
 
-    if (in_vim9script() && (flags & ASSIGN_NO_DECL) == 0
+    if (in_vim9script() && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0
                        && (flags & (ASSIGN_CONST | ASSIGN_FINAL)) == 0
                                  && vim_strchr((char_u *)"$@&", *arg) != NULL)
     {
@@ -1476,7 +1476,8 @@ ex_let_one(
        lval_T  lv;
 
        p = get_lval(arg, tv, &lv, FALSE, FALSE,
-               (flags & ASSIGN_NO_DECL) ? GLV_NO_DECL : 0, FNE_CHECK_START);
+               (flags & (ASSIGN_NO_DECL | ASSIGN_DECL))
+                                          ? GLV_NO_DECL : 0, FNE_CHECK_START);
        if (p != NULL && lv.ll_name != NULL)
        {
            if (endchars != NULL && vim_strchr(endchars,
@@ -3053,7 +3054,7 @@ set_var(
     typval_T   *tv,
     int                copy)       // make copy of value in "tv"
 {
-    set_var_const(name, NULL, tv, copy, ASSIGN_NO_DECL);
+    set_var_const(name, NULL, tv, copy, ASSIGN_DECL);
 }
 
 /*
@@ -3067,7 +3068,7 @@ set_var_const(
     type_T     *type,
     typval_T   *tv_arg,
     int                copy,       // make copy of value in "tv"
-    int                flags)      // ASSIGN_CONST, ASSIGN_FINAL, ASSIGN_NO_DECL
+    int                flags)      // ASSIGN_CONST, ASSIGN_FINAL, etc.
 {
     typval_T   *tv = tv_arg;
     typval_T   bool_tv;
@@ -3087,7 +3088,7 @@ set_var_const(
 
     if (vim9script
            && !is_script_local
-           && (flags & ASSIGN_NO_DECL) == 0
+           && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0
            && (flags & (ASSIGN_CONST | ASSIGN_FINAL)) == 0
            && name[1] == ':')
     {
@@ -3126,7 +3127,7 @@ set_var_const(
 
            if (is_script_local && vim9script)
            {
-               if ((flags & ASSIGN_NO_DECL) == 0)
+               if ((flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0)
                {
                    semsg(_(e_redefining_script_item_str), name);
                    goto failed;
@@ -3200,8 +3201,15 @@ set_var_const(
 
        clear_tv(&di->di_tv);
     }
-    else                   // add a new variable
+    else
     {
+       // add a new variable
+       if (vim9script && is_script_local && (flags & ASSIGN_NO_DECL))
+       {
+           semsg(_(e_unknown_variable_str), name);
+           goto failed;
+       }
+
        // Can't add "v:" or "a:" variable.
        if (ht == &vimvarht || ht == get_funccal_args_ht())
        {
index d884a4f7a828b327e2f39881b5d0b5e28b622ed2..5f45b57a11a0075599feb21fb93e07172bb1449b 100644 (file)
@@ -261,6 +261,12 @@ def Test_assign_unpack()
   END
   CheckDefFailure(lines, 'E1031:', 3)
 
+  lines =<< trim END
+      [v1, v2] = [1, 2]
+  END
+  CheckDefFailure(lines, 'E1089', 1)
+  CheckScriptFailure(['vim9script'] + lines, 'E1089', 2)
+
   lines =<< trim END
       var v1: number
       var v2: number
@@ -759,6 +765,8 @@ def Test_assignment_default()
   assert_equal(5678, nr)
 enddef
 
+let scriptvar = 'init'
+
 def Test_assignment_var_list()
   var lines =<< trim END
       var v1: string
@@ -794,10 +802,9 @@ def Test_assignment_var_list()
       assert_equal('some', $SOME_VAR)
       assert_equal('other', $OTHER_VAR)
 
-      [g:globalvar, s:scriptvar, b:bufvar, w:winvar, t:tabvar, v:errmsg] =
-            ['global', 'script', 'buf', 'win', 'tab', 'error']
+      [g:globalvar, b:bufvar, w:winvar, t:tabvar, v:errmsg] =
+            ['global', 'buf', 'win', 'tab', 'error']
       assert_equal('global', g:globalvar)
-      assert_equal('script', s:scriptvar)
       assert_equal('buf', b:bufvar)
       assert_equal('win', w:winvar)
       assert_equal('tab', t:tabvar)
@@ -805,6 +812,21 @@ def Test_assignment_var_list()
       unlet g:globalvar
   END
   CheckDefAndScriptSuccess(lines)
+
+  [g:globalvar, s:scriptvar, b:bufvar] = ['global', 'script', 'buf']
+  assert_equal('global', g:globalvar)
+  assert_equal('script', s:scriptvar)
+  assert_equal('buf', b:bufvar)
+
+  lines =<< trim END
+      vim9script
+      var s:scriptvar = 'init'
+      [g:globalvar, s:scriptvar, w:winvar] = ['global', 'script', 'win']
+      assert_equal('global', g:globalvar)
+      assert_equal('script', s:scriptvar)
+      assert_equal('win', w:winvar)
+  END
+  CheckScriptSuccess(lines)
 enddef
 
 def Test_assignment_vim9script()
@@ -1182,7 +1204,7 @@ def Test_var_declaration()
     g:other_var = other
 
     # type is inferred
-    s:dict = {['a']: 222}
+    var s:dict = {['a']: 222}
     def GetDictVal(key: any)
       g:dict_val = s:dict[key]
     enddef
index 1c5c6b39fc3af906442df7bf8d64c2d708ae7446..76a9b4ea9114391a151c6fe344e52acb0cfb049e 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2268,
 /**/
     2267,
 /**/
index f19a4fe97b8e79df25efd1f38c00b4042675b00a..a0ee0d6b9059870d19880080fdf9d16342473c15 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -2146,6 +2146,7 @@ typedef enum {
 #define ASSIGN_FINAL   1   // ":final"
 #define ASSIGN_CONST   2   // ":const"
 #define ASSIGN_NO_DECL 4   // "name = expr" without ":let"/":const"/":final"
+#define ASSIGN_DECL    8   // may declare variable if it does not exist
 
 #include "ex_cmds.h"       // Ex command defines
 #include "spell.h"         // spell checking stuff
index 19d8473fb7b03df68e22f467cb8d4db3b282de6a..303573f914ceab1447b5cc8966136a57e61fd38b 100644 (file)
@@ -5634,6 +5634,11 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
                semsg(_(e_cannot_use_operator_on_new_variable), name);
                goto theend;
            }
+           if (!is_decl)
+           {
+               semsg(_(e_unknown_variable_str), name);
+               goto theend;
+           }
 
            // new local variable
            if ((type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
@@ -6140,6 +6145,7 @@ compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
        return NULL;
     }
 
+    // TODO: this doesn't work for local variables
     ex_unletlock(eap, p, 0, GLV_NO_AUTOLOAD, compile_unlet, cctx);
     return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
 }
index 31b1274028341ccdf99e1938315b6432021fd610..b389891df6d81f6a6671457bb2801c3a4b3d7df7 100644 (file)
@@ -806,7 +806,7 @@ store_var(char_u *name, typval_T *tv)
     funccal_entry_T entry;
 
     save_funccal(&entry);
-    set_var_const(name, NULL, tv, FALSE, ASSIGN_NO_DECL);
+    set_var_const(name, NULL, tv, FALSE, ASSIGN_DECL);
     restore_funccal();
 }