changeset 21646:a640bc762196 v8.2.1373

patch 8.2.1373: Vim9: no error for assigning to non-existing script var Commit: https://github.com/vim/vim/commit/f9b2b49663226235f94f08230fe9023caf80a6e9 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Aug 5 14:34:14 2020 +0200 patch 8.2.1373: Vim9: no error for assigning to non-existing script var Problem: Vim9: no error for assigning to non-existing script var. Solution: Check that in Vim9 script the variable was defined. (closes https://github.com/vim/vim/issues/6630)
author Bram Moolenaar <Bram@vim.org>
date Wed, 05 Aug 2020 14:45:03 +0200
parents 5c2e5c71c08c
children 03d8640840f5
files src/structs.h src/testdir/test_vim9_script.vim src/userfunc.c src/version.c src/vim9compile.c
diffstat 5 files changed, 69 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/src/structs.h
+++ b/src/structs.h
@@ -1594,7 +1594,9 @@ typedef struct
     int		uf_tml_execed;	// line being timed was executed
 # endif
     sctx_T	uf_script_ctx;	// SCTX where function was defined,
-				// used for s: variables
+				// used for s: variables; sc_version changed
+				// for :function
+    int		uf_script_ctx_version;  // original sc_version of SCTX
     int		uf_refcount;	// reference count, see func_name_refcount()
 
     funccall_T	*uf_scoped;	// l: local variables for closure
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -112,6 +112,15 @@ def Test_assignment()
   call CheckDefFailure(['let s:var = 123'], 'E1101:')
   call CheckDefFailure(['let s:var: number'], 'E1101:')
 
+  lines =<< trim END
+    vim9script
+    def SomeFunc()
+      s:var = 123
+    enddef
+    defcompile
+  END
+  call CheckScriptFailure(lines, 'E1089:')
+
   g:inc_counter += 1
   assert_equal(2, g:inc_counter)
 
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -3508,6 +3508,7 @@ def_function(exarg_T *eap, char_u *name_
     fp->uf_calls = 0;
     fp->uf_cleared = FALSE;
     fp->uf_script_ctx = current_sctx;
+    fp->uf_script_ctx_version = current_sctx.sc_version;
     fp->uf_script_ctx.sc_lnum += sourcing_lnum_top;
     if (is_export)
     {
--- 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 */
 /**/
+    1373,
+/**/
     1372,
 /**/
     1371,
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -148,6 +148,7 @@ static char e_syntax_at[] = N_("E1002: S
 static char e_used_as_arg[] = N_("E1006: %s is used as an argument");
 static char e_cannot_use_void[] = N_("E1031: Cannot use void value");
 static char e_namespace[] = N_("E1075: Namespace not supported: %s");
+static char e_unknown_var[] = N_("E1089: unknown variable: %s");
 
 static void delete_def_function_contents(dfunc_T *dfunc);
 static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
@@ -5335,7 +5336,6 @@ compile_assignment(char_u *arg, exarg_T 
 	    else
 	    {
 		int	    idx;
-		imported_T  *import = NULL;
 
 		for (idx = 0; reserved[idx] != NULL; ++idx)
 		    if (STRCMP(reserved[idx], name) == 0)
@@ -5374,50 +5374,68 @@ compile_assignment(char_u *arg, exarg_T 
 			goto theend;
 		    }
 		}
-		else if ((varlen > 1 && STRNCMP(var_start, "s:", 2) == 0)
-			|| lookup_script(var_start, varlen) == OK
-			|| (import = find_imported(var_start, varlen, cctx))
-								       != NULL)
+		else
 		{
-		    char_u	*rawname = name + (name[1] == ':' ? 2 : 0);
-
-		    if (is_decl)
+		    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;
+		    imported_T  *import =
+					find_imported(var_start, varlen, cctx);
+
+		    if (script_namespace || script_var || import != NULL)
 		    {
-			if ((varlen > 1 && STRNCMP(var_start, "s:", 2) == 0))
-			    semsg(_("E1101: Cannot declare a script variable in a function: %s"),
+			char_u	*rawname = name + (name[1] == ':' ? 2 : 0);
+
+			if (is_decl)
+			{
+			    if (script_namespace)
+				semsg(_("E1101: Cannot declare a script variable in a function: %s"),
+									 name);
+			    else
+				semsg(_("E1054: Variable already declared in the script: %s"),
 									 name);
-			else
-			    semsg(_("E1054: Variable already declared in the script: %s"),
+			    goto theend;
+			}
+			else if (cctx->ctx_ufunc->uf_script_ctx_version
+							== SCRIPT_VERSION_VIM9
+				&& script_namespace
+					      && !script_var && import == NULL)
+			{
+			    semsg(_(e_unknown_var), name);
+			    goto theend;
+			}
+
+			dest = dest_script;
+
+			// existing script-local variables should have a type
+			scriptvar_sid = current_sctx.sc_sid;
+			if (import != NULL)
+			    scriptvar_sid = import->imp_sid;
+			scriptvar_idx = get_script_item_idx(scriptvar_sid,
+								rawname, TRUE);
+			if (scriptvar_idx >= 0)
+			{
+			    scriptitem_T *si = SCRIPT_ITEM(scriptvar_sid);
+			    svar_T	     *sv =
+					    ((svar_T *)si->sn_var_vals.ga_data)
+							       + scriptvar_idx;
+			    type = sv->sv_type;
+			}
+		    }
+		    else if (name[1] == ':' && name[2] != NUL)
+		    {
+			semsg(_("E1082: Cannot use a namespaced variable: %s"),
 									 name);
 			goto theend;
 		    }
-		    dest = dest_script;
-
-		    // existing script-local variables should have a type
-		    scriptvar_sid = current_sctx.sc_sid;
-		    if (import != NULL)
-			scriptvar_sid = import->imp_sid;
-		    scriptvar_idx = get_script_item_idx(scriptvar_sid,
-								rawname, TRUE);
-		    if (scriptvar_idx >= 0)
+		    else if (!is_decl)
 		    {
-			scriptitem_T *si = SCRIPT_ITEM(scriptvar_sid);
-			svar_T	     *sv = ((svar_T *)si->sn_var_vals.ga_data)
-							       + scriptvar_idx;
-			type = sv->sv_type;
+			semsg(_(e_unknown_var), name);
+			goto theend;
 		    }
 		}
-		else if (name[1] == ':' && name[2] != NUL)
-		{
-		    semsg(_("E1082: Cannot use a namespaced variable: %s"),
-									 name);
-		    goto theend;
-		}
-		else if (!is_decl)
-		{
-		    semsg(_("E1089: unknown variable: %s"), name);
-		    goto theend;
-		}
 	    }
 
 	    if (declare_error)