changeset 26372:f5727e2603f0 v8.2.3717

patch 8.2.3717: Vim9: error for constant list size is only given at runtime Commit: https://github.com/vim/vim/commit/db9ff9ab5d7ce1fcc2c4106e7ad49151a323996c Author: Bram Moolenaar <Bram@vim.org> Date: Wed Dec 1 17:38:01 2021 +0000 patch 8.2.3717: Vim9: error for constant list size is only given at runtime Problem: Vim9: error for constant list size is only given at runtime. Solution: Give the error at compile time if possible.
author Bram Moolenaar <Bram@vim.org>
date Wed, 01 Dec 2021 18:45:03 +0100
parents 7f4ef8856810
children a9d498b069f3
files src/testdir/test_vim9_assign.vim src/testdir/test_vim9_disassemble.vim src/testdir/test_vim9_script.vim src/version.c src/vim9compile.c
diffstat 5 files changed, 49 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/testdir/test_vim9_assign.vim
+++ b/src/testdir/test_vim9_assign.vim
@@ -386,6 +386,27 @@ def Test_assign_unpack()
   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
       [v1, v2] = 
   END
   CheckDefFailure(lines, 'E1097:', 5)
--- a/src/testdir/test_vim9_disassemble.vim
+++ b/src/testdir/test_vim9_disassemble.vim
@@ -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*' ..
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -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
--- 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 */
 /**/
+    3717,
+/**/
     3716,
 /**/
     3715,
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -6999,6 +6999,8 @@ compile_assignment(char_u *arg, exarg_T 
 	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 
 	    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;
 	}