To: vim_dev@googlegroups.com Subject: Patch 8.2.2722 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.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. Files: src/vim9compile.c, src/eval.c, src/testdir/test_vim9_assign.vim *** ../vim-8.2.2721/src/vim9compile.c 2021-04-05 19:41:17.139727625 +0200 --- src/vim9compile.c 2021-04-05 20:37:01.715411366 +0200 *************** *** 6094,6099 **** --- 6094,6141 ---- } /* + * 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,6114 **** 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; --- 6148,6154 ---- *************** *** 6147,6178 **** // - 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 (dest_type == VAR_LIST || dest_type == VAR_DICT || dest_type == VAR_ANY) { --- 6187,6194 ---- // - index // - for [a : b] second index // - variable ! 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,6391 **** // for "+=", "*=", "..=" etc. first load the current value if (*op != '=') { ! generate_loadvar(cctx, lhs.lhs_dest, lhs.lhs_name, ! lhs.lhs_lvar, lhs.lhs_type); if (lhs.lhs_has_index) { --- 6400,6406 ---- // for "+=", "*=", "..=" etc. first load the current value if (*op != '=') { ! compile_load_lhs(&lhs, var_start, NULL, cctx); if (lhs.lhs_has_index) { *** ../vim-8.2.2721/src/eval.c 2021-04-04 21:55:19.688076468 +0200 --- src/eval.c 2021-04-05 20:47:30.425373515 +0200 *************** *** 1474,1480 **** { if (op != NULL && *op != '=') { ! semsg(_(e_letwrong), op); return; } --- 1474,1480 ---- { if (op != NULL && *op != '=') { ! semsg(_(e_dictkey), lp->ll_newkey); return; } *** ../vim-8.2.2721/src/testdir/test_vim9_assign.vim 2021-04-05 17:11:11.093726064 +0200 --- src/testdir/test_vim9_assign.vim 2021-04-05 20:48:05.617270128 +0200 *************** *** 1146,1151 **** --- 1146,1157 ---- assert_equal(2, dn.a) dn.a %= 6 assert_equal(2, dn.a) + + var dd: dict>> + dd.a = {} + dd.a.b = [0] + dd.a.b += [1] + assert_equal({a: {b: [0, 1]}}, dd) END CheckDefAndScriptSuccess(lines) enddef *************** *** 1187,1192 **** --- 1193,1205 ---- s[1] ..= 'x' END CheckDefAndScriptFailure2(lines, 'E1141:', 'E689:', 2) + + lines =<< trim END + var dd: dict>> + dd.a = {} + dd.a.b += [1] + END + CheckDefExecAndScriptFailure(lines, 'E716:', 3) enddef def Test_assign_lambda() *** ../vim-8.2.2721/src/version.c 2021-04-05 19:41:17.139727625 +0200 --- src/version.c 2021-04-05 20:50:16.248891957 +0200 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 2722, /**/ -- hundred-and-one symptoms of being an internet addict: 66. You create a homepage with the impression to cure the afflicted...but your hidden agenda is to receive more e-mail. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///