Repository navigation
[mypyc] add support for contextlib.contextmanager - #22267
hauntsaninja wants to merge 8 commits into
Conversation
|
I guess you can say that this fixes mypyc/mypyc#905, right? (Btw I didn't look in details, @JukkaL would be a better reviewer here.) |
| wrapped_call = mypy.nodes.CallExpr( | ||
| mypy.nodes.MemberExpr(expr.callee, "__wrapped__"), | ||
| expr.args, | ||
| expr.arg_kinds, | ||
| expr.arg_names, | ||
| ) | ||
| wrapped_call.line = line | ||
| gen = builder.accept(wrapped_call) |
There was a problem hiding this comment.
i think this results in a generic Python attribute access + generic function call at runtime which we could optimize for compiled functions decorated with @contextmanager. for those we could call the generated C function directly.
| assert isinstance(expr.callee, mypy.nodes.MemberExpr) | ||
| receiver = builder.accept(receiver_expr) | ||
| method = builder.py_get_attr(receiver, expr.callee.name, line) | ||
| wrapped = builder.py_get_attr(method, "__wrapped__", line) |
There was a problem hiding this comment.
for non-final methods we should check and optimize only if __wrapped__ actually exists because it's legal to override a contextmanager method with a regular method in a subclass.
we might be able to optimize the call for final methods and for methods of compiled classes that don't allow interpreted subclasses by calling the C function directly.
|
Thanks for the review, will address! I used prints instead of runtime asserts because the exception logic is actually kind of tricky and was a source of bugs for me, very easy to accidentally suppress an exception I couldn't see an easy way to find the generated C function. Codex had a diff where it did something that created some new statics, it benchmarked only a little bit better, but you're right that it could be a little more robust. Let me investigate it. |
Should make self check like 6-10% faster and torch 8-12% faster (compiled, clean cache, not parallel)
Fixes mypyc/mypyc#905
Co-authored by Codex