Make reachability code understand chained comparisons (v2) (#8148) #3
+956
−65
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This pull request is v2 (well, more like v10...) of my attempts to
make our reachability code better understand chained comparisons.
Unlike python#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:
This pull request fixes this so we correctly infer the literal type
for x and y in both conditionals.
Some additional notes:
While analyzing our codebase, I found that while comparison
expressions involving two or more
is
or==
operatorswere somewhat common, there were almost no comparisons involving
chains of
!=
oris not
operators, and no comparisonsinvolving "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.
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.
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 littletoo overwhelming for me. So, baby steps.)