changeset 32489:d6055989fa27 v9.0.1576

patch 9.0.1576: users may not know what to do with an internal error Commit: https://github.com/vim/vim/commit/097c5370ea8abab17ceb0f3bcd74f57b1655c7f7 Author: Bram Moolenaar <Bram@vim.org> Date: Wed May 24 21:02:24 2023 +0100 patch 9.0.1576: users may not know what to do with an internal error Problem: Users may not know what to do with an internal error. Solution: Add a translated message with instructions.
author Bram Moolenaar <Bram@vim.org>
date Wed, 24 May 2023 22:15:06 +0200
parents dab4184aaff9
children 4f54d3384e48
files runtime/doc/message.txt src/channel.c src/errors.h src/evalvars.c src/ex_docmd.c src/gui.c src/message.c src/regexp_nfa.c src/testdir/test_expr.vim src/testdir/test_functions.vim src/testdir/test_listdict.vim src/testdir/test_vimscript.vim src/userfunc.c src/version.c src/window.c
diffstat 15 files changed, 82 insertions(+), 70 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/message.txt
+++ b/runtime/doc/message.txt
@@ -78,7 +78,7 @@ See `:messages` above.
 LIST OF MESSAGES
 			*E222* *E228* *E232* *E293* *E298* *E304* *E317*
 			*E318* *E356* *E438* *E439* *E440* *E316* *E320* *E322*
-			*E323* *E341* *E473* *E570* *E685* *E292*
+			*E323* *E341* *E473* *E570* *E292*
   Add to read buffer ~
   makemap: Illegal mode ~
   Cannot create BalloonEval with both message and callback ~
@@ -99,9 +99,9 @@ LIST OF MESSAGES
   Internal error in regexp ~
   fatal error in cs_manage_matches ~
   Invalid count for del_bytes(): {N} ~
-
+						*E340* *E685* *internal-error*
 This is an internal error.  If you can reproduce it, please send in a bug
-report. |bugs|
+report, see |bugs|.
 
 
   ATTENTION ~
--- a/src/channel.c
+++ b/src/channel.c
@@ -1757,7 +1757,7 @@ invoke_callback(channel_T *channel, call
     typval_T	rettv;
 
     if (safe_to_invoke_callback == 0)
-	iemsg("INTERNAL: Invoking callback when it is not safe");
+	iemsg("Invoking callback when it is not safe");
 
     argv[0].v_type = VAR_CHANNEL;
     argv[0].vval.v_channel = channel;
@@ -2400,7 +2400,7 @@ channel_remove_block_id(chanpart_T *chan
 	    }
 	    return;
 	}
-    siemsg("INTERNAL: channel_remove_block_id: cannot find id %d", id);
+    siemsg("channel_remove_block_id(): cannot find id %d", id);
 }
 
 /*
--- a/src/errors.h
+++ b/src/errors.h
@@ -840,7 +840,8 @@ EXTERN char e_sorry_no_file_browser_in_c
 #endif
 EXTERN char e_pattern_too_long[]
 	INIT(= N_("E339: Pattern too long"));
-// E340 unused
+EXTERN char e_internal_error_please_report_a_bug[]
+	INIT(= N_("E340: Internal error; if you can reproduce please report a bug"));
 EXTERN char e_internal_error_lalloc_zero[]
 	INIT(= N_("E341: Internal error: lalloc(0, )"));
 EXTERN char e_out_of_memory_allocating_nr_bytes[]
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -206,7 +206,7 @@ evalvars_init(void)
 	p = &vimvars[i];
 	if (STRLEN(p->vv_name) > DICTITEM16_KEY_LEN)
 	{
-	    iemsg("INTERNAL: name too long, increase size of dictitem16_T");
+	    iemsg("Name too long, increase size of dictitem16_T");
 	    getout(1);
 	}
 	STRCPY(p->vv_di.di_key, p->vv_name);
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -4716,7 +4716,7 @@ address_default_all(exarg_T *eap)
 	case ADDR_NONE:
 	case ADDR_UNSIGNED:
 	case ADDR_QUICKFIX:
-	    iemsg(_("INTERNAL: Cannot use EX_DFLALL with ADDR_NONE, ADDR_UNSIGNED or ADDR_QUICKFIX"));
+	    iemsg("Cannot use EX_DFLALL with ADDR_NONE, ADDR_UNSIGNED or ADDR_QUICKFIX");
 	    break;
     }
 }
--- a/src/gui.c
+++ b/src/gui.c
@@ -142,7 +142,7 @@ gui_start(char_u *arg UNUSED)
 	settmode(TMODE_RAW);		// restart RAW mode
 	set_title_defaults();		// set 'title' and 'icon' again
 #if defined(GUI_MAY_SPAWN) && defined(EXPERIMENTAL_GUI_CMD)
-	if (msg)
+	if (msg != NULL)
 	    emsg(msg);
 #endif
     }
@@ -2786,14 +2786,8 @@ gui_redraw_block(
 		if (col1 > 0)
 		    --col1;
 		else
-		{
 		    // FIXME: how can the first character ever be zero?
-		    // Make this IEMSGN when it no longer breaks Travis CI.
-		    vim_snprintf((char *)IObuff, IOSIZE,
-			    "INTERNAL ERROR: NUL in ScreenLines in row %ld",
-			    (long)gui.row);
-		    msg((char *)IObuff);
-		}
+		    siemsg("NUL in ScreenLines in row %ld", (long)gui.row);
 	    }
 #ifdef FEAT_GUI_GTK
 	    if (col2 + 1 < Columns && ScreenLines[off + col2 + 1] == 0)
@@ -4400,9 +4394,9 @@ gui_do_scrollbar(
 }
 
 /*
- * Scroll a window according to the values set in the globals current_scrollbar
- * and scrollbar_value.  Return TRUE if the cursor in the current window moved
- * or FALSE otherwise.
+ * Scroll a window according to the values set in the globals
+ * "current_scrollbar" and "scrollbar_value".
+ * Return TRUE if the cursor in the current window moved or FALSE otherwise.
  */
     int
 gui_do_scroll(void)
--- a/src/message.c
+++ b/src/message.c
@@ -592,12 +592,12 @@ ignore_error_for_testing(char_u *error)
 }
 
     static int
-ignore_error(char_u *msg)
+ignore_error(const char *msg)
 {
     int i;
 
     for (i = 0; i < ignore_error_list.ga_len; ++i)
-	if (strstr((char *)msg,
+	if (strstr(msg,
 		  (char *)((char_u **)(ignore_error_list.ga_data))[i]) != NULL)
 	    return TRUE;
     return FALSE;
@@ -629,7 +629,7 @@ do_perror(char *msg)
  * Note: caller must check 'emsg_not_now()' before calling this.
  */
     static int
-emsg_core(char_u *s)
+emsg_core(const char *s)
 {
     int		attr;
     char_u	*p;
@@ -665,7 +665,7 @@ emsg_core(char_u *s)
 	 * when the message should be ignored completely (used for the
 	 * interrupt message).
 	 */
-	if (cause_errthrow(s, severe, &ignore) == TRUE)
+	if (cause_errthrow((char_u *)s, severe, &ignore) == TRUE)
 	{
 	    if (!ignore)
 		++did_emsg;
@@ -674,7 +674,7 @@ emsg_core(char_u *s)
 
 	if (in_assert_fails && emsg_assert_fails_msg == NULL)
 	{
-	    emsg_assert_fails_msg = vim_strsave(s);
+	    emsg_assert_fails_msg = vim_strsave((char_u *)s);
 	    emsg_assert_fails_lnum = SOURCING_LNUM;
 	    vim_free(emsg_assert_fails_context);
 	    emsg_assert_fails_context = vim_strsave(
@@ -682,7 +682,7 @@ emsg_core(char_u *s)
 	}
 
 	// set "v:errmsg", also when using ":silent! cmd"
-	set_vim_var_string(VV_ERRMSG, s, -1);
+	set_vim_var_string(VV_ERRMSG, (char_u *)s, -1);
 #endif
 
 	/*
@@ -711,7 +711,7 @@ emsg_core(char_u *s)
 		    redir_write(p, -1);
 		    vim_free(p);
 		}
-		redir_write(s, -1);
+		redir_write((char_u *)s, -1);
 	    }
 #ifdef FEAT_EVAL
 	    // Only increment did_emsg_def when :silent! wasn't used inside the
@@ -720,7 +720,7 @@ emsg_core(char_u *s)
 		++did_emsg_def;
 #endif
 #ifdef FEAT_EVAL
-	    ch_log(NULL, "ERROR silent: %s", (char *)s);
+	    ch_log(NULL, "ERROR silent: %s", s);
 #endif
 	    return TRUE;
 	}
@@ -778,45 +778,44 @@ emsg_core(char_u *s)
 }
 
 /*
- * Print an error message.
+ * Print error message "s".  Should already be translated.
+ * Return TRUE if wait_return() not called.
  */
     int
 emsg(char *s)
 {
     // Skip this if not giving error messages at the moment.
-    if (!emsg_not_now())
-	return emsg_core((char_u *)s);
-    return TRUE;		// no error messages at the moment
+    if (emsg_not_now())
+	return TRUE;
+
+    return emsg_core(s);
 }
 
 #ifndef PROTO  // manual proto with __attribute__
 /*
- * Print an error message with format string and variable arguments.
- * Note: caller must not pass 'IObuff' as 1st argument.
+ * Print error message "s" with format string and variable arguments.
+ * "s" should already be translated.
+ * Note: caller must not use "IObuff" for "s"!
+ * Return TRUE if wait_return() not called.
  */
     int
 semsg(const char *s, ...)
 {
     // Skip this if not giving error messages at the moment.
-    if (!emsg_not_now())
-    {
-	if (IObuff == NULL)
-	{
-	    // Very early in initialisation and already something wrong, just
-	    // give the raw message so the user at least gets a hint.
-	    return emsg_core((char_u *)s);
-	}
-	else
-	{
-	    va_list ap;
-
-	    va_start(ap, s);
-	    vim_vsnprintf((char *)IObuff, IOSIZE, s, ap);
-	    va_end(ap);
-	    return emsg_core(IObuff);
-	}
-    }
-    return TRUE;		// no error messages at the moment
+    if (emsg_not_now())
+	return TRUE;
+
+    if (IObuff == NULL)
+	// Very early in initialisation and already something wrong, just
+	// give the raw message so the user at least gets a hint.
+	return emsg_core(s);
+
+    va_list ap;
+
+    va_start(ap, s);
+    vim_vsnprintf((char *)IObuff, IOSIZE, s, ap);
+    va_end(ap);
+    return emsg_core((char *)IObuff);
 }
 #endif
 
@@ -831,7 +830,11 @@ iemsg(char *s)
     if (emsg_not_now())
 	return;
 
-    emsg_core((char_u *)s);
+    // Give a generic error which is translated.  The error itself may not be
+    // translated, it almost never shows.
+    emsg_core(_(e_internal_error_please_report_a_bug));
+
+    emsg_core(s);
 #if defined(ABORT_ON_INTERNAL_ERROR) && defined(FEAT_EVAL)
     set_vim_var_string(VV_ERRMSG, (char_u *)s, -1);
     msg_putchar('\n');  // avoid overwriting the error message
@@ -853,11 +856,15 @@ siemsg(const char *s, ...)
     if (emsg_not_now())
 	return;
 
+    // Give a generic error which is translated.  The error itself may not be
+    // translated, it almost never shows.
+    emsg_core(_(e_internal_error_please_report_a_bug));
+
     if (IObuff == NULL)
     {
 	// Very early in initialisation and already something wrong, just
 	// give the raw message so the user at least gets a hint.
-	emsg_core((char_u *)s);
+	emsg_core(s);
     }
     else
     {
@@ -866,7 +873,7 @@ siemsg(const char *s, ...)
 	va_start(ap, s);
 	vim_vsnprintf((char *)IObuff, IOSIZE, s, ap);
 	va_end(ap);
-	emsg_core(IObuff);
+	emsg_core((char *)IObuff);
     }
 # ifdef ABORT_ON_INTERNAL_ERROR
     msg_putchar('\n');  // avoid overwriting the error message
@@ -882,6 +889,10 @@ siemsg(const char *s, ...)
     void
 internal_error(char *where)
 {
+    // Give a generic error which is translated.  The error itself may not be
+    // translated, it almost never shows.
+    emsg_core(_(e_internal_error_please_report_a_bug));
+
     siemsg(_(e_internal_error_str), where);
 }
 
@@ -893,7 +904,11 @@ internal_error(char *where)
     void
 internal_error_no_abort(char *where)
 {
-     semsg(_(e_internal_error_str), where);
+    // Give a generic error which is translated.  The error itself may not be
+    // translated, it almost never shows.
+    emsg_core(_(e_internal_error_please_report_a_bug));
+
+    semsg(_(e_internal_error_str), where);
 }
 #endif
 
--- a/src/regexp_nfa.c
+++ b/src/regexp_nfa.c
@@ -1401,7 +1401,7 @@ nfa_regatom(void)
 		    rc_did_emsg = TRUE;
 		    return FAIL;
 		}
-		siemsg("INTERNAL: Unknown character class char: %d", c);
+		siemsg("Unknown character class char: %d", c);
 		return FAIL;
 	    }
 
@@ -6905,7 +6905,7 @@ nfa_regmatch(
 
 #ifdef DEBUG
 		if (c < 0)
-		    siemsg("INTERNAL: Negative state char: %ld", (long)c);
+		    siemsg("Negative state char: %ld", (long)c);
 #endif
 		result = (c == curc);
 
@@ -7196,9 +7196,9 @@ nfa_regtry(
     if (f != NULL)
     {
 	fprintf(f, "\n\n\t=======================================================\n");
-#ifdef DEBUG
+# ifdef DEBUG
 	fprintf(f, "\tRegexp is \"%s\"\n", nfa_regengine.expr);
-#endif
+# endif
 	fprintf(f, "\tInput text is \"%s\" \n", rex.input);
 	fprintf(f, "\t=======================================================\n\n");
 	nfa_print_state(f, start);
--- a/src/testdir/test_expr.vim
+++ b/src/testdir/test_expr.vim
@@ -25,7 +25,7 @@ func Test_equal()
   call assert_fails('echo base.method > instance.method')
   call assert_equal(0, test_null_function() == function('min'))
   call assert_equal(1, test_null_function() == test_null_function())
-  call assert_fails('eval 10 == test_unknown()', 'E685:')
+  call assert_fails('eval 10 == test_unknown()', ['E340:', 'E685:'])
 endfunc
 
 func Test_version()
--- a/src/testdir/test_functions.vim
+++ b/src/testdir/test_functions.vim
@@ -82,15 +82,15 @@ func Test_empty()
   call assert_equal(0, empty(function('Test_empty')))
   call assert_equal(0, empty(function('Test_empty', [0])))
 
-  call assert_fails("call empty(test_void())", 'E685:')
-  call assert_fails("call empty(test_unknown())", 'E685:')
+  call assert_fails("call empty(test_void())", ['E340:', 'E685:'])
+  call assert_fails("call empty(test_unknown())", ['E340:', 'E685:'])
 endfunc
 
 func Test_test_void()
   call assert_fails('echo 1 == test_void()', 'E1031:')
   call assert_fails('echo 1.0 == test_void()', 'E1031:')
-  call assert_fails('let x = json_encode(test_void())', 'E685:')
-  call assert_fails('let x = copy(test_void())', 'E685:')
+  call assert_fails('let x = json_encode(test_void())', ['E340:', 'E685:'])
+  call assert_fails('let x = copy(test_void())', ['E340:', 'E685:'])
   call assert_fails('let x = copy([test_void()])', 'E1031:')
 endfunc
 
--- a/src/testdir/test_listdict.vim
+++ b/src/testdir/test_listdict.vim
@@ -1384,7 +1384,7 @@ func Test_listdict_index()
   call v9.CheckLegacyAndVim9Failure(['VAR l = [1, 2, 3]', 'LET l[1.1] = 4'], ['E805:', 'E1012:', 'E805:'])
   call v9.CheckLegacyAndVim9Failure(['VAR l = [1, 2, 3]', 'LET l[: i] = [4, 5]'], ['E121:', 'E1001:', 'E121:'])
   call v9.CheckLegacyAndVim9Failure(['VAR l = [1, 2, 3]', 'LET l[: 3.2] = [4, 5]'], ['E805:', 'E1012:', 'E805:'])
-  call v9.CheckLegacyAndVim9Failure(['VAR t = test_unknown()', 'echo t[0]'], ['E685:', 'E909:', 'E685:'])
+  call v9.CheckLegacyAndVim9Failure(['VAR t = test_unknown()', 'echo t[0]'], ['E340:', 'E909:', 'E340:', 'E685:'])
 endfunc
 
 " Test for a null list
--- a/src/testdir/test_vimscript.vim
+++ b/src/testdir/test_vimscript.vim
@@ -6524,8 +6524,8 @@ func Test_type()
     endif
     call assert_equal(v:t_blob, type(test_null_blob()))
 
-    call assert_fails("call type(test_void())", 'E685:')
-    call assert_fails("call type(test_unknown())", 'E685:')
+    call assert_fails("call type(test_void())", ['E340:', 'E685:'])
+    call assert_fails("call type(test_unknown())", ['E340:', 'E685:'])
 
     call assert_equal(0, 0 + v:false)
     call assert_equal(1, 0 + v:true)
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -3247,7 +3247,7 @@ save_funccal(funccal_entry_T *entry)
 restore_funccal(void)
 {
     if (funccal_stack == NULL)
-	iemsg("INTERNAL: restore_funccal()");
+	internal_error("restore_funccal()");
     else
     {
 	current_funccal = funccal_stack->top_funccal;
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1576,
+/**/
     1575,
 /**/
     1574,
--- a/src/window.c
+++ b/src/window.c
@@ -1948,7 +1948,7 @@ win_move_after(win_T *win1, win_T *win2)
     {
 	if (win1->w_frame->fr_parent != win2->w_frame->fr_parent)
 	{
-	    iemsg("INTERNAL: trying to move a window into another frame");
+	    iemsg("Trying to move a window into another frame");
 	    return;
 	}