Subject: bug#74294: Master: debug-on-error is ineffective whilst requiring a file from the byte compiler.

From: Alan Mackenzie <[email-masked]>
Date: Sun, 10 Nov 2024 18:38:26 +0000

Hello, Stefan.

On Sun, Nov 10, 2024 at 12:31:46 -0500, Stefan Monnier wrote:
> > Create the following files:

> > 1: ~/test-byte-compile-errors.el:
> > #########################################################################
> > ;; -*- lexical-binding:t -*-
> > (require 'test-byte-compile-errors-2 "~/test-byte-compile-errors-2")
> > #########################################################################

> > 2: ~/test-byte-compile-errors-2.el:
> > #########################################################################
> > ;; -*- lexical-binding:t -*-
> > (car 'baz)

> > (provide 'test-byte-compile-errors-2)
> > #########################################################################

> > (Note the erroneous (car 'baz) in this file.)

> > (i) emacs -Q
> > (ii) M-: (setq debug-on-error t) RET
> > (iii) M-x byte-compile-file RET ~/test-byte-compile-errors.el RET

> > (iv) The error message:

> >     test-byte-compile-errors.el:2:11: Error: Wrong type argument: listp, baz

> > is displayed.  The debugger is not run.  This is surely a bug.

> > (Note also, the file name displayed is not that where the error is: See
> > bug#66912.)

> > #########################################################################

> > Diagnosis
> > ---------

> > In the function bytecomp--displaying-warnings (bytecomp.el), a blocking
> > condition-case is set up, except when byte-compile-debug is non-nil.
> > This prevents the debugger running.  The problem is, the effect of this
> > condition-case prevails even outside the byte compiler whilst loading a
> > file with `require'.

> Hmm... whether it's "outside the byte compiler" or not is debatable.

Well for sure, we're not processing functions beginning "byte-compile-"
at the time.  And perhaps most pertinently, an error in Fload doesn't
(?can't be made to) invoke the byte compiler's error mechanism
satisfactorally.

> [ FWIW, I've been annoyed by the behavior as well, but just decided to set
>   `byte-compile-debug` to t in my init file, and life is bliss since then.  ]

That's fine for those who know about byte-compile-debug.  I suspect the
vast majority of users don't.  And it's a hassle to have to run something
THREE times to get a backtrace:  The first time the error happens, the
second time the user sets debug-on-error, then after considerable
frustration and looking up of the elisp manual, the third time with
byte-compile-debug set too.

There might be an argument here for removing byte-compile-debug and that
condition-case altogether, but that's not what I'm arguing at the moment.

> > Set up one or more handler-binds around the parts of Fload that evaluate
> > the contents of the file being loaded.  In the event of an error, the
> > handler-bind handler would trigger, test debug-on-error, and if it's set
> > appropriately, call the debugger, then quit.  Otherwise, the handler
> > would return, and the error handling would eventually reach the
> > condition-case set up by bytecomp--displaying-warnings.

> Is the problem specific to `load`, really?

Yes, I think it is.  Because it is precisely during Fload called from the
byte compiler when a signalled error gives no clue as to the source of
that error.

> What about errors within `eval-when-compile` or during the expansion of
> one of the macros?

Errors there will say where they have happened, more or less.

> Also, do you really want to bring up the debugger in cases like

>     (eval-when-compile
>       (condition-case nil
>           (require ...)
>         (error ...)))

> which I've seen used in a few packages out there?

When debug-on-error is enabled, yes.  To do everything the way we'd like,
we don't have enough control levers.  It is probably better to enter the
debugger in the above case (the user did set debug-on-error after all)
than not enter it when an error happens in a deep stack of `require's.

>         Stefan

-- 
Alan Mackenzie (Nuremberg, Germany).