mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-04 02:38:25 +00:00
![]() ## Summary Consider the following example, which leads to a excessively large runtime on `main`. The reason for this is the following. When inferring types for `self.a`, we look up the `a` attribute on `C`. While looking for implicit instance attributes, we go through every method and check for `self.a = …` assignments. There are no such assignments here, but we always have an implicit `self.a = <unbound>` binding at the beginning over every method. This binding accumulates a complex visibility constraint in `C.f`, due to the `isinstance` checks. While evaluating that constraint, we need to infer the type of `self.b`. There's no binding for `self.b` either, but there's also an implicit `self.b = <unbound>` binding with the same complex visibility constraint (involving `self.b` recursively). This leads to a combinatorial explosion: ```py class C: def f(self: "C"): if isinstance(self.a, str): return if isinstance(self.b, str): return if isinstance(self.b, str): return if isinstance(self.b, str): return # repeat 20 times ``` (note that the `self` parameter here is annotated explicitly because we currently still infer `Unknown` for `self` otherwise) The fix proposed here is rather simple: when there are no `self.name = …` attribute assignments in a given method, we skip evaluating the visibility constraint of the implicit `self.name = <unbound>` binding. This should also generally help with performance, because that's a very common case. This is *not* a fix for cases where there *are* actual bindings in the method. When we add `self.a = 1; self.b = 1` to that example above, we still see that combinatorial explosion of runtime. I still think it's worth to make this optimization, as it fixes the problems with `pandas` and `sqlalchemy` reported by users. I will open a ticket to track that separately. closes https://github.com/astral-sh/ty/issues/627 closes https://github.com/astral-sh/ty/issues/641 ## Test Plan * Made sure that `ty` finishes quickly on the MREs in https://github.com/astral-sh/ty/issues/627 * Made sure that `ty` finishes quickly on `pandas` * Made sure that `ty` finishes quickly on `sqlalchemy` |
||
---|---|---|
.. | ||
resources | ||
src | ||
tests | ||
build.rs | ||
Cargo.toml | ||
mdtest.py | ||
mdtest.py.lock |