ruff
5ffba809 - [ty] Restrict length narrowing to types that encode their length (#25840)

Commit
144 days ago
[ty] Restrict length narrowing to types that encode their length (#25840) ## Summary Restrict exact `len()` narrowing to types that actually encode their possible lengths, so that we don't wrongly preserve length-narrowings on types with mutable length. Closes astral-sh/ty#3710. ## Test plan Added/updated mdtests. ### Ecosystem analysis 72 of the added diagnostics (48 in apprise, 19 in scrapy, plus some others) are from restoring correct reachability to code that was previously erroneously marked unreachable. 33 new diagnostics involve cases where we previously narrowed `None` out of a type after a `len` call (which itself errors since `None` is not `Sized`), since `None` is disjoint from `ExactlySized`. We could easily continue to do this (remove any non `Sized` types when narrowing from a `len` check), and I don't think it's wrong to do so? But it's kind of odd to narrow from a failed call, and no other type checker does it, so I haven't done it in this PR. 12 new diagnostics (all in packaging, or pip from its vendored packaging) come from a case where we are length-narrowing correctly, it's just we top-materialize `isinstance` and `object` is not assignable where a value from that tuple is used. This was silenced on main because we don't support exact unpacking from an intersection at all, and we previously had an intersection with `ExactlySized` here. Four new diagnostics in `ppb-vector` come from code like this: ```py def unpack(value: Sequence[int] | Mapping[str, int]): if isinstance(value, Sequence) and len(value) == 2: return value[0] if isinstance(value, Mapping) and "x" in value and len(value) == 2: return value["x"] raise ValueError ``` Where retaining the intersection with `~ExactlySized[2]` allowed us to rule out the "both a Sequence and a Mapping" case in the second branch (since if it were a sequence of length 2 it would have already taken the first branch). This is the only case where this PR regresses results. We could keep this by restoring `ExactlySized` and continuing to use it with `Sequence` and `Mapping` types -- but that would add a lot of code for something that has a very small ecosystem impact.
Author
Parents
Loading