summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-12-01 17:38:01 +0000
committerBram Moolenaar <Bram@vim.org>2021-12-01 17:38:01 +0000
commitdb9ff9ab5d7ce1fcc2c4106e7ad49151a323996c (patch)
tree1350ceab93989980581bc2b3511de6d5fc2a7a1a
parente4eed8c6db693a9183b776032570ce2f89dcffb6 (diff)
patch 8.2.3717: Vim9: error for constant list size is only given at runtimev8.2.3717
Problem: Vim9: error for constant list size is only given at runtime. Solution: Give the error at compile time if possible.
-rw-r--r--src/testdir/test_vim9_assign.vim21
-rw-r--r--src/testdir/test_vim9_disassemble.vim1
-rw-r--r--src/testdir/test_vim9_script.vim6
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c25
5 files changed, 49 insertions, 6 deletions
diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim
index 87924c6294..d191ac0bdf 100644
--- 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)
diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim
index 1c6b4bb3a2..184f557586 100644
--- 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*' ..
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index 989627f95f..40833c51c6 100644
--- 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
diff --git a/src/version.c b/src/version.c
index 5724eeccd4..c5e5f6b351 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 */
/**/
+ 3717,
+/**/
3716,
/**/
3715,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index a8e2c121d6..70cf0b4e99 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -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;
}