Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mypyc] Support __pow__, __rpow__, and __ipow__ dunders #14616

Merged
merged 2 commits into from
Feb 16, 2023

Conversation

ichard26
Copy link
Collaborator

@ichard26 ichard26 commented Feb 5, 2023

Unlike every other slot, power slots are ternary. Some special casing had to be done in generate_bin_op_wrapper() to support the third slot argument. Annoyingly, pow() also has these unique behaviours:

  • Ternary pow() does NOT fallback to __rpow__ if __pow__ returns NotImplemented unlike binary ops.
  • Ternary pow() does NOT try the right operand's __rpow__ first if it's a subclass of the left operand and redefines __rpow__ unlike binary ops.

Add in the fact it's allowed and common to only define __(r|i)pow__ to take two arguments (actually mypy won't let you define __rpow__ to take three arguments) and the patch becomes frustratingly non-trivial.

Towards mypyc/mypyc#553. Fixes mypyc/mypyc#907.

Unlike every other slot, power slots are ternary. Lots of special casing
had to be done in generate_bin_op_wrapper() to support the third slot
argument.

- Ternary pow() does NOT fallback to __rpow__ if __pow__ returns
  NotImplemented unlike binary ops.
- Ternary pow() does NOT try the right operand's __rpow__ first if it's
  a subclass of the left operand and redefines __rpow__ unlike binary
  ops.

Add in the fact it's allowed and common to only define __(r|i)pow__ to
take two arguments and you get a mess of a patch...
Copy link
Collaborator

@JukkaL JukkaL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks for considering all cases carefully. This was tricky! These are some of the most important remaining dunders that we need to support.

"""
gen = WrapperGenerator(cl, emitter)
gen.set_target(fn)
assert len(fn.args) in (2, 3), "__ipow__ should only take 2 or 3 arguments"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The number of arguments accepted by dunders mostly isn't checked by mypy or mypyc, so it looks like we can actually trip the assertion -- but that's a more general problem and doesn't need to be addressed now (mypyc/mypyc#949).

@JukkaL JukkaL merged commit bcf60ac into python:master Feb 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

"TypeError: unsupported operand type(s) for **" despite having __pow__
2 participants