diff options
author | Bram Moolenaar <Bram@vim.org> | 2021-04-05 20:51:00 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2021-04-05 20:51:00 +0200 |
commit | b9c0cd897ab4ad54f514187e89719c0241393f8b (patch) | |
tree | d77cabb1e4f17c9221586b923a8b56888e138ba5 /src | |
parent | 2927c07b0ec627c13e863e1b84bec831743bce12 (diff) |
patch 8.2.2722: Vim9: crash when using LHS with double indexv8.2.2722
Problem: Vim9: crash when using LHS with double index.
Solution: Handle lhs_dest which is "dest_expr". (closes #8068)
Fix confusing error message for missing dict item.
Diffstat (limited to 'src')
-rw-r--r-- | src/eval.c | 2 | ||||
-rw-r--r-- | src/testdir/test_vim9_assign.vim | 13 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9compile.c | 75 |
4 files changed, 61 insertions, 31 deletions
diff --git a/src/eval.c b/src/eval.c index d49264997b..05b6584424 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1474,7 +1474,7 @@ set_var_lval( { if (op != NULL && *op != '=') { - semsg(_(e_letwrong), op); + semsg(_(e_dictkey), lp->ll_newkey); return; } diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim index 4e37efb282..4e78b5d5b5 100644 --- a/src/testdir/test_vim9_assign.vim +++ b/src/testdir/test_vim9_assign.vim @@ -1146,6 +1146,12 @@ def Test_assign_dict_with_op() assert_equal(2, dn.a) dn.a %= 6 assert_equal(2, dn.a) + + var dd: dict<dict<list<any>>> + dd.a = {} + dd.a.b = [0] + dd.a.b += [1] + assert_equal({a: {b: [0, 1]}}, dd) END CheckDefAndScriptSuccess(lines) enddef @@ -1187,6 +1193,13 @@ def Test_assign_with_op_fails() s[1] ..= 'x' END CheckDefAndScriptFailure2(lines, 'E1141:', 'E689:', 2) + + lines =<< trim END + var dd: dict<dict<list<any>>> + dd.a = {} + dd.a.b += [1] + END + CheckDefExecAndScriptFailure(lines, 'E716:', 3) enddef def Test_assign_lambda() diff --git a/src/version.c b/src/version.c index 331ccdbadc..807ef10b86 100644 --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2722, +/**/ 2721, /**/ 2720, diff --git a/src/vim9compile.c b/src/vim9compile.c index 678a985288..6ff00f7d49 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -6094,6 +6094,48 @@ compile_assign_index( } /* + * For a LHS with an index, load the variable to be indexed. + */ + static int +compile_load_lhs( + lhs_T *lhs, + char_u *var_start, + type_T *rhs_type, + cctx_T *cctx) +{ + if (lhs->lhs_dest == dest_expr) + { + size_t varlen = lhs->lhs_varlen; + int c = var_start[varlen]; + char_u *p = var_start; + garray_T *stack = &cctx->ctx_type_stack; + + // Evaluate "ll[expr]" of "ll[expr][idx]" + var_start[varlen] = NUL; + if (compile_expr0(&p, cctx) == OK && p != var_start + varlen) + { + // this should not happen + emsg(_(e_missbrac)); + return FAIL; + } + var_start[varlen] = c; + + lhs->lhs_type = stack->ga_len == 0 ? &t_void + : ((type_T **)stack->ga_data)[stack->ga_len - 1]; + // now we can properly check the type + if (rhs_type != NULL && lhs->lhs_type->tt_member != NULL + && rhs_type != &t_void + && need_type(rhs_type, lhs->lhs_type->tt_member, -2, 0, cctx, + FALSE, FALSE) == FAIL) + return FAIL; + } + else + generate_loadvar(cctx, lhs->lhs_dest, lhs->lhs_name, + lhs->lhs_lvar, lhs->lhs_type); + return OK; +} + +/* * Assignment to a list or dict member, or ":unlet" for the item, using the * information in "lhs". * Returns OK or FAIL. @@ -6106,9 +6148,7 @@ compile_assign_unlet( type_T *rhs_type, cctx_T *cctx) { - char_u *p; vartype_T dest_type; - size_t varlen = lhs->lhs_varlen; garray_T *stack = &cctx->ctx_type_stack; int range = FALSE; @@ -6147,32 +6187,8 @@ compile_assign_unlet( // - index // - for [a : b] second index // - variable - if (lhs->lhs_dest == dest_expr) - { - int c = var_start[varlen]; - - // Evaluate "ll[expr]" of "ll[expr][idx]" - p = var_start; - var_start[varlen] = NUL; - if (compile_expr0(&p, cctx) == OK && p != var_start + varlen) - { - // this should not happen - emsg(_(e_missbrac)); - return FAIL; - } - var_start[varlen] = c; - - lhs->lhs_type = stack->ga_len == 0 ? &t_void - : ((type_T **)stack->ga_data)[stack->ga_len - 1]; - // now we can properly check the type - if (lhs->lhs_type->tt_member != NULL && rhs_type != &t_void - && need_type(rhs_type, lhs->lhs_type->tt_member, -2, 0, cctx, - FALSE, FALSE) == FAIL) - return FAIL; - } - else - generate_loadvar(cctx, lhs->lhs_dest, lhs->lhs_name, - lhs->lhs_lvar, lhs->lhs_type); + if (compile_load_lhs(lhs, var_start, rhs_type, cctx) == FAIL) + return FAIL; if (dest_type == VAR_LIST || dest_type == VAR_DICT || dest_type == VAR_ANY) { @@ -6384,8 +6400,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) // for "+=", "*=", "..=" etc. first load the current value if (*op != '=') { - generate_loadvar(cctx, lhs.lhs_dest, lhs.lhs_name, - lhs.lhs_lvar, lhs.lhs_type); + compile_load_lhs(&lhs, var_start, NULL, cctx); if (lhs.lhs_has_index) { |