Skip to content

TypeVar in generic union member gets restricted to first constraint #3644

Closed
@JelleZijlstra

Description

@JelleZijlstra

In the below:

from typing import TypeVar, Generic, Union

AnyStr = TypeVar('AnyStr', str, bytes)

class PathLike(Generic[AnyStr]):
    def __fspath__(self) -> AnyStr: ...

def readlink(s: Union[AnyStr, PathLike[AnyStr]]) -> AnyStr:
    ...

class BP(PathLike[bytes]):
    def __fspath__(self) -> bytes:
        return b''

class SP(PathLike[str]):
    def __fspath__(self) -> str:
        return ''

reveal_type(readlink(''))
reveal_type(readlink(b''))
reveal_type(readlink(BP()))  # E: Argument 1 to "readlink" has incompatible type "BP"; expected "Union[str, PathLike[str]]"
reveal_type(readlink(SP()))

I ran mypy current master with no extra options.

The second to last line should type check and the type should be bytes, but instead mypy somehow expects Union[str, PathLike[str]]. If I switch around the order of the constraints on the TypeVar, it complains about the last line instead.

The following all make the error go away:

  • Changing the argument type of readlink to Union[str, PathLike[AnyStr]]
  • Changing the argument type to Union[AnyStr, PathLike]
    Changing the order of the Union doesn't make a difference.

Guido found this bug in a comment on python/typeshed#1441. I couldn't find any other reports in the tracker, but wasn't sure what to search for.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions