Subject: Re: bug#78989: 31.0.50; classes and methods inheritance (defclass) seq-contains-p

From: Stefan Monnier <[email-masked]>
Date: Fri, 11 Jul 2025 11:51:24 -0400

Pip Cet [2025-07-11 13:43:30] wrote:

> "Eli Zaretskii" <[email-masked]> writes:
>
>>> From: "Pierre L. Nageoire" <[email-masked]>
>>> Date: Thu, 10 Jul 2025 10:31:50 +0200
>>>
>>> Code below has a different behavior in the current emacs version
>>> (referenced in this mail) and in the last git pull one (one day ago)
>>> that I will name new!
>>>
>>>
>>> In current version it produces the expected message
>>> "Son does not contain dummy"
>>>
>>> but in new one it trigger the error also included below.
>>>
>>> Please excuse me for the complicated code but it was very tricky to find
>>> a minimal class tree structure that triggers the error.
>>>
>>> I suspect that problem comes from the method lookup through the
>>> inheritance class tree. This schedule has maybe been modified recently ;
>>> and it is perhaps not a bug but simply changes in inheritance scope.
>>>
>>> I know that that whole stuff is work in progress and that things may
>>> change from time to time.
>>>
>>> Anywa it looks me strange that the reimplemented method `seq-contains-p'
>>> cannot be reached from son while it can be from father. From son it
>>> fallback on the method for sequence as shown in the error report.
>>>
>>> Sory that mother seems to be responsbile for that !
>>
>> Thanks, I added the usual suspects to this discussion.
>
> I think the bug is in cl--class-allparents, which incorrectly assumes
> topological sorting can be done recursively, but it's hidden by another
> problem:

FWIW, `cl--class-allparents` does not promise a general topological sort.

> Consider '((a b) (a c) (c b)):

This would be an invalid input: class `a` cannot have two different
lists of parents.

> In our case, the incorrect partially-sorted return value of
> cl--class-allparents has t appear in the list before `baselist` does, so
> we end up trying to use the wrong method: we incorrectly assume that t
> is a more specific type than `baselist`.

Good spotting.  I traced this further to:

1 -> (merge-ordered-lists ((widgetlist widobj baselist state sortable eieio-default-superclass record atom t) (loadable loadfile loader eieio-persistent state interface title widobj abstitle eieio-default-superclass record atom t) (interfacelist widgetlist interface title widobj baselist state sortable abstitle eieio-default-superclass record atom t)))
1 <- merge-ordered-lists: (loadable loadfile loader eieio-persistent interfacelist widgetlist widobj baselist state interface title widobj baselist state sortable abstitle eieio-default-superclass record atom t)

where we see that `baselist` (and several others as well) appears twice in the output.

        Stefan