# HG changeset patch # User Bram Moolenaar # Date 1600101004 -7200 # Node ID 23f5750146d9aa5bfb4ff5c56c5628c8d46befc3 # Parent 2156b72e9b6bb3cbeafd00decc9f82f842a78238 patch 8.2.1682: Vim9: const works in an unexpected way Commit: https://github.com/vim/vim/commit/dbeecb2b6bc5bf90b7345807e0a313fe890a7c7b Author: Bram Moolenaar Date: Mon Sep 14 18:15:09 2020 +0200 patch 8.2.1682: Vim9: const works in an unexpected way Problem: Vim9: const works in an unexpected way. Solution: ":const" only disallows changing the variable, not the value. Make "list[0] = 9" work at the script level. diff --git a/src/evalvars.c b/src/evalvars.c --- a/src/evalvars.c +++ b/src/evalvars.c @@ -2945,6 +2945,7 @@ set_var_const( char_u *varname; hashtab_T *ht; int is_script_local; + int vim9script = in_vim9script(); ht = find_var_ht(name, &varname); if (ht == NULL || *varname == NUL) @@ -2954,7 +2955,7 @@ set_var_const( } is_script_local = ht == get_script_local_ht(); - if (in_vim9script() + if (vim9script && !is_script_local && (flags & LET_NO_COMMAND) == 0 && name[1] == ':') @@ -2992,7 +2993,7 @@ set_var_const( goto failed; } - if (is_script_local && in_vim9script()) + if (is_script_local && vim9script) { if ((flags & LET_NO_COMMAND) == 0) { @@ -3088,7 +3089,7 @@ set_var_const( if (flags & LET_IS_CONST) di->di_flags |= DI_FLAGS_LOCK; - if (is_script_local && in_vim9script()) + if (is_script_local && vim9script) { scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); @@ -3123,7 +3124,8 @@ set_var_const( init_tv(tv); } - if (flags & LET_IS_CONST) + // ":const var = val" locks the value, but not in Vim9 script + if ((flags & LET_IS_CONST) && !vim9script) // Like :lockvar! name: lock the value and what it contains, but only // if the reference count is up to one. That locks only literal // values. diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -821,8 +821,15 @@ enddef def Test_const() CheckDefFailure(['const var = 234', 'var = 99'], 'E1018:') CheckDefFailure(['const one = 234', 'let one = 99'], 'E1017:') + CheckDefFailure(['const list = [1, 2]', 'let list = [3, 4]'], 'E1017:') CheckDefFailure(['const two'], 'E1021:') CheckDefFailure(['const &option'], 'E996:') + + let lines =<< trim END + const list = [1, 2, 3] + list[0] = 4 + END + CheckDefAndScriptSuccess(lines) enddef def Test_range_no_colon() diff --git a/src/version.c b/src/version.c --- 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 */ /**/ + 1682, +/**/ 1681, /**/ 1680, diff --git a/src/vim9compile.c b/src/vim9compile.c --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -4800,11 +4800,6 @@ compile_assignment(char_u *arg, exarg_T semsg(_(e_variable_already_declared), name); goto theend; } - else if (lvar->lv_const) - { - semsg(_(e_cannot_assign_to_constant), name); - goto theend; - } } else { @@ -4960,6 +4955,11 @@ compile_assignment(char_u *arg, exarg_T semsg(_(e_cannot_assign_to_argument), name); goto theend; } + if (!is_decl && lvar != NULL && lvar->lv_const && !has_index) + { + semsg(_(e_cannot_assign_to_constant), name); + goto theend; + } if (!heredoc) {