changeset 24614:07b3d21a8b4b v8.2.2846

patch 8.2.2846: Vim9: "echo Func()" does not give an error for using void Commit: https://github.com/vim/vim/commit/68db996b621b98066fb7ab7028ed5c6aaa3954a8 Author: Bram Moolenaar <Bram@vim.org> Date: Sun May 9 23:19:22 2021 +0200 patch 8.2.2846: Vim9: "echo Func()" does not give an error for using void Problem: Vim9: "echo Func()" does not give an error for a function without a return value. Solution: Give an error. Be more specific about why a value is invalid.
author Bram Moolenaar <Bram@vim.org>
date Sun, 09 May 2021 23:30:05 +0200
parents 2ccff0c26a2f
children ae9123ea11af
files src/errors.h src/eval.c src/evalfunc.c src/globals.h src/testdir/test_vim9_cmd.vim src/typval.c src/version.c src/vim9compile.c src/vim9execute.c
diffstat 9 files changed, 65 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/errors.h
+++ b/src/errors.h
@@ -31,6 +31,8 @@ EXTERN char e_cannot_slice_dictionary[]
 	INIT(= N_("E719: Cannot slice a Dictionary"));
 EXTERN char e_assert_fails_second_arg[]
 	INIT(= N_("E856: \"assert_fails()\" second argument must be a string or a list with one or two strings"));
+EXTERN char e_using_invalid_value_as_string_str[]
+	INIT(= N_("E908: using an invalid value as a String: %s"));
 EXTERN char e_cannot_index_special_variable[]
 	INIT(= N_("E909: Cannot index a special variable"));
 #endif
@@ -409,3 +411,5 @@ EXTERN char e_cannot_nest_redir[]
 	INIT(= N_("E1185: Cannot nest :redir"));
 EXTERN char e_missing_redir_end[]
 	INIT(= N_("E1185: Missing :redir END"));
+EXTERN char e_expression_does_not_result_in_value_str[]
+	INIT(= N_("E1186: Expression does not result in a value: %s"));
--- a/src/eval.c
+++ b/src/eval.c
@@ -2951,7 +2951,8 @@ eval5(char_u **arg, typval_T *rettv, eva
 		if (vim9script && (var2.v_type == VAR_VOID
 			|| var2.v_type == VAR_CHANNEL
 			|| var2.v_type == VAR_JOB))
-		    emsg(_(e_inval_string));
+		    semsg(_(e_using_invalid_value_as_string_str),
+						   vartype_name(var2.v_type));
 #ifdef FEAT_FLOAT
 		else if (vim9script && var2.v_type == VAR_FLOAT)
 		{
@@ -6110,7 +6111,7 @@ ex_echo(exarg_T *eap)
 {
     char_u	*arg = eap->arg;
     typval_T	rettv;
-    char_u	*p;
+    char_u	*arg_start;
     int		needclr = TRUE;
     int		atstart = TRUE;
     int		did_emsg_before = did_emsg;
@@ -6127,7 +6128,7 @@ ex_echo(exarg_T *eap)
 	// still need to be cleared. E.g., "echo 22,44".
 	need_clr_eos = needclr;
 
-	p = arg;
+	arg_start = arg;
 	if (eval1(&arg, &rettv, &evalarg) == FAIL)
 	{
 	    /*
@@ -6137,14 +6138,21 @@ ex_echo(exarg_T *eap)
 	     */
 	    if (!aborting() && did_emsg == did_emsg_before
 					  && called_emsg == called_emsg_before)
-		semsg(_(e_invexpr2), p);
+		semsg(_(e_invexpr2), arg_start);
 	    need_clr_eos = FALSE;
 	    break;
 	}
 	need_clr_eos = FALSE;
 
 	if (!eap->skip)
+	{
+	    if (rettv.v_type == VAR_VOID)
+	    {
+		semsg(_(e_expression_does_not_result_in_value_str), arg_start);
+		break;
+	    }
 	    echo_one(&rettv, eap->cmdidx == CMD_echo, &atstart, &needclr);
+	}
 
 	clear_tv(&rettv);
 	arg = skipwhite(arg);
@@ -6218,7 +6226,8 @@ ex_execute(exarg_T *eap)
 	    {
 		if (rettv.v_type == VAR_CHANNEL || rettv.v_type == VAR_JOB)
 		{
-		    emsg(_(e_inval_string));
+		    semsg(_(e_using_invalid_value_as_string_str),
+						  vartype_name(rettv.v_type));
 		    p = NULL;
 		}
 		else
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -3175,7 +3175,8 @@ execute_common(typval_T *argvars, typval
     else if (argvars[arg_off].v_type == VAR_JOB
 	    || argvars[arg_off].v_type == VAR_CHANNEL)
     {
-	emsg(_(e_inval_string));
+	semsg(_(e_using_invalid_value_as_string_str),
+				       vartype_name(argvars[arg_off].v_type));
 	return;
     }
     else
--- a/src/globals.h
+++ b/src/globals.h
@@ -1728,7 +1728,6 @@ EXTERN char e_list_end[]	INIT(= N_("E697
 EXTERN char e_listdictarg[]	INIT(= N_("E712: Argument of %s must be a List or Dictionary"));
 EXTERN char e_listdictblobarg[]	INIT(= N_("E896: Argument of %s must be a List, Dictionary or Blob"));
 EXTERN char e_modulus[]		INIT(= N_("E804: Cannot use '%' with Float"));
-EXTERN char e_inval_string[]	INIT(= N_("E908: using an invalid value as a String"));
 EXTERN char e_const_option[]	INIT(= N_("E996: Cannot lock an option"));
 EXTERN char e_unknown_option[]	INIT(= N_("E113: Unknown option: %s"));
 EXTERN char e_letunexp[]	INIT(= N_("E18: Unexpected characters in :let"));
--- a/src/testdir/test_vim9_cmd.vim
+++ b/src/testdir/test_vim9_cmd.vim
@@ -1282,5 +1282,28 @@ def Test_redir_to_var()
   CheckDefFailure(lines, 'E1141:')
 enddef
 
+def Test_echo_void()
+  var lines =<< trim END
+      vim9script
+      def NoReturn()
+        echo 'nothing'
+      enddef
+      echo NoReturn()
+  END
+  CheckScriptFailure(lines, 'E1186:', 5)
+
+  lines =<< trim END
+      vim9script
+      def NoReturn()
+        echo 'nothing'
+      enddef
+      def Try()
+        echo NoReturn()
+      enddef
+      defcompile
+  END
+  CheckScriptFailure(lines, 'E1186:', 1)
+enddef
+
 
 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
--- a/src/typval.c
+++ b/src/typval.c
@@ -522,7 +522,8 @@ tv_get_string_buf_chk_strict(typval_T *v
 	case VAR_ANY:
 	case VAR_VOID:
 	case VAR_INSTR:
-	    emsg(_(e_inval_string));
+	    semsg(_(e_using_invalid_value_as_string_str),
+						  vartype_name(varp->v_type));
 	    break;
     }
     return NULL;
--- 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 */
 /**/
+    2846,
+/**/
     2845,
 /**/
     2844,
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -8375,15 +8375,31 @@ compile_mult_expr(char_u *arg, int cmdid
 {
     char_u	*p = arg;
     char_u	*prev = arg;
+    char_u	*expr_start;
     int		count = 0;
     int		start_ctx_lnum = cctx->ctx_lnum;
+    garray_T	*stack = &cctx->ctx_type_stack;
+    type_T	*type;
 
     for (;;)
     {
 	if (ends_excmd2(prev, p))
 	    break;
+	expr_start = p;
 	if (compile_expr0(&p, cctx) == FAIL)
 	    return NULL;
+
+	if (cctx->ctx_skip != SKIP_YES)
+	{
+	    // check for non-void type
+	    type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
+	    if (type->tt_type == VAR_VOID)
+	    {
+		semsg(_(e_expression_does_not_result_in_value_str), expr_start);
+		return NULL;
+	    }
+	}
+
 	++count;
 	prev = p;
 	p = skipwhite(p);
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -1578,7 +1578,8 @@ exec_instructions(ectx_T *ectx)
 						      || tv->v_type == VAR_JOB)
 			    {
 				SOURCING_LNUM = iptr->isn_lnum;
-				emsg(_(e_inval_string));
+				semsg(_(e_using_invalid_value_as_string_str),
+						    vartype_name(tv->v_type));
 				break;
 			    }
 			    else