fix: handle union-bound TypeVar in type[T] callable analysis#21191
Open
Bahtya wants to merge 1 commit intopython:masterfrom
Open
fix: handle union-bound TypeVar in type[T] callable analysis#21191Bahtya wants to merge 1 commit intopython:masterfrom
Bahtya wants to merge 1 commit intopython:masterfrom
Conversation
When a TypeVar T has a union bound (e.g. T: bool|int|float|str), calling a value of type type[T] would incorrectly infer the return type as the union rather than T. This happened because analyze_type_type_callee only replaced return types for CallableType and Overloaded, not for UnionType. Additionally, CallableType.type_object() would crash with an assertion error when encountering a TypeVarType whose upper_bound is a union, since it expected all paths to resolve to an Instance. Fixes python#21106 Signed-off-by: bahtya <bahtyar153@qq.com>
Contributor
|
According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅ |
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 a TypeVar
Thas a union bound (e.g.T: bool | int | float | str), calling a value of typetype[T]produces a false positive:The error is:
Incompatible return value type (got "int | float | str", expected "T").With a single-type bound (e.g.
T: int) this works correctly.Root Cause
Two issues in
checkexpr.pyandtypes.py:analyze_type_type_callee(checkexpr.py): When handlingTypeVarType, it recurses on the upper bound. For a union bound, this returns aUnionTypeof callables, but the code only replaced return types with the TypeVar forCallableTypeandOverloaded— notUnionType. The union members kept their original return types (e.g.int,float) instead ofT.CallableType.type_object()(types.py): When a TypeVar's upper bound is a union,get_proper_type(ret.upper_bound)returns aUnionType, which hits the finalassert isinstance(ret, Instance)and crashes.Solution
Added a
_replace_callable_return_typehelper and aUnionTypebranch in theTypeVarTypehandling inanalyze_type_type_callee, so each callable in the union gets its return type replaced with the TypeVar.Added a
UnionTypecase inCallableType.type_object()that resolves to the firstInstancein the union (this is only used foris_protocolchecks, which don't apply to union-bound TypeVars).Testing
Verified with the exact reproduction case from the issue — now passes with no errors. Also tested:
reveal_type(func(bool, 'True'))showsbool, not the full unionmypy_self_check.ini)