fix: prevent false unreachable error when comparing generic callables#21188
Open
Bahtya wants to merge 2 commits intopython:masterfrom
Open
fix: prevent false unreachable error when comparing generic callables#21188Bahtya wants to merge 2 commits intopython:masterfrom
Bahtya wants to merge 2 commits intopython:masterfrom
Conversation
When comparing a generic Callable parameter with a generic function using ==, mypy incorrectly concluded the types could never overlap and marked the if-body as unreachable. Fix by extending shallow_erase_type_for_equality to handle CallableType and using erased current_type in the equality overlap checks. Fixes python#21182 Signed-off-by: bahtya <bahtyar153@qq.com>
for more information, see https://pre-commit.ci
Contributor
|
Diff from mypy_primer, showing the effect of this PR on open source code: rotki (https://github.com/rotki/rotki)
- rotkehlchen/tests/integration/test_premium.py:844: error: Statement is unreachable [unreachable]
+ rotkehlchen/tests/integration/test_premium.py:845: error: Statement is unreachable [unreachable]
- rotkehlchen/tests/integration/test_premium.py:858: error: Statement is unreachable [unreachable]
+ rotkehlchen/tests/integration/test_premium.py:859: error: Statement is unreachable [unreachable]
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Problem
Fixes #21182
When comparing a generic
Callableparameter with a generic function using==, mypy incorrectly reported "Statement is unreachable" with--warn-unreachable:This is a regression — the code was accepted in earlier mypy versions.
Root Cause
In
conditional_typeswithfrom_equality=True, mypy usesshallow_erase_type_for_equalityto erase generic type parameters from the proposed type before checking overlap. However:shallow_erase_type_for_equalityonly handledInstancetypes, notCallableType. So generic callables likedef [T] (x: T) -> Twere never erased.Only the proposed type was erased, not the current type. When
is_overlapping_typeswas called with an unerased generic callable ascurrent_type(e.g., the identity function with.variables=(T,)),is_callable_compatibletried to unify its type variables against the other callable's free type variables and failed, concluding the types don't overlap.At runtime, generic type parameters are erased, so
identityandcmp_propertycan absolutely be equal — one could be passed as the other.Solution
Two changes:
1. Extend
shallow_erase_type_for_equalitytoCallableType(mypy/erasetype.py).variableshave their arg types and return type replaced withAnyand variables cleared2. Erase both sides in the overlap check (
mypy/checker.py)conditional_types, applyshallow_erase_type_for_equalityto bothcurrent_typeandproposed_typebefore callingis_overlapping_typesTesting
unreachabletests passnarrowingtests passequalitytests passmeet/overlaptests passerasetests pass!=operator — all work correctly