changeset 21921:e420f3cf60e2 v8.2.1510

patch 8.2.1510: using "var" in :def function may refer to legacy script var Commit: https://github.com/vim/vim/commit/5390099a9733f7952a612670693dd4ebf9e0e178 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Aug 22 19:02:02 2020 +0200 patch 8.2.1510: using "var" in :def function may refer to legacy script var Problem: Using "var" in a :def function may refer to a legacy Vim script variable. Solution: Require using "s:" to refer to a legacy Vim script variable. (closes #6771)
author Bram Moolenaar <Bram@vim.org>
date Sat, 22 Aug 2020 19:15:04 +0200
parents b7cac8d181c3
children bad21603b8c4
files src/testdir/test_vim9_func.vim src/version.c src/vim9compile.c
diffstat 3 files changed, 33 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -829,30 +829,30 @@ endfunc
 let s:funcResult = 0
 
 def FuncNoArgNoRet()
-  funcResult = 11
+  s:funcResult = 11
 enddef
 
 def FuncNoArgRetNumber(): number
-  funcResult = 22
+  s:funcResult = 22
   return 1234
 enddef
 
 def FuncNoArgRetString(): string
-  funcResult = 45
+  s:funcResult = 45
   return 'text'
 enddef
 
 def FuncOneArgNoRet(arg: number)
-  funcResult = arg
+  s:funcResult = arg
 enddef
 
 def FuncOneArgRetNumber(arg: number): number
-  funcResult = arg
+  s:funcResult = arg
   return arg
 enddef
 
 def FuncTwoArgNoRet(one: bool, two: number)
-  funcResult = two
+  s:funcResult = two
 enddef
 
 def FuncOneArgRetString(arg: string): string
@@ -865,31 +865,31 @@ enddef
 
 def Test_func_type()
   let Ref1: func()
-  funcResult = 0
+  s:funcResult = 0
   Ref1 = FuncNoArgNoRet
   Ref1()
-  assert_equal(11, funcResult)
+  assert_equal(11, s:funcResult)
 
   let Ref2: func
-  funcResult = 0
+  s:funcResult = 0
   Ref2 = FuncNoArgNoRet
   Ref2()
-  assert_equal(11, funcResult)
+  assert_equal(11, s:funcResult)
 
-  funcResult = 0
+  s:funcResult = 0
   Ref2 = FuncOneArgNoRet
   Ref2(12)
-  assert_equal(12, funcResult)
+  assert_equal(12, s:funcResult)
 
-  funcResult = 0
+  s:funcResult = 0
   Ref2 = FuncNoArgRetNumber
   assert_equal(1234, Ref2())
-  assert_equal(22, funcResult)
+  assert_equal(22, s:funcResult)
 
-  funcResult = 0
+  s:funcResult = 0
   Ref2 = FuncOneArgRetNumber
   assert_equal(13, Ref2(13))
-  assert_equal(13, funcResult)
+  assert_equal(13, s:funcResult)
 enddef
 
 def Test_repeat_return_type()
--- a/src/version.c
+++ b/src/version.c
@@ -755,6 +755,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1510,
+/**/
     1509,
 /**/
     1508,
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -260,15 +260,20 @@ lookup_arg(
 
 /*
  * Lookup a variable in the current script.
+ * If "vim9script" is TRUE the script must be Vim9 script.  Used for "var"
+ * without "s:".
  * Returns OK or FAIL.
  */
     static int
-lookup_script(char_u *name, size_t len)
+lookup_script(char_u *name, size_t len, int vim9script)
 {
     int		    cc;
     hashtab_T	    *ht = &SCRIPT_VARS(current_sctx.sc_sid);
     dictitem_T	    *di;
 
+    if (vim9script && SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
+							!= SCRIPT_VERSION_VIM9)
+	return FAIL;
     cc = name[len];
     name[len] = NUL;
     di = find_var_in_ht(ht, 0, name, TRUE);
@@ -287,7 +292,7 @@ check_defined(char_u *p, size_t len, cct
     int c = p[len];
 
     p[len] = NUL;
-    if (lookup_script(p, len) == OK
+    if (lookup_script(p, len, FALSE) == OK
 	    || (cctx != NULL
 		&& (lookup_local(p, len, cctx) != NULL
 		    || lookup_arg(p, len, NULL, NULL, NULL, cctx) == OK))
@@ -2145,15 +2150,14 @@ compile_load(char_u **arg, char_u *end_a
 	    else
 	    {
 		// "var" can be script-local even without using "s:" if it
-		// already exists.
-		if (SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
-						    == SCRIPT_VERSION_VIM9
-			    || lookup_script(*arg, len) == OK)
-		   res = compile_load_scriptvar(cctx, name, *arg, &end,
-								    FALSE);
+		// already exists in a Vim9 script or when it's imported.
+		if (lookup_script(*arg, len, TRUE) == OK
+			|| find_imported(name, 0, cctx) != NULL)
+		   res = compile_load_scriptvar(cctx, name, *arg, &end, FALSE);
 
 		// When the name starts with an uppercase letter or "x:" it
 		// can be a user defined function.
+		// TODO: this is just guessing
 		if (res == FAIL && (ASCII_ISUPPER(*name) || name[1] == ':'))
 		    res = generate_funcref(cctx, name);
 	    }
@@ -4697,8 +4701,8 @@ compile_assignment(char_u *arg, exarg_T 
 		    int script_namespace = varlen > 1
 					   && STRNCMP(var_start, "s:", 2) == 0;
 		    int script_var = (script_namespace
-				? lookup_script(var_start + 2, varlen - 2)
-				: lookup_script(var_start, varlen)) == OK;
+			      ? lookup_script(var_start + 2, varlen - 2, FALSE)
+			      : lookup_script(var_start, varlen, TRUE)) == OK;
 		    imported_T  *import =
 					find_imported(var_start, varlen, cctx);
 
@@ -6637,7 +6641,7 @@ compile_def_function(ufunc_T *ufunc, int
 			    || lookup_local(ea.cmd, len, &cctx) != NULL
 			    || lookup_arg(ea.cmd, len, NULL, NULL,
 							     NULL, &cctx) == OK
-			    || lookup_script(ea.cmd, len) == OK
+			    || lookup_script(ea.cmd, len, FALSE) == OK
 			    || find_imported(ea.cmd, len, &cctx) != NULL)
 		    {
 			line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);