Subject: Re: bug#31090: 26.0.91; Edebug incorrectly instruments unquotes in nested backquotes

From: Alan Mackenzie <[email-masked]>
Date: 9 Apr 2018 19:15:41 -0000

Hello, Gemini.

In article <[email-masked]> you wrote:
> Edebug incorrectly instruments unquotes inside of nested backquotes,
> causing errors if the incorrectly instrumented forms are part of a
> macro expansion that then gets executed in another context.

> To reproduce, enter this code into *scratch*:

> (defun my-wrap-form (form description)
>   `(unless ,form
>      (message "failed %s" ,description)))

> (defmacro my-should (form)
>   (declare (debug t))
>   (let ((fn (gensym "fn-"))
>         (args (gensym "args-"))
>         (value (gensym "value-")))
>     `(let ((,fn (function ,(car form)))
>            (,args (list ,@(cdr form)))
>            ,value)
>        ,(my-wrap-form
>          `(setq ,value (apply ,fn ,args))
>          `(nconc (list :form `(,,fn ,@,args))
>                  (list :value ,value))))))

> (defun my-test ()
>   (my-should (= 1 2)))

> Then:

> Navigate to the definition of my-wrap-form and evaluate it with C-M-x
> Navigate to the definition of my-should and evaluate it with C-u C-M-x
> Navigate to the definition of my-test and evaluate it with C-M-x
> g
> M-: (my-test) RET

> Result: The debugger appears with an error (wrong-type-argument consp nil)
> in edebug-before.

I think we've been here before, in bug #16184.  The problem is that the
instrumented form hasn't called edebug-enter, for whatever reason, hence
hasn't pushed a cons onto edebug-offset-indices, which is thus still
nil.  The (setcar edebug-offset-indices ...) at the start of
edebug-slow-before (to which edebug-before is aliased) thus fails.

At the time, I committed a solution which involved initialising that
variable to '(0) instead of nil.  You persuaded me to revert that
change, saying [Date: Fri, 30 Dec 2016 15:27:37 -0800, Subject: Re:
bug#16184: 24.3.50; edebug and eval-when-compiler don't work together]:

  > I haven't able to reproduce the bug with cc-eval-when-compile, just
  > eval-and-compile. But the thing that is supposed to make Edebug wrap a
  > form in edebug-enter is the use of def-form or def-body in the Edebug
  > spec. It works for eval-when-compile which has the Edebug spec (&rest
  > def-form). The body of eval-and-compile doesn't get wrapped because
  > its Edebug spec is t, so the bug happens there.

  > cc-eval-when-compile has the same Edebug spec as eval-when-compile, so
  > its body should get wrapped by edebug-enter. If that's not happening
  > in your Emacs, it's a bug in Edebug which is different from the
  > eval-and-compile Edebug spec bug.

This, if true, implies that using an instrumented macro is liable to
produce this error if that macro doesn't have an appropriate edebug
spec.  This seems to be an unreasonable prerequisite - I think the
typical work flow would be writing a macro first, testing it with the
help of Edebug, and then, possibly writing an edebug spec.

Perhaps we should think again about my solution from December 2016,
namely initialising edebug-offset-indices to a cons '(0).  I've just
tried this, and got the error edebug-freq-count is unbound.  So perhaps
we should give initial values to all these declared dynamic variables
which are bound by edebug-enter, for the case when edebug-enter doesn't
get called.

[ .... ]

-- 
Alan Mackenzie (Nuremberg, Germany).