changeset 21839:c7699985db00 v8.2.1469

patch 8.2.1469: Vim9: cannot assign string to string option Commit: https://github.com/vim/vim/commit/0aae4809fd52b445531766411a9c963dc6274a04 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Aug 16 21:29:05 2020 +0200 patch 8.2.1469: Vim9: cannot assign string to string option Problem: Vim9: cannot assign string to string option. Solution: Change checks for option value. (closes https://github.com/vim/vim/issues/6720)
author Bram Moolenaar <Bram@vim.org>
date Sun, 16 Aug 2020 21:30:03 +0200
parents 3e44fb527472
children 5a6e009dc3f2
files src/evalvars.c src/testdir/test_vim9_script.vim src/version.c
diffstat 3 files changed, 57 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -1294,28 +1294,36 @@ ex_let_one(
 	    emsg(_(e_letunexp));
 	else
 	{
-	    long	n;
+	    long	n = 0;
 	    int		opt_type;
 	    long	numval;
 	    char_u	*stringval = NULL;
 	    char_u	*s = NULL;
+	    int		failed = FALSE;
 
 	    c1 = *p;
 	    *p = NUL;
 
-	    n = (long)tv_get_number(tv);
-	    // avoid setting a string option to the text "v:false" or similar.
-	    if (tv->v_type != VAR_BOOL && tv->v_type != VAR_SPECIAL)
-		s = tv_get_string_chk(tv);	// != NULL if number or string
-	    if (s != NULL && op != NULL && *op != '=')
+	    opt_type = get_option_value(arg, &numval, &stringval, opt_flags);
+	    if ((opt_type == 1 || opt_type == -1)
+			     && (tv->v_type != VAR_STRING || !in_vim9script()))
+		// number, possibly hidden
+		n = (long)tv_get_number(tv);
+
+	    // Avoid setting a string option to the text "v:false" or similar.
+	    // In Vim9 script also don't convert a number to string.
+	    if (tv->v_type != VAR_BOOL && tv->v_type != VAR_SPECIAL
+			     && (!in_vim9script() || tv->v_type != VAR_NUMBER))
+		s = tv_get_string_chk(tv);
+
+	    if (op != NULL && *op != '=')
 	    {
-		opt_type = get_option_value(arg, &numval,
-						       &stringval, opt_flags);
 		if ((opt_type == 1 && *op == '.')
 			|| (opt_type == 0 && *op != '.'))
 		{
 		    semsg(_(e_letwrong), op);
-		    s = NULL;  // don't set the value
+		    failed = TRUE;  // don't set the value
+
 		}
 		else
 		{
@@ -1330,19 +1338,25 @@ ex_let_one(
 			    case '%': n = (long)num_modulus(numval, n); break;
 			}
 		    }
-		    else if (opt_type == 0 && stringval != NULL) // string
+		    else if (opt_type == 0 && stringval != NULL && s != NULL)
 		    {
+			// string
 			s = concat_str(stringval, s);
 			vim_free(stringval);
 			stringval = s;
 		    }
 		}
 	    }
-	    if (s != NULL || tv->v_type == VAR_BOOL
-						  || tv->v_type == VAR_SPECIAL)
+
+	    if (!failed)
 	    {
-		set_option_value(arg, n, s, opt_flags);
-		arg_end = p;
+		if (opt_type != 0 || s != NULL)
+		{
+		    set_option_value(arg, n, s, opt_flags);
+		    arg_end = p;
+		}
+		else
+		    emsg(_(e_stringreq));
 	    }
 	    *p = c1;
 	    vim_free(stringval);
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -96,22 +96,36 @@ def Test_assignment()
     &ts += 3
     assert_equal(9, &ts)
   END
-  call CheckScriptSuccess(lines)
-
-  call CheckDefFailure(['&notex += 3'], 'E113:')
-  call CheckDefFailure(['&ts ..= "xxx"'], 'E1019:')
-  call CheckDefFailure(['&ts = [7]'], 'E1012:')
-  call CheckDefExecFailure(['&ts = g:alist'], 'E1029: Expected number but got list')
-  call CheckDefFailure(['&ts = "xx"'], 'E1012:')
-  call CheckDefExecFailure(['&ts = g:astring'], 'E1029: Expected number but got string')
-  call CheckDefFailure(['&path += 3'], 'E1012:')
-  call CheckDefExecFailure(['&bs = "asdf"'], 'E474:')
+  CheckScriptSuccess(lines)
+
+  CheckDefFailure(['&notex += 3'], 'E113:')
+  CheckDefFailure(['&ts ..= "xxx"'], 'E1019:')
+  CheckDefFailure(['&ts = [7]'], 'E1012:')
+  CheckDefExecFailure(['&ts = g:alist'], 'E1029: Expected number but got list')
+  CheckDefFailure(['&ts = "xx"'], 'E1012:')
+  CheckDefExecFailure(['&ts = g:astring'], 'E1029: Expected number but got string')
+  CheckDefFailure(['&path += 3'], 'E1012:')
+  CheckDefExecFailure(['&bs = "asdf"'], 'E474:')
   # test freeing ISN_STOREOPT
-  call CheckDefFailure(['&ts = 3', 'let asdf'], 'E1022:')
+  CheckDefFailure(['&ts = 3', 'let asdf'], 'E1022:')
   &ts = 8
 
-  call CheckDefFailure(['let s:var = 123'], 'E1101:')
-  call CheckDefFailure(['let s:var: number'], 'E1101:')
+  lines =<< trim END
+    let save_TI = &t_TI
+    &t_TI = ''
+    assert_equal('', &t_TI)
+    &t_TI = 'xxx'
+    assert_equal('xxx', &t_TI)
+    &t_TI = save_TI
+  END
+  CheckDefSuccess(lines)
+  CheckScriptSuccess(['vim9script'] + lines)
+
+  CheckDefFailure(['&t_TI = 123'], 'E1012:')
+  CheckScriptFailure(['vim9script', '&t_TI = 123'], 'E928:')
+
+  CheckDefFailure(['let s:var = 123'], 'E1101:')
+  CheckDefFailure(['let s:var: number'], 'E1101:')
 
   lines =<< trim END
     vim9script
--- 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 */
 /**/
+    1469,
+/**/
     1468,
 /**/
     1467,