Skip to content

Commit dbeecb2

Browse files
committed
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.
1 parent 0805222 commit dbeecb2

4 files changed

Lines changed: 20 additions & 9 deletions

File tree

src/evalvars.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2945,6 +2945,7 @@ set_var_const(
29452945
char_u *varname;
29462946
hashtab_T *ht;
29472947
int is_script_local;
2948+
int vim9script = in_vim9script();
29482949

29492950
ht = find_var_ht(name, &varname);
29502951
if (ht == NULL || *varname == NUL)
@@ -2954,7 +2955,7 @@ set_var_const(
29542955
}
29552956
is_script_local = ht == get_script_local_ht();
29562957

2957-
if (in_vim9script()
2958+
if (vim9script
29582959
&& !is_script_local
29592960
&& (flags & LET_NO_COMMAND) == 0
29602961
&& name[1] == ':')
@@ -2992,7 +2993,7 @@ set_var_const(
29922993
goto failed;
29932994
}
29942995

2995-
if (is_script_local && in_vim9script())
2996+
if (is_script_local && vim9script)
29962997
{
29972998
if ((flags & LET_NO_COMMAND) == 0)
29982999
{
@@ -3088,7 +3089,7 @@ set_var_const(
30883089
if (flags & LET_IS_CONST)
30893090
di->di_flags |= DI_FLAGS_LOCK;
30903091

3091-
if (is_script_local && in_vim9script())
3092+
if (is_script_local && vim9script)
30923093
{
30933094
scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
30943095

@@ -3123,7 +3124,8 @@ set_var_const(
31233124
init_tv(tv);
31243125
}
31253126

3126-
if (flags & LET_IS_CONST)
3127+
// ":const var = val" locks the value, but not in Vim9 script
3128+
if ((flags & LET_IS_CONST) && !vim9script)
31273129
// Like :lockvar! name: lock the value and what it contains, but only
31283130
// if the reference count is up to one. That locks only literal
31293131
// values.

src/testdir/test_vim9_script.vim

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -821,8 +821,15 @@ enddef
821821
def Test_const()
822822
CheckDefFailure(['const var = 234', 'var = 99'], 'E1018:')
823823
CheckDefFailure(['const one = 234', 'let one = 99'], 'E1017:')
824+
CheckDefFailure(['const list = [1, 2]', 'let list = [3, 4]'], 'E1017:')
824825
CheckDefFailure(['const two'], 'E1021:')
825826
CheckDefFailure(['const &option'], 'E996:')
827+
828+
let lines =<< trim END
829+
const list = [1, 2, 3]
830+
list[0] = 4
831+
END
832+
CheckDefAndScriptSuccess(lines)
826833
enddef
827834

828835
def Test_range_no_colon()

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,8 @@ static char *(features[]) =
750750

751751
static int included_patches[] =
752752
{ /* Add new patch number below this line */
753+
/**/
754+
1682,
753755
/**/
754756
1681,
755757
/**/

src/vim9compile.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4800,11 +4800,6 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
48004800
semsg(_(e_variable_already_declared), name);
48014801
goto theend;
48024802
}
4803-
else if (lvar->lv_const)
4804-
{
4805-
semsg(_(e_cannot_assign_to_constant), name);
4806-
goto theend;
4807-
}
48084803
}
48094804
else
48104805
{
@@ -4960,6 +4955,11 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
49604955
semsg(_(e_cannot_assign_to_argument), name);
49614956
goto theend;
49624957
}
4958+
if (!is_decl && lvar != NULL && lvar->lv_const && !has_index)
4959+
{
4960+
semsg(_(e_cannot_assign_to_constant), name);
4961+
goto theend;
4962+
}
49634963

49644964
if (!heredoc)
49654965
{

0 commit comments

Comments
 (0)