Subject: bug#61847: debug-early-backtrace only works some of the time.

From: Alan Mackenzie <[email-masked]>
Date: Tue, 28 Feb 2023 09:12:08 +0000

Hello, Stefan.

On Mon, Feb 27, 2023 at 14:15:22 -0500, Stefan Monnier wrote:
> > The cause of the problem was patch

> > commit 08108a856a544a80d11b1e9e437fe6c45e25adec
> > Author: Stefan Monnier <[email-masked]>
> > Date:   Fri Apr 29 22:18:09 2022 -0400

> >     debug-early: Print bytecode in a more manageable way

> >     * lisp/emacs-lisp/debug-early.el (debug-early-backtrace):
> >     Escape newlines to and bytecodes to make backtraces slightly more
> >     readable.  Use `cl-prin1` when available.

> > , which made debug-early.el dependent on arbitrarily nested Lisp code, in
> > violation of its explicitly stated design goal to have _no_ dependence on
> > Lisp code.  Some of this Lisp simply fails to load.

> Indeed (fboundp 'cl-prin1) was too optimistic a test since it just
> checks whether we're before loading `loaddef.el` or after it, but
> `cl-prin1` uses more (preloaded) features such as those provided by
> `cl-generic` which is only loaded later.

It violates the design goal of having no Lisp dependencies.  It was those
dependencies which broke the rock solid dependability of the original
code.

> > It's not clear why the patch was applied.

> To get more readable backtraces when used after bootstrapping (as well as
> in the later phases of bootstrapping).

More readable?  Just how is a backtrace produced using cl-prin1 more
readable than one using prin1?  They both look pretty much the same.  But
cl-prin1 only outputs partial information for some things, such as
compiled functions, so it is not a good choice.  debug-early-backtrace
should produce _complete_ backtraces.

> > I propose fixing the bug by restoring the code to having no such
> > dependencies with the following patch:

> How 'bout the patch below instead.
> Maybe we should instead try and check whether we're after the bootstrap
> (not sure what would be the corresponding test).

It might work.  It might work now, and fail in future releases of Emacs
should the loading mechanism get changed.  The original code using prin1
was rock solid, by design.

What if there was some bug in the loading mechanism, or a bug in
cl-print.el which prevented it loading cleanly, yet without triggering
the condition-case you suggest below?

Again, what's so readable about cl-prin1's output that makes it worth the
compromise in debug-early-backtrace's design?

And how will the contition-case you suggest help?  (require 'cl-print nil
t) returns non-nil in the pertinent circumstances.  Putting a
condition-case around that isn't going to change this.  Have you actually
tried out your patch?  What happened when you did?

>         Stefan

> diff --git a/lisp/emacs-lisp/debug-early.el b/lisp/emacs-lisp/debug-early.el
> index 395498f2206..65770a9c1d9 100644
> --- a/lisp/emacs-lisp/debug-early.el
> +++ b/lisp/emacs-lisp/debug-early.el
> @@ -46,10 +46,13 @@ 'debug-early-backtrace
>              (print-escape-control-characters t)
>              (print-escape-nonascii t)
>              (prin1 (if (and (fboundp 'cl-prin1)
> +                            (fboundp 'cl-defmethod)
>                              ;; If we're being called while
>                              ;; bootstrapping, we won't be able to load
>                              ;; cl-print.
> -                            (require 'cl-print nil t))
> +                            (condition-case nil
> +                                (require 'cl-print nil t)
> +                              (error nil)))
>                         #'cl-prin1
>                       #'prin1)))
>          (mapbacktrace

-- 
Alan Mackenzie (Nuremberg, Germany).