Repository navigation
Don't narrow unions to Never on isinstance with a TypeVar classinfo - #5261
Open
Divyansh151005 wants to merge 1 commit into
Open
Divyansh151005 wants to merge 1 commit into
Divyansh151005 wants to merge 1 commit into
Conversation
Fixes facebook#5147. When the value being narrowed is a union, `narrow_isinstance_from_definite` intersects each member with the isinstance target using a `Never` fallback, so that e.g. `isinstance(x, Iterable)` on `int | list[int]` narrows to just `list[int]`. With a `type[T]` classinfo every concrete member is unrelated to `T`, so the whole union collapsed to `Never`. Use the regular intersection fallback when the target is a type variable, giving `(int & T) | (str & T)` (consistent with narrowing `x: T` against concrete classes). Members that cannot overlap with the TypeVar's bound are still dropped via `disjoint_base`.
Contributor
|
This pull request has been imported. If you are a Meta employee, you can view this in D125878285. (Because this pull request was imported automatically, there will not be any future comments.) |
|
According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅ |
This branch has not been deployed
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.
Summary
Fixes #5147
isinstancewith atype[T]classinfo narrowed a union-typed value toNever:Narrowing to
Nevermakes the rest of the branch look unreachable, so errors inside it are silently suppressed.Root cause. When the narrowed value is a union,
narrow_isinstance_from_definiteintersects each member with the target usingIntersectFallback::Never. That is intentional for concrete targets, soisinstance(x, Iterable)onint | list[int]narrows to justlist[int]. A type variable target, however, is neither a subtype nor a supertype of any concrete member, so every member hit the fallback and the whole union becameNever. (The non-union case already used theRightfallback and producedint & T.)Fix. Use the regular
Rightfallback when the target is a type variable. Each member then intersects withT, producing(int & T) | (str & T). This is consistent with how we already narrowx: Tagainst concrete classes (e.g.(float & T) | (int & T)intest_typevar_isinstance_narrow_else) and with what ty reports. Members that cannot overlap with the TypeVar's bound are still removed, sinceintersect_implcomparesdisjoint_bases anddisjoint_baseuses the bound: withT: int,int | strnarrows toT.The
Neverfallback for concrete targets is unchanged.Test Plan
Added
test_isinstance_union_with_typevar_classinfotopyrefly/lib/test/narrow.rs, covering:int | strnarrowed bytype[T]→(int & T) | (str & T); the negative branch staysint | strT: int):int | str→T(thestrmember is dropped via the bound)int→int & T(unchanged)-> Tfunction type-checksBefore the fix:
After: