-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Commit 9101707
authored
Make reachability code understand chained comparisons (v2) (#8148)
This pull request is v2 (well, more like v10...) of my attempts to
make our reachability code better understand chained comparisons.
Unlike #7169, this diff focuses
exclusively on adding support for chained operation comparisons and
deliberately does not attempt to change any of the semantics of
how identity and equality operations are performed.
Specifically, mypy currently only examines the first two operands
within a comparison expression when refining types. That means
the following expressions all do not behave as expected:
```python
x: MyEnum
y: MyEnum
if x is y is MyEnum.A:
# x and y are not narrowed at all
if x is MyEnum.A is y:
# Only x is narrowed to Literal[MyEnum.A]
```
This pull request fixes this so we correctly infer the literal type
for x and y in both conditionals.
Some additional notes:
1. While analyzing our codebase, I found that while comparison
expressions involving two or more `is` or `==` operators
were somewhat common, there were almost no comparisons involving
chains of `!=` or `is not` operators, and no comparisons
involving "disjoint chains" -- e.g. expressions like
`a == b < c == b` where there are multiple "disjoint"
chains of equality comparisons.
So, this diff is primarily designed to handle the case where
a comparison expression has just one chain of `is` or `==`.
For all other cases, I fall back to the more naive strategy
of evaluating each comparison individually and and-ing the
inferred types together without attempting to propagate
any info.
2. I tested this code against one of our internal codebases. This
ended up making mypy produce 3 or 4 new errors, but they all
seemed legitimate, as far as I can tell.
3. I plan on submitting a follow-up diff that takes advantage of
the work done in this diff to complete support for tagged unions
using any Literal key, as previously promised.
(I tried adding support for tagged unions in this diff, but
attempting to simultaneously add support for chained comparisons
while overhauling the semantics of `==` proved to be a little
too overwhelming for me. So, baby steps.)1 parent 5336f27 commit 9101707Copy full SHA for 9101707
File tree
5 files changed
+956
-65
lines changedFilter options
- mypy
- test
- test-data/unit
5 files changed
+956
-65
lines changed
0 commit comments