Skip to content

Fix handling of default arguments in generated glue methods #10825

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

Merged
merged 4 commits into from
Jul 15, 2021

Conversation

msullivan
Copy link
Collaborator

Currently these mostly segfault.

The main tricky case here is with *args and **kwargs (which we need to
deal with always when generating pycall glue and also when a native
function takes them), though we also need to take care to coerce error
values when forwarding optional arguments.

I also accidentally fixed a bug where we would compile f(a, *b, c)
as f(a, c, *b).

@msullivan msullivan requested a review from JukkaL July 15, 2021 07:07
@msullivan msullivan force-pushed the default-glue branch 2 times, most recently from b44f26e to 6edb06c Compare July 15, 2021 07:17
@msullivan
Copy link
Collaborator Author

Thanks to @pranavrajpal for spotting this class of issues with forwarding default arguments!

@msullivan msullivan force-pushed the default-glue branch 4 times, most recently from 39be7a4 to 44626de Compare July 15, 2021 15:55
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.

This looks solid, excellent!

Glue method generation must be one of the trickiest things we do in mypyc. The PR is still pretty easy to understand because of the high-quality comments. I very much appreciate them.

I can imagine it would be quite hard to debug what went wrong if a user would hit a bug in the old implementation.

Just left a few minor comments about docstrings and tests.

has_star2: bool) -> Tuple[Optional[Value], Optional[Value]]:
"""Construct *args and **kwargs from a collection of arguments

This is pretty complicated, and almost all of the complication here stems from
Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks for writing such a detailed explanation! This really made it easier to figure what is going on.

Can you briefly also document has_star and has_star2?


z: Foo = Bar()
z.f(1, z=2)
z.f(1, 2, 3)
Copy link
Collaborator

Choose a reason for hiding this comment

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

What about testing z.f(x=5)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I didn't test that because we (knowingly) don't do the right thing: we forward it as a positional argument and not a keyword one. I added a comment.

z: Foo = Baz()
z.f()
z.f(y=1)
z.f(1, 2)
Copy link
Collaborator

Choose a reason for hiding this comment

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

What about z.f(x=7)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Similar thing: in cpython this will raise a TypeError, since Baz.f wants the first argument to be a, but we forward it as a positional argument and not a keyword one, so it actually works.

print("stuff", args, kwargs)

z: Foo = Bar()
z.f(1, z=50)
Copy link
Collaborator

Choose a reason for hiding this comment

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

What about z.f(1) or z.f(z=50)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added both

Base automatically changed from pos-only-unannotated to master July 15, 2021 17:57
Currently these mostly segfault.

The main tricky case here is with *args and **kwargs (which we need to
deal with always when generating pycall glue and also when a native
function takes them), though we also need to take care to coerce error
values when forwarding optional arguments.

I also accidentally fixed a bug where we would compile `f(a, *b, c)`
as `f(a, c, *b)`.
@msullivan msullivan merged commit 5e83bd6 into master Jul 15, 2021
@msullivan msullivan deleted the default-glue branch July 15, 2021 22:11
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.

2 participants