]> granicus.if.org Git - vim/commitdiff
patch 8.2.3717: Vim9: error for constant list size is only given at runtime v8.2.3717
authorBram Moolenaar <Bram@vim.org>
Wed, 1 Dec 2021 17:38:01 +0000 (17:38 +0000)
committerBram Moolenaar <Bram@vim.org>
Wed, 1 Dec 2021 17:38:01 +0000 (17:38 +0000)
Problem:    Vim9: error for constant list size is only given at runtime.
Solution:   Give the error at compile time if possible.

src/testdir/test_vim9_assign.vim
src/testdir/test_vim9_disassemble.vim
src/testdir/test_vim9_script.vim
src/version.c
src/vim9compile.c

index 87924c62946865e9d664720209f090fe41c0c3df..d191ac0bdfd0fb463d2bffdd0b411f35fd098cd4 100644 (file)
@@ -383,6 +383,27 @@ def Test_assign_unpack()
   END
   CheckDefAndScriptSuccess(lines)
 
+  lines =<< trim END
+      var v1: number
+      var v2: number
+      [v1, v2] = [1, 2, 3]
+  END
+  CheckDefFailure(lines, 'E1093: Expected 2 items but got 3', 3)
+
+  lines =<< trim END
+      var v1: number
+      var v2: number
+      [v1, v2] = [1]
+  END
+  CheckDefFailure(lines, 'E1093: Expected 2 items but got 1', 3)
+
+  lines =<< trim END
+      var v1: number
+      var v2: number
+      [v1, v2; _] = [1]
+  END
+  CheckDefFailure(lines, 'E1093: Expected 2 items but got 1', 3)
+
   lines =<< trim END
       var v1: number
       var v2: number
index 1c6b4bb3a2b8108601c6834054c5956cdb1d11d5..184f5575866b226ae13d6627316a6e7b6e65514d 100644 (file)
@@ -471,7 +471,6 @@ def Test_disassemble_list_assign_with_op()
         '\d\+ PUSHNR 4\_s*' ..
         '\d\+ PUSHNR 5\_s*' ..
         '\d\+ NEWLIST size 2\_s*' ..
-        '\d\+ CHECKLEN 2\_s*' ..
         '\d\+ LOAD $0\_s*' ..
         '\d\+ ITEM 0 with op\_s*' ..
         '\d\+ OPNR +\_s*' ..
index 989627f95f11ae13e91d506e6598f8e092e84331..40833c51c640ff856f5cfa75ebfd7feb8f88da89 100644 (file)
@@ -496,8 +496,9 @@ def Test_try_catch_throw()
   endtry
   assert_equal(266, n)
 
+  l = [1, 2, 3] 
   try
-    [n] = [1, 2, 3]
+    [n] = l
   catch /E1093:/
     n = 277
   endtry
@@ -4327,7 +4328,8 @@ def Test_catch_exception_in_callback()
         var x: string
         var y: string
         # this error should be caught with CHECKLEN
-        [x, y] = ['']
+        var sl = ['']
+        [x, y] = sl
       catch
         g:caught = 'yes'
       endtry
index 5724eeccd4e7ab0bad0b1f7754e45d0312795cb9..c5e5f6b351b013a8a75907c9d3702615ed90d5b5 100644 (file)
@@ -753,6 +753,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    3717,
 /**/
     3716,
 /**/
index a8e2c121d6cc83261662314e5da2507ceabe0e33..70cf0b4e99503e274d9dc1db3d00f18a98a4dc12 100644 (file)
@@ -6999,6 +6999,8 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
        if (cctx->ctx_skip != SKIP_YES)
        {
            type_T      *stacktype;
+           int         needed_list_len;
+           int         did_check = FALSE;
 
            stacktype = stack->ga_len == 0 ? &t_void
                              : ((type_T **)stack->ga_data)[stack->ga_len - 1];
@@ -7010,9 +7012,26 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
            if (need_type(stacktype, &t_list_any, -1, 0, cctx,
                                                         FALSE, FALSE) == FAIL)
                goto theend;
-           // TODO: check the length of a constant list here
-           generate_CHECKLEN(cctx, semicolon ? var_count - 1 : var_count,
-                                                                   semicolon);
+           // If a constant list was used we can check the length right here.
+           needed_list_len = semicolon ? var_count - 1 : var_count;
+           if (instr->ga_len > 0)
+           {
+               isn_T   *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
+
+               if (isn->isn_type == ISN_NEWLIST)
+               {
+                   did_check = TRUE;
+                   if (semicolon ? isn->isn_arg.number < needed_list_len
+                           : isn->isn_arg.number != needed_list_len)
+                   {
+                       semsg(_(e_expected_nr_items_but_got_nr),
+                                        needed_list_len, isn->isn_arg.number);
+                       goto theend;
+                   }
+               }
+           }
+           if (!did_check)
+               generate_CHECKLEN(cctx, needed_list_len, semicolon);
            if (stacktype->tt_member != NULL)
                rhs_type = stacktype->tt_member;
        }