Subject: Re: bug#67008: 30.0.50; Multiple major mode parents

From: Stefan Monnier <[email-masked]>
Date: Mon, 13 Nov 2023 08:30:22 -0500

>> I improved the docstring to try and clarify.
> Thank you, but the new text,
>> +The order of the (sub)lists determines the final order in those cases where
>> +the order within the sublists does not impose a unique choice.
> still doesn't explain how the sublist order affects the choice of linearisation.

Suggestions welcome to make it better.  I couldn't come up with
a wording that is both short enough and clear.

> Since I'm here:
>>      (while (cdr (setq lists (delq nil lists)))
> When this loop is entered the first time, `lists` still holds the argument
> which probably shouldn't be mutated even if it's for removing empty lists
> inside. (In later iterations it seems to be a copy.)

I guess you're right.  The list passed to it is always freshly made, so
it's not a real problem in practice, but it's a bit ugly.

> +(ert-deftest subt-tests--merge-ordered-lists ()
>                  ^
>                  r

Damn, you caught my subt-erfuge!

> +  (should (equal (merge-ordered-lists
> +                  '((B A) (C A) (D B) (E D C)))
> +                 '(E D B C A)))
> +  (should (equal (merge-ordered-lists
> +                  '((E D C) (B A) (C A) (D B)))
> +                 '(E D C B A)))
> +  (should-error (merge-ordered-lists
> +                 '((E C D) (B A) (A C) (D B))
> +                 (lambda (_) (error "cycle")))))
>
> All calls should error on cycles, not just the one that actually contains one.

Fair enough.

> Maybe the default value for the `error-function` argument should be one that
> raises an error, so that callers need to specify something explicitly if
> they want a different behaviour?

I decided against that because the existing evidence is that we prefer
to hide the problem than to signal an error.  Part of the issue is also
that in practice most "cycles" aren't real: they are the result of
submode/subtype relationships where two types/modes have linearized their
parents in incompatible ways.

E.g. C inherits from (A B)
     D inherits from (B A)
     E inherits from (C D)

there is no cycle in the inheritance, but since the linearization is
done piecemeal (a.k.a locally), you get to merge

    ((C A B) (D B A))

and that finds a "cycle".  That's why EIEIO calls it
`inconsistent-class-hierarchy` rather than `cycle`.

        Stefan