Skip to content

Incorrect type inference when using generics of "union" TypeVars #7913

Open

Description

@wadetregaskis-linkedin
from typing import MutableSet, Sequence, TypeVar

T = TypeVar('T', str, Sequence[str])

class CustomSet(MutableSet[T]):
    def add(self, value: T) -> None:
        pass

foo = CustomSet()
foo.add(('a', 'b'))

mypy 0.740 says: error: Argument 1 to "add" of "CustomSet" has incompatible type "Tuple[str, str]"; expected "str"

There's seemingly nothing I can do to get mypy to handle this pattern correctly. If I try explicitly specifying the type of foo, it just complains that the assignment to it is incompatible.

Activity

  1. wadetregaskis-linkedin commented on Nov 9, 2019

    @wadetregaskis-linkedin
    Author

    And to be clear, this is irrespective of whether T includes Sequence[str] as in my real code from which this case is simplified, or an extremely literal Tuple[str, str] - it appears that no matter what, mypy stubbornly assumes T is always str. It's not related to the order in the TypeVar either; moving str to the end doesn't influence mypy.

  2. wadetregaskis-linkedin commented on Nov 9, 2019

    @wadetregaskis-linkedin
    Author

    But changing str to int in the TypeVar does make mypy now stubbornly assume foo takes ints. For some reason mypy is picking the 'simplest' type in the TypeVar, to fixate on.

  3. jonathanslenders commented on Dec 2, 2019

    @jonathanslenders

    I think I have the same issue here:

    import asyncio
    
    async def f() -> None:
        future: asyncio.Future[None] = asyncio.Future()
    
        # error: Argument 1 to "gather" has incompatible type "Future[None]";
        #     expected "Union[Future[<nothing>], Generator[Any, None, <nothing>], Awaitable[<nothing>]]"
        await asyncio.gather(future)
  4. JelleZijlstra commented on Dec 2, 2019

    @JelleZijlstra
    Member

    @jonathanslenders that sounds like #8051.

  5. JukkaL commented on Dec 3, 2019

    @JukkaL
    Collaborator

    The inferred type for foo is incorrect (CustomSet[str]). Mypy should require a type annotation here.

    You can work around the issue by adding an explicit type annotation:

    ...
    foo: CustomSet[Sequence[str]] = CustomSet()
    foo.add(('a', 'b'))
  6. MarioIshac commented on Aug 29, 2020

    @MarioIshac

    I may have ran into same issue here:

    from typing import Union, TypeVar, Sequence
    
    T = TypeVar("T", bound=Union[int, str])
    
    def a(t: Sequence[T]):
        return t
    
    a([1, "a"])
    

    results in:

    Value of type variable "T" of "a" cannot be "object"
    

    but

    b: Sequence[Union[int, str]] = [1, "a"]
    a(b)
    

    works.

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

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions