Skip to content

Narrowing depends on the order of isinstance checks when using a genric type #10178

Closed

Description

@heg-ulmuten

Bug Report

Mypy is incoherent in the following code even though the only difference is the order of the isinstance checks. I know that Optional is the idiomatic mypy way to represent possibly missing values, but this is the smallest example I found that shows the problem.

from dataclasses import dataclass
from typing import Generic, TypeVar, Union, NoReturn


def assert_never(a: NoReturn) -> NoReturn:
    raise AssertionError("Unhandled type: {}".format(type(a).__name__))


@dataclass
class Nothing:
    pass


T = TypeVar("T")


@dataclass
class Just(Generic[T]):
    value: T


Maybe = Union[Nothing, Just[T]]


def ok(a: Maybe[int]) -> None:
    if isinstance(a, Just):
        print(a.value)
    elif isinstance(a, Nothing):
        print("nothing")
    else:
        assert_never(a)


def ko(a: Maybe[int]) -> None:
    if isinstance(a, Nothing):
        print("nothing")
    elif isinstance(a, Just):
        print(a.value)
    else:
        assert_never(a)

Expected Behavior

Either mypy finds an error in both functions or neither.

Actual Behavior

In the ko function, mypy finds this error for the last line:
Argument 1 to "assert_never" has incompatible type "Just[int]"; expected "NoReturn"

If I use a concrete type instead of a generic one in the Just class no error is reported in both functions.

Your Environment

  • Mypy version used: 0.812
  • Mypy command-line flags: N/A
  • Mypy configuration options from mypy.ini (and other config files): N/A
  • Python version used: 3.9.2
  • Operating system and version: N/A

Activity

  1. erictraut commented on Aug 12, 2023

    @erictraut

    This bug appears to have been fixed. It no longer repros with the latest version of mypy.

  2. hauntsaninja commented on Aug 12, 2023

    @hauntsaninja
    Collaborator

    I think fixed by #11273

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrongtopic-type-narrowingConditional type narrowing / binder

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions