You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This pull request refactors and reworks how we handle reversible
operators like __add__.
Specifically, what our code was previously doing was assuming that given
the expression `A() + B()`, we would always try calling
`A().__add__(B())` first, followed by `B().__radd__(A())` second (if the
`__radd__` method exists).
Unfortunately, it seems like this model was a little too naive, which
caused several mismatches/weird errors when I was working on refining
how we handle overlaps and TypeVars in a subsequent PR.
Specifically, what actually happens is that...
1. When doing `A() + A()`, we only ever try calling `A.__add__`, never
`A.__radd__`. This is the case even if `__add__` is undefined.
2. If `B` is a subclass of `A`, and if `B` defines an `__radd__` method,
and we do `A() + B()`, Python will actually try checking `B.__radd__`
*first*, then `A.__add__` second.
This lets a subclass effectively "refine" the desired return type.
Note that if `B` only *inherits* an `__radd__` method, Python calls
`A.__add__` first as usual. Basically, `B` must provide a genuine
refinement over whatever `A` returns.
3. In all other cases, we call `__add__` then `__radd__` as usual.
This pull request modifies both checker.py and checkexpr.py to match
this behavior, and adds logic so that we check the calls in the
correct order.
This ended up slightly changing a few error messages in certain edge
cases.
0 commit comments