From ad43d2639d4031ff1893bde763505e6d4d13a6ca Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Sun, 28 Sep 2025 17:17:37 +0000 Subject: [PATCH] patch 9.1.1801: Vim9: misleading error when extending dictionary Problem: Vim9: misleading error when extending dictionary (lacygoill) Solution: Give a proper error message when a Dict type is used with a compound operator (Yegappan Lakshmanan) fixes: #8072 closes: #18426 Signed-off-by: Yegappan Lakshmanan Signed-off-by: Christian Brabandt --- src/testdir/test_vim9_assign.vim | 13 +++++++++++ src/version.c | 2 ++ src/vim9compile.c | 37 ++++++++++++++++++++++++-------- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim index 6021148597..b7b09c9724 100644 --- a/src/testdir/test_vim9_assign.vim +++ b/src/testdir/test_vim9_assign.vim @@ -3414,6 +3414,19 @@ def Test_type_check() v9.CheckScriptFailure(lines, 'E1411: Missing dot after object "o"') enddef +" Test for using a compound operator with a dict +def Test_dict_compoundop_check() + for op in ['+=', '-=', '*=', '/=', '%='] + v9.CheckSourceDefAndScriptFailure(['var d: dict = {a: 1}', $'d {op} 1'], $'E734: Wrong variable type for {op}') + endfor + var lines =<< trim END + var d: dict = {a: 1} + d['a'] += 2 + assert_equal({a: 3}, d) + END + v9.CheckSourceDefAndScriptSuccess(lines) +enddef + " Test for checking the argument type of a def function def Test_func_argtype_check() var lines =<< trim END diff --git a/src/version.c b/src/version.c index 1faf29ad3c..47d461971d 100644 --- a/src/version.c +++ b/src/version.c @@ -729,6 +729,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1801, /**/ 1800, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 91c1c0c9ed..efbea59145 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -3438,6 +3438,27 @@ compile_assign_rhs(cctx_T *cctx, cac_T *cac) &cac->cac_skip_store); } +/* + * Returns OK if "type" supports compound operator "op_arg" (e.g. +=, -=, %=, + * etc.). Compound operators are not supported with a tuple and a dict. + * Returns FAIL if compound operator is not supported. + */ + static int +check_type_supports_compound_op(type_T *type, char_u op_arg) +{ + if (type->tt_type == VAR_TUPLE || type->tt_type == VAR_DICT) + { + char_u op[2]; + + op[0] = op_arg; + op[1] = NUL; + semsg(_(e_wrong_variable_type_for_str_equal), op); + return FAIL; + } + + return OK; +} + /* * Compile a compound op assignment statement (+=, -=, *=, %=, etc.) */ @@ -3448,16 +3469,10 @@ compile_assign_compound_op(cctx_T *cctx, cac_T *cac) type_T *expected; type_T *stacktype = NULL; - if (cac->cac_lhs.lhs_type->tt_type == VAR_TUPLE) - { - // compound operators are not supported with a tuple - char_u op[2]; - - op[0] = *cac->cac_op; - op[1] = NUL; - semsg(_(e_wrong_variable_type_for_str_equal), op); + if (cac->cac_lhs.lhs_type->tt_type == VAR_TUPLE + && check_type_supports_compound_op(cac->cac_lhs.lhs_type, + *cac->cac_op) == FAIL) return FAIL; - } if (*cac->cac_op == '.') { @@ -3474,6 +3489,10 @@ compile_assign_compound_op(cctx_T *cctx, cac_T *cac) { expected = lhs->lhs_member_type; stacktype = get_type_on_stack(cctx, 0); + + if (check_type_supports_compound_op(expected, *cac->cac_op) == FAIL) + return FAIL; + if ( // If variable is float operation with number is OK. !(expected == &t_float && (stacktype == &t_number