Skip to content

Fix false positive unreachable error for isinstance(x, UnionType) on TypeForm - #22022

Open
Dextheking1 wants to merge 1 commit into
python:masterfrom
Dextheking1:fix/typeform-uniontype-unreachable-21910
Open

Dextheking1 wants to merge 1 commit into
python:masterfrom
Dextheking1:fix/typeform-uniontype-unreachable-21910

Conversation

@Dextheking1

Copy link
Copy Markdown

Bug

With --warn-unreachable, mypy reported Statement is unreachable [unreachable] for isinstance(t, UnionType) when t: TypeForm[Any]:

from types import UnionType
from typing import Any
from typing_extensions import TypeForm

def g(t: TypeForm[Any]) -> Any:
    if isinstance(t, UnionType):  # error: Statement is unreachable [unreachable]
        pass

This is a false positive: at runtime a type expression like int | str is an instance of types.UnionType, so the check can genuinely succeed. mypy treated TypeForm and types.UnionType as disjoint.

(The sibling behavior for isinstance(t, Union) with bare Union is untouched — bare Union still errors with arg-type since it can't be used in isinstance at runtime.)

Fix

mypy/meet.py: teach is_overlapping_types that a TypeForm[T] overlaps with types.UnionType when the item can be a union expression — i.e. Any, a union, or an unconstrained type variable (via new helper _type_form_item_can_be_union). The check runs before the existing Type[C] vs metaclass case, which would otherwise return False.

Precision is preserved:

  • TypeForm[int] vs UnionType is still correctly reported unreachable (int is never a UnionType instance)
  • plain type[Any] (non-TypeForm) behavior is unchanged
  • the yes-branch narrows to types.UnionType; the else-branch keeps TypeForm[Any]

Test evidence

New regression test testTypeFormIsinstanceUnionType in test-data/unit/check-typeform.test (flags: --warn-unreachable) covering TypeForm[Any], TypeForm[int | str] (reachable, narrows to types.UnionType) and TypeForm[int] (still unreachable).

  • New test fails before the fix (Statement is unreachable on the reachable branches) and passes after
  • Suites run, all green: check-typeform.test + check-isinstance.test (244 passed), check-narrowing.test (175 passed, 1 xfailed), check-python310.test (202 passed, 1 skipped), check-overloading.test (272 passed, 1 skipped), testsubtypes.py (26 passed)

Closes #21910.

…TypeForm

With --warn-unreachable, mypy reported 'Statement is unreachable' for
isinstance(t, UnionType) when t: TypeForm[Any]. This is a false positive:
at runtime a type expression like int | str is an instance of
types.UnionType, so the check can succeed.

Teach is_overlapping_types that a TypeForm whose item can be a union
(Any, a union, or an unconstrained type variable) overlaps with
types.UnionType. TypeForm[int] and friends remain correctly unreachable,
and the bare-Union isinstance case is untouched.

Fixes python#21910.
@github-actions

Copy link
Copy Markdown
Contributor

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Union(Type) and TypeForm

1 participant