[mypyc] Optimize dunder methods by jairov4 · Pull Request #17934 · python/mypy (original) (raw)
This change gives mypyc the ability to optionally optimize dunder methods that can guarantee strict adherence to its signature typing. The optimization allows to bypass vtable for dunder methods in certain cases that are applicable.
Currently, mypy has adopted the convention of accept dunder methods that return NotImplemented
value even when its signature do not reflect this possibility. With this change and by enabling an special flag, mypyc will expect strict typing be honored and will unleash more optimizations like native call without vtable lookup for some cases on dunder method calls.
For example it could avoid calls to RichCompare Python API making the code can be fully optimized in by the C compiler when some comparison with dunders are required.
Example:
@final class A: def init(self, x: i32) -> None: self.x: Final = x
def __lt__(self, other: "A") -> bool:
return self.x < other.x
A(1) < A(2)
would produce:
char CPyDef_A_____lt__(PyObject *cpy_r_self, PyObject *cpy_r_other) { int32_t cpy_r_r0; int32_t cpy_r_r1; char cpy_r_r2; cpy_r_r0 = ((AObject *)cpy_r_self)->_x; cpy_r_r1 = ((AObject *)cpy_r_other)->_x; cpy_r_r2 = cpy_r_r0 < cpy_r_r1; return cpy_r_r2; }
... cpy_r_r29 = CPyDef_A_____lt__(cpy_r_r27, cpy_r_r28); ...
Instead of:
PyObject *CPyDef_A_____lt__(PyObject *cpy_r_self, PyObject *cpy_r_other) { int32_t cpy_r_r0; int32_t cpy_r_r1; char cpy_r_r2; PyObject *cpy_r_r3; cpy_r_r0 = ((AObject *)cpy_r_self)->_x; cpy_r_r1 = ((AObject *)cpy_r_other)->_x; cpy_r_r2 = cpy_r_r0 < cpy_r_r1; cpy_r_r3 = cpy_r_r2 ? Py_True : Py_False; CPy_INCREF(cpy_r_r3); return cpy_r_r3; }
... cpy_r_r29 = PyObject_RichCompare(cpy_r_r27, cpy_r_r28, 0); ...
Default behavior is kept.
Tests run with both of strict typing enabled and disabled.
Should be rebased and reviewed after #17886