# HG changeset patch # User Bram Moolenaar # Date 1624713303 -7200 # Node ID 3b8d3b383fd661de0feb4ed9782b6e5ebf85e7f1 # Parent 4a0d69a89bda2c98679d00aae37e4aa2b2f6d7f2 patch 8.2.3055: strange error for assigning to "x.key" on non-dictionary Commit: https://github.com/vim/vim/commit/3a3b10e87a10dd0bc355618dbfc4a0a6c828aad7 Author: Bram Moolenaar Date: Sat Jun 26 15:00:59 2021 +0200 patch 8.2.3055: strange error for assigning to "x.key" on non-dictionary Problem: Strange error for assigning to "x.key" on non-dictionary. Solution: Add a specific error message. (closes https://github.com/vim/vim/issues/8451) diff --git a/src/errors.h b/src/errors.h --- a/src/errors.h +++ b/src/errors.h @@ -448,3 +448,5 @@ EXTERN char e_libsodium_decryption_faile INIT(= N_("E1201: Decryption failed: pre-mature end of file!")); EXTERN char e_no_white_space_allowed_after_str_str[] INIT(= N_("E1202: No white space allowed after '%s': %s")); +EXTERN char e_dot_can_only_be_used_on_dictionary_str[] + INIT(= N_("E1203: Dot can only be used on a dictionary: %s")); diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -924,8 +924,14 @@ get_lval( lp->ll_tv = &v->di_tv; var1.v_type = VAR_UNKNOWN; var2.v_type = VAR_UNKNOWN; - while (*p == '[' || (*p == '.' && lp->ll_tv->v_type == VAR_DICT)) + while (*p == '[' || (*p == '.' && p[1] != '=' && p[1] != '.')) { + if (*p == '.' && lp->ll_tv->v_type != VAR_DICT) + { + if (!quiet) + semsg(_(e_dot_can_only_be_used_on_dictionary_str), name); + return NULL; + } if (!(lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list != NULL) && !(lp->ll_tv->v_type == VAR_DICT) && !(lp->ll_tv->v_type == VAR_BLOB diff --git a/src/testdir/test_let.vim b/src/testdir/test_let.vim --- a/src/testdir/test_let.vim +++ b/src/testdir/test_let.vim @@ -293,7 +293,7 @@ func Test_let_errors() let s = "var" let var = 1 call assert_fails('let var += [1,2]', 'E734:') - call assert_fails('let {s}.1 = 2', 'E18:') + call assert_fails('let {s}.1 = 2', 'E1203:') call assert_fails('let a[1] = 5', 'E121:') let l = [[1,2]] call assert_fails('let l[:][0] = [5]', 'E708:') diff --git a/src/testdir/test_listdict.vim b/src/testdir/test_listdict.vim --- a/src/testdir/test_listdict.vim +++ b/src/testdir/test_listdict.vim @@ -294,6 +294,9 @@ func Test_dict_assign() let d.1 = 1 let d._ = 2 call assert_equal({'1': 1, '_': 2}, d) + + let n = 0 + call assert_fails('let n.key = 3', 'E1203: Dot can only be used on a dictionary: n.key = 3') endfunc " Function in script-local List or Dict diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim --- a/src/testdir/test_vim9_assign.vim +++ b/src/testdir/test_vim9_assign.vim @@ -787,6 +787,12 @@ def Test_assignment_dict() d.dd[0] = 0 END CheckDefExecFailure(lines, 'E1148:', 2) + + lines =<< trim END + var n: any + n.key = 5 + END + CheckDefExecAndScriptFailure2(lines, 'E1148:', 'E1203: Dot can only be used on a dictionary: n.key = 5', 2) enddef def Test_assignment_local() diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -756,6 +756,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3055, +/**/ 3054, /**/ 3053,