object-oriented – describing C3 in terms of predicates on types

What is the proper way to describe the properties of a method resolution sequence that naturally leads you to the C3 linearization algorithm?

I'm trying to nail desiderata for an MRO that are conceptually prior to the C3 algorithm itself.

I've recently read a blog post about the C3 resolution order and its use in Python here [https://python-history.blogspot.com/2010/06/method-resolution-order.html][1]

The publication speaks of C3 satisfying a property of monotony and informally describing an invariant that we would like to preserve for the system as a whole.

Within a complex inheritance hierarchy, you want to be able to satisfy
all these possible rules in a monotonous way. That's, if
you have already determined that class A must be verified before
class B, then you should never encounter a situation that requires
class B to be checked before class A (otherwise, the result is
undefined and the inheritance hierarchy must be rejected).

We can take this (section of one) paragraph and run with it. We define two predicates:

  • $ A <B $ means $ A $ is a subclass of $ B $ and $ A neq B $
  • $ A sqsubset B $ means $ A $ is checked before $ B $ and $ A neq B $

And then we start proposing rules (101-104). $ (A ; text {extension} ; B, C) $ is supposed to be interpreted as a fact about the source code and not as a new predicate. (I do not know if it's worthwhile to make a distinction like this). The other thing I do, it's a little weird, is to create a partial order on a $ <$-like and $ = $predicate-like instead of a simple $ the $-like one, but I think the meaning is clear.

$$ (<, =) ; ; ; text {is a partial order} tag {101} $$

$$ ( sqsubset, =) ; ; ; text {is a partial order} tag {102} $$

$$ frac {A <B} {A sqsubset B} tag {103} $$

$$ frac {(A ; text {extension} ; B, C)} {A <B ; ; ; text {and} ; ; ; A <C ; ; ; text {and} ; ; ; B sqsubset C} tag {104} $$

However, from these facts, we can immediately say that (105) must be rejected as invalid because $ E sqsubset F $ and $ F sqsubset E $ can not be simultaneously true.

$$ (A ; text {s> expand} ; E, F) ; ; ; text {and} ; ; ; (B ; text {s>}; F, E) implies bot tag {105} $$

However, the Python 3+ equivalent (106) will execute without generating error:

class E: pass number (106)
class F: pass
class A (E, F): pass
class B (F, E): pass

In order to obtain python to complain about the order of resolution of the method, we must inherit from both $ A $ and $ B $ simultaneously (107).

class E: pass number (107)
class F: pass
class A (E, F): pass
class B (F, E): pass
class Z (A, B): pass

produces the following error:

Traceback (most recent call last):
"Inherit.py" file, line 5, in 
    class Z (A, B): pass
TypeError: Can not create a consistent method resolution
order (MRO) for the E, F bases

This immediately raises some questions: