Subject: Re: bug#54079: 29.0.50; Method dispatching eratically fails

From: Alan Mackenzie <[email-masked]>
Date: Sun, 13 Mar 2022 16:49:58 +0000

Hello, Stefan.

On Fri, Mar 11, 2022 at 23:23:50 -0500, Stefan Monnier wrote:

[ .... ]

> Whatever appears in the code passed through `eval-{when,and}-compile`
> can survive that code, so the fact that `symbols-with-pos-enabled` is

> `eval` is exactly this "as long as possible" point where we know the
> code won't be compiled because it's about to be interpreted.
> non-nil while evaluating it doesn't make it correct.

OK, you've persuaded me.  ;-)  Lisp forms need to be stripped of SWPs
before being passed into `eval'.

> > But, looking at the code, I don't think byte-compile binds
> > symbols-with-pos-enabled to t.  This could be a bug.

> Maybe not: it has no reason to presume that its argument has positions.

More to the point, I don't think it can assume that there aren't SWPs in
the form.

> If it does, then it must be because the caller explicitly arranged for
> it to happen and so the caller could be in charge of binding
> that variable.

The caller could be any lisp function.  It's just that binding
symbols-with-pos-enabled in byte-compile is cheap and harmless, and there
might well be legitimate cases that need it.  I can't think of any at the
moment, though.

> >>     And why bother stripping the result of `byte-compile-eval`?

I think this point is moot if the form has been stripped before going
into byte-compile-eval.  In that case, there will be no need to strip the
result.

[ .... ]

> >>     Fundamentally, `eval` should always strip before doing its job.
> > You mean, by "always", you meant ALWAYS???

> Yes.

> > I understood you to mean "always, when in the context of
> > eval-{when,and}-compile".  If we're not inside a compilation, and thus
> > there're no SWPs hanging around, stripping symbols from an expression
> > will just mean a loss of time for a null operation.

> That's right: the only cases where not stripping the arg of `eval` is OK
> is when we know that stripping would do nothing.
> IOW it's an optimization.

It's NOT an optimisation.  It's a straightforward implementation of the
design.  To add unnecessary stripping of non-existent symbol positions
would be a pessimisation, a possibly measurable slowing down of Emacs.

The whole essence of the SWP design was to minimise the influence of the
SWPs on code which isn't the compiler.  Always stripping before calling
`eval' would not be in accordance with that design.

There are a lot of places where `eval' is called.  Inserting
byte-run-strip-symbol-positions before each of them would be tedious in
the extreme.  Instead damaging `eval', to make it do two disparate things
which just happen to follow on from eachother sometimes, would be worse;
it would likely involve adding an extra &optional argument meaning
"strip".

[ .... ]

> >> The misbehavior I'm referring to is what happens when you call the
> >> function before you byte-compile it (or, more likely, when you never end
> >> up byte-compiling it), because the presence of sympos in the function
> >> will mess up its semantics (because `symbols-with-pos-enabled` won't be
> >> set any more when it's called).

> > I'm puzzled.  Are we still talking about eval-{when,and}-compile, here?

> No.  We're talking about a hypothetical case where `(eval '(defun foo ...))`
> is executed somehow and where the `(defun foo ...)` part somehow
> contains symposes.

Modulo bugs, I think that could only happen in a macro, where the (defun
foo ...) bit was an argument, and the macro takes steps to preserve that
argument beyond its natural scope.

> I used it as an example of why `eval` should conceptually always strip
> its argument (or if `eval` doesn't do it, then its caller should make
> sure that the code passed to it doesn't contains symposes).

I think it will be rare.

[ .... ]

I will prepare another patch which strips the forms of SWPs before the
`eval' in eval-{when,and}-compile.

Apologies if I've inadvertently failed to answer any open points.

>         Stefan

-- 
Alan Mackenzie (Nuremberg, Germany).