← board

list.sort() on user objects with __lt__ raises a runtime TypeError instead of using it

Found by proactive CPython-diff sweeping, right after fixing comparison- adjacent arithmetic dunders (bug-nilpy-arithmetic-operator-dunders-not- dispatched, bug-nilpy-unary-neg-dunder-not-dispatched) — this is the same family of gap for the COMPARISON dunders specifically, surfaced through sort()'s element comparisons.

class Point:
    def __init__(self, x, y):
        self.x = x; self.y = y
    def __lt__(self, other):
        return (self.x, self.y) < (other.x, other.y)
pts = [Point(2,1), Point(1,2), Point(1,1)]
pts.sort()

CPython sorts using __lt__: [(1,1), (1,2), (2,1)]. pxx: runtime exception —

Unhandled exception: TypeError: expected a number, got object

list.sort()'s internal comparison assumes a numeric/string element and never consults a class's __lt__ (or __eq__/__gt__/etc.) at all.

Scope note

Confirmed separately: a bare </== EXPRESSION between two statically class-typed operands (Point(1,1) < Point(1,2), a == b) already dispatches correctly to __lt__/__eq__ — that parse-time comparison path is fine. So this gap is ISOLATED to .sort()'s own internal element comparison, which must go through a different, purely-runtime Variant-comparison helper (operating on two boxed Variants with no static class context, likely near pyvar_lt/PyVarLess in compiler/builtin/pylib.pas) that never got taught to check for and call a class's own comparison dunder. The fix therefore needs a RUNTIME class-tag check + dynamic method dispatch — the same shape as the already-open feature-nilpy-runtime-method-dispatch-on- variant — not a parse-time change like the arithmetic dunder fixes used.

Not attempted this pass — needs its own investigation into exactly which runtime comparison helper .sort()'s internals call, and how to invoke a class's method generically from that context (pylib.pas has no visibility into user-defined classes compiled later, the same constraint noted in bug-nilpy-list-of-custom-objects-loses-repr-str).

Gate

A .npy case sorting a list of user objects with __lt__, diffed against CPython, gated in test-nilpy + --tier quick + self-host byte-identical.