Skip to content

False-positive on TypeVar bound class return value #10817

Closed
@SalomonSmeke

Description

@SalomonSmeke

Bug Report

When using a bound TypeVar, returning a type revealed as a class (not the generic) sometimes results in a false positive.

from typing import TypeVar

class A:
    pass
class B(A):
    pass

QBT = TypeVar("QBT", bound=A)

def fn(t: QBT) -> QBT:
    if not isinstance(t, B):
        raise NotImplementedError
    return t # <- Incompatible types in "return" (actual type "B", expected type "QBT")

To Reproduce

Minimal example available here: https://mypy-play.net/?mypy=latest&python=3.10&gist=a9419e2d2627a65ae181f16224680618

On python 3.10 and latest mypy. Though I originally reproduced it on python 3.8 and mypy 0.8.

Expected Behavior

I am not 100%, but I think this should be allowed. I checked in the gitter.im and @JelleZijlstra also thought it might be a bug.

Actual Behavior

Exception regarding return type. Happens with yields also.

Your Environment

  • Mypy version used: .8 and latest
  • Mypy command-line flags: None
  • Mypy configuration options from mypy.ini: Defaults
  • Python version used: 3.8 and 3.10
  • Operating system and version: macOS Big Sur / Centos7 / whatever mypy playground uses.

Workaround:

On .8 this does not work. But:

from typing import TypeVar, cast

class A:
    pass
class B(A):
    pass

QBT = TypeVar("QBT", bound=A)

def fn(t: QBT) -> QBT:
    if not isinstance(t, B):
        raise NotImplementedError
    return cast(QBT, t) # <- OK! on .8 its marked as redundant.

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