diff options
author | Bram Moolenaar <Bram@vim.org> | 2021-12-01 17:38:01 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2021-12-01 17:38:01 +0000 |
commit | db9ff9ab5d7ce1fcc2c4106e7ad49151a323996c (patch) | |
tree | 1350ceab93989980581bc2b3511de6d5fc2a7a1a | |
parent | e4eed8c6db693a9183b776032570ce2f89dcffb6 (diff) | |
download | vim-git-db9ff9ab5d7ce1fcc2c4106e7ad49151a323996c.tar.gz |
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.vim | 21 | ||||
-rw-r--r-- | src/testdir/test_vim9_disassemble.vim | 1 | ||||
-rw-r--r-- | src/testdir/test_vim9_script.vim | 6 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9compile.c | 25 |
5 files changed, 49 insertions, 6 deletions
diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim index 87924c629..d191ac0bd 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 1c6b4bb3a..184f55758 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 989627f95..40833c51c 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 5724eeccd..c5e5f6b35 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 a8e2c121d..70cf0b4e9 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; } |