changeset 22266:23f5750146d9 v8.2.1682

patch 8.2.1682: Vim9: const works in an unexpected way Commit: https://github.com/vim/vim/commit/dbeecb2b6bc5bf90b7345807e0a313fe890a7c7b Author: Bram Moolenaar <Bram@vim.org> 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.
author Bram Moolenaar <Bram@vim.org>
date Mon, 14 Sep 2020 18:30:04 +0200
parents 2156b72e9b6b
children 65a5797b155f
files src/evalvars.c src/testdir/test_vim9_script.vim src/version.c src/vim9compile.c
diffstat 4 files changed, 20 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- 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.
--- 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()
--- 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,
--- 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)
 	{