Skip to content

isinstance with TypeVar in Tuple doesn't accurately determine TypeVar #4949

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
ikelos opened this issue Apr 22, 2018 · 3 comments
Open

isinstance with TypeVar in Tuple doesn't accurately determine TypeVar #4949

ikelos opened this issue Apr 22, 2018 · 3 comments
Labels
bug mypy got something wrong false-positive mypy gave an error on correct code priority-1-normal

Comments

@ikelos
Copy link

ikelos commented Apr 22, 2018

Mypy version: 0.590
Python version: 3.6.5

I don't know if I've described this accurately, but it's probably best described by some code. I've reduced this to the simple scenario I can find:

T = TypeVar('T', bound = A)

def check_subtype(instance: A, instance_type: Tuple[Type[T], ...]) -> Optional[T]:
    if isinstance(instance, instance_type):
      return instance
    return None

returns

test.py:15: error: Incompatible return value type (got "A", expected "Optional[T]")

Removing the Tuple and only allowing one Type to be passed to isinstance gives no errors:

T = TypeVar('T', bound = A)

def check_subtype(instance: A, instance_type: Type[T]) -> Optional[T]:
    if isinstance(instance, instance_type):
      return instance
    return None

My understanding was that the signature for isinstance was Union[Type[T], Tuple[Type[T], ...]], so I'd have expected similar outputs when providing it a Type[T] versus a Tuple[Type[T], ...]?

@gvanrossum
Copy link
Member

gvanrossum commented Apr 22, 2018 via email

@ilevkivskyi ilevkivskyi added bug mypy got something wrong priority-1-normal labels Apr 23, 2018
@ilevkivskyi ilevkivskyi added the false-positive mypy gave an error on correct code label May 19, 2018
@roosemberth
Copy link

I believe to have stumbled with another instance of this problem:

from typing import TypeVar, Dict, Tuple

TT = TypeVar('TT', bound=Tuple)
KT = TypeVar('KT', bound=Dict)

def k1() -> Tuple[Tuple[int, int], Dict[str, int]]:
    return (23, 42), dict(ds=42)  # No problem


def k2() -> Tuple[TT, KT]:
    # vv Incompatible return value type (got "Tuple[Tuple[int, int], Dict[str, int]]", expected "Tuple[TT, KT]")
    return (23, 231231), dict(ds=42)

@JelleZijlstra
Copy link
Member

@roosemberth I don't think that code is correct, because you use TypeVars without anything to constrain them. Usually you only want to use TypeVars in the signature of a function if you're using them in multiple places, because the point of a TypeVar is to constrain multiple types to be the same.

Maybe there's still a bug here (mypy's error message could be better), but in that case it's unrelated to the original bug in this issue, which is about isinstance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong false-positive mypy gave an error on correct code priority-1-normal
Projects
None yet
Development

No branches or pull requests

5 participants