Subject: Re: bug#65051: internal_equal manipulates symbols with position without checking symbols-with-pos-enabled.

From: Alan Mackenzie <[email-masked]>
Date: Thu, 10 Aug 2023 18:35:27 +0000

Hello, Stefan.

On Thu, Aug 10, 2023 at 10:28:55 -0400, Stefan Monnier wrote:

[ .... ]

> >> > In the code at the moment, the result of `equal' on symbols with
> >> > position is undefined, i.e. it returns a random value.
> >> In which sense?
> > In the sense it wasn't deliberately coded.  It's just a random value
> > resulting from the code for other scenarios.

> Then it's not "random" nor "undefined".
> I'd describe it as "arbitrary".

Then we're reduced to arguing about words rather than Emacs.

> >> AFAICT it returns non-nil iff the underlying bare symbols are `eq`.
> >> That does not sound "random" at all to me.
> >> What am I missing?
> > That equal is different from eq.

> Then let me rephrase the above:

>     AFAICT it returns non-nil iff the underlying bare symbols are `equal`.

> See?  No` eq` any more :-)

Yes I see, and it is wrong.

Let me try another tack.  Look closely at the definition of
symbols-with-pos-enabled:

(i) When nil: Emacs works without any special handling for SWPs.

(ii) When non-nil: Emacs handles SWPs as though they were their bare
symbols.

> > The definition of eq (more or less) is "identical objects".
> > The definition of equal (more or less) is "same structure with same
> > components".

> Yes, but the "more or less" is very applicable to SWP.

> E.g. one could argue that if two objects are sometimes `eq`, then
> I think it's a good enough justification to treat them as always
> `equal`.

A SWP is sometimes EQ its bare symbol, in particular when
symbols-with-pos-enabled is non-nil.  That is no justification for
regarding the two as _always_ EQ, in particular when s-w-p-enabled is
nil.  If you were to make that argument, you would be arguing for a
significant slowdown in Emacs.

> > See my previous paragraph of this post.  You're proposing that the
> > position elements of SWPs should be ignored in equal.  I don't see any
> > good reason for this.

> One reason is that it's the semantics we use 99% of the time (where
> `symbols-with-pos-enabled` is also non-nil).

It's not the semantics we should use when s-w-p-enabled is nil.  That
would violate the definition of symbols-with-pos-enabled.  See above.

> But as I said at the beginning, my main point is that the current
> behavior is not a *bug*.  It's just an arbitrary semantics, and you're
> proposing to use another arbitrary semantics.

I'm proposing correctness, according to a coherent definition of
symbols-with-pos-enabled.  I was surprised indeed, and continue to be
surprised, that you do not see this correction as a correction.  To me,
it's obvious.

> And the new arbitrary semantics does not seem clearly superior.
> IOW, bikeshedding material.

The correctness of symbols-with-pos-enabled is not arbitrary.

If you think the semantics are arbitrary, why are you so fixed on
implementing a particular one of them?

[ .... ]

> But the behavior for `equal` is not "special" IMO.  It fits within the
> general behavior of `equal`.

Yet you're insisting on special behaviour for SWP's when
symbols-with-pos-enabled is nil.

[ .... ]

> None of it is concrete, and I disagree with them, so it's just my opinion
> against your opinion.  We're not going to have much success with that.

> Hence the need for more concrete practical arguments.

Well, one argument, not very strong but stronger than any other you'll
accept is that the code and documentation amendments have already been
made.  There are so far no signs of the needed documentation changes for
leaving the handling of SWPs by equal contrasting with that of other
types.

> >> > It was me that coded up that amendment to equal, and I can remember
> >> > simply not taking into account the scenario we're talking about.
> >> Which scenario?
> > <sigh> Comparing two arguments using equal, at least one of which is a
> > symbol with position, when symbols-with-pos-enabled is nil.

> Ah, sorry, I thought you were referring to a more concrete use-case
> where such a `equal` test would occur.  Having such use-cases would help
> the current discussion significantly, since currently we're basically
> arguing about what Emacs should do in cases that never occur.

That is the case, yes.  There are no current use-cases for SWPs with
s-w-p-enabled nil.

[ .... ]

> > So why are you making such a big thing out of it?

> [ Hmm... I have a feeling of déjà-vu.  ]

> > I see quite clearly which of these options is correct.
> > Why won't you respect my superior insight into the matter?

> [ Hmm... this sounds a bit arrogant, so I'll just skip it.  ]

No, you won't.  There is a basic contradiction in your stance, namely
you say on the one hand that the correct strategy here is arbitrary, yet
on the other hand that the one you prefer is overwhelmingly better.  If
you were being honest about this arbitrariness, you wouldn't be making
such a song and dance about it.

> >>   It makes it impure, and will invalidate existing optimizations,
> >>   exactly like we've just witnessed for `eq`.
> > Which optimisations are you talking about here?  Just how is equal
> > optimised?

> The same one that causes my bug-fix to fail:

>     (let ((symbols-with-position-enabled V)) (equal E1 E2))

> is optimized to

>     (equal E1 E2)

What can I say?  If you eliminate semantically essential code what you
end up with is not what you started with.  Is there actually an instance
of the above code in the Emacs sources?  In particular, one where
symbols-with-position-enabled gets bound by a let, and the body of the
let contains an equal (or member, or ...), but no uses of EQ?

> -- Stefan

-- 
Alan Mackenzie (Nuremberg, Germany).