Conversation
|
Thanks for all the mypyc PRs! I will probably leave them all to @JukkaL and @p-sawicki (or maybe I will take one-two if they are busy). |
|
Thanks for the! This is a useful improvement. I found a few regressions when trying this out. First, this crashes the compiler: def f(x: object, classes: tuple[type, ...]) -> bool:
return isinstance(x, (int, *classes))The assertion here unexpectedly fails (this is pretty esoteric though): def f(x: object) -> bool:
cls: type = int
return isinstance(x, (cls, (cls := str)))
assert f(1)Maybe fall back to the old approach in these cases? However, this could slightly change semantics. |
|
@JukkaL Oof. Good catch. I'll be honest, out of all the mypyc PRs I opened this weekend, this one was the one I had the least confidence in. Fwiw, #22099 is second... You are correct, I think the only way to handle those is to fall back to the old method since a star-expansion can have a variable number of items of unreliable types, and a walrus operator can change the values. I think the walrus regression would be the mypyc equivalent of #21249 . I've also added tests for this. Also just testing now I think I found an issue that also fails on master which is similar to the second regression. I don't see it reported anywhere. Your test there is about when the walrus replaces a var in the tuple, but I seem to have problems when it replaces another arg as well. For example, |
Fixes mypyc/mypyc#1227
This is just an idea for how to improve performance, for an issue that was exposed to me because of the issues in PR #22097 .
isinstance(x, (A, B))is specialized when every class in the tuple is a primitive type (#19949) or every class is a native class (mypyc/mypyc#413). Anything else falls back to the generic path, which builds a new tuple and callsPyObject_IsInstanceon every call, so the primitive types in the tuple lose their fast checks as well. That covers:isinstance(x, (float, MyNativeClass))isinstance(x, (float, Decimal))isinstance(x, (int, (float, str)))The chained checks added in #19949 could be generalized: flatten nested tuples, use the fast checks for primitive types and native classes, and check any other class with its own
PyObject_IsInstancecall, so no tuple is built. In a quick microbenchmark this takesisinstance(x, (float, MyNativeClass))from about 50 ns to about 5 ns per call.Relatedly,
isinstance(f(), ())currently returnsFalsewithout callingf().