fix: isinstance narrowing regression with dynamic tuple argument#21190
Open
Bahtya wants to merge 2 commits intopython:masterfrom
Open
fix: isinstance narrowing regression with dynamic tuple argument#21190Bahtya wants to merge 2 commits intopython:masterfrom
Bahtya wants to merge 2 commits intopython:masterfrom
Conversation
When isinstance is called with a dynamically-computed tuple of types (e.g. isinstance(exc, tuple(expected_excs))), the second argument's stored type gets widened to match the _ClassInfo recursive type alias (type | types.UnionType | tuple[_ClassInfo, ...]). The union handler in get_type_range_of_type then decomposes this into individual members, producing TypeRange(object, ...) from bare 'type', which incorrectly narrows the expression to 'object' instead of keeping its existing type. Fix by checking if the simplified union result is just 'object' — which indicates we've lost type precision — and returning None to fall back to keeping the current type, matching the v1.19 behavior. Also handle None sub-items explicitly (propagate uncertainty) and filter out UninhabitedType entries before simplifying. Fixes python#21181 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: psycopg (https://github.com/psycopg/psycopg)
- psycopg/psycopg/types/numeric.py:407: error: No overload variant of "int" matches argument type "object" [call-overload]
- psycopg/psycopg/types/numeric.py:407: note: Possible overload variants:
- psycopg/psycopg/types/numeric.py:407: note: def int(str | Buffer | SupportsInt | SupportsIndex = ..., /) -> int
- psycopg/psycopg/types/numeric.py:407: note: def int(str | bytes | bytearray, /, base: SupportsIndex) -> int
hydra-zen (https://github.com/mit-ll-responsible-ai/hydra-zen)
+ src/hydra_zen/_launch.py:92: error: Redundant cast to "T" [redundant-cast]
|
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
When
isinstanceis called with a dynamically-computed tuple of types (e.g.isinstance(exc, tuple(expected_excs))), mypy 1.20 incorrectly narrows the expression toobjectinstead of keeping its already-narrowed type. This is a regression from 1.19.Root Cause
The second argument to
isinstancehas its type stored as the expanded_ClassInforecursive type alias (type | types.UnionType | tuple[_ClassInfo, ...]) rather than the precisetuple[type[BaseException], ...].In
get_type_range_of_type, theUnionTypehandler decomposes this union into individual members. The baretypemember producesTypeRange(object, is_upper_bound=True), which after union simplification becomes the sole result. This causesconditional_typesto narrow toobject— a broader type than the already-narrowedBaseException.In mypy 1.19, the raw
UnionTypewas not handled by the type-range logic (it fell through toreturn None), which correctly preserved the existing narrowed type.Solution
In
get_type_range_of_typeUnionType handler:Noneif any sub-item returnsNone(uncertainty)UninhabitedTypeentries before simplifyingobject, returnNone— this indicates type precision was lost (e.g. from the_ClassInfowidening), and we should fall back to keeping the current typeTesting
Fixes #21181