Skip to content
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

Tuple types don't work with higher level typing #16935

Open
fjarri opened this issue Feb 21, 2024 · 2 comments · May be fixed by #17235
Open

Tuple types don't work with higher level typing #16935

fjarri opened this issue Feb 21, 2024 · 2 comments · May be fixed by #17235
Labels
bug mypy got something wrong

Comments

@fjarri
Copy link

fjarri commented Feb 21, 2024

mypy 1.8.0, python 3.10.10

So tuple types get matched and checked normally in simple situations like this:

a: tuple[int, int] = (2, "a")
# Incompatible types in assignment ...

But imagine I want to define a function that takes a type and returns a value of that type (e.g. by deserializing something as the given type):

from typing import Tuple, TypeVar, Type, List

_T = TypeVar("_T")

def structure(structure_into: Type[_T], obj: str) -> _T:
    raise NotImplementedError

This works with builtin types, or with generics like List:

reveal_type(structure(int, "a"))
# Revealed type is "builtins.int"
reveal_type(structure(List[int], "a"))
# Revealed type is "builtins.list[builtins.int]"

... but not with tuples:

reveal_type(structure(Tuple[int, int], "a"))
# note: Revealed type is "Never"
# error: Argument 1 to "structure" has incompatible type "object"; expected "type[Never]"  [arg-type]

Trying to reveal the type of Tuple itself leads to strange results too (compared to List[...]):

reveal_type(Tuple[int, int])
# Revealed type is "builtins.object"
reveal_type(tuple[int, int])
# Revealed type is "def [_T_co] (typing.Iterable[_T_co`1] =) -> builtins.tuple[_T_co`1, ...]"

So the question is, why does Tuple get a special treatment, and is there a way to make it behave like other generics?

@fjarri fjarri added the bug mypy got something wrong label Feb 21, 2024
@fjarri
Copy link
Author

fjarri commented Mar 15, 2024

Same issue with UnionType types (T1 | T2 | ...).

@urnest
Copy link

urnest commented Apr 25, 2024

am having a go at this in https://github.com/urnest/mypy/tree/issue-16935

urnest added a commit to urnest/mypy that referenced this issue May 12, 2024
... so e.g. reveal_type(tuple[int, int]) gives expected
def (p0: builtins.int, p1: builtins.int) ->
  tuple[builtins.int, builtins.int]

... rather than
def [_T_co] (typing.Iterable[_T_co`1] =) ->
  builtins.tuple[_T_co`1, ...]
urnest added a commit to urnest/mypy that referenced this issue May 12, 2024
... so e.g. reveal_type(tuple[int, int]) gives expected
def (p0: builtins.int, p1: builtins.int) ->
  tuple[builtins.int, builtins.int]

... rather than
def [_T_co] (typing.Iterable[_T_co`1] =) ->
  builtins.tuple[_T_co`1, ...]
@urnest urnest linked a pull request May 12, 2024 that will close this issue
urnest added a commit to urnest/mypy that referenced this issue Jun 1, 2024
…back

i.e. the mypy type of the expression union[str, int] is a
CallableType with fallback builtins.type

this matches the mypy type of the expression int
which is a CallableType with fallback builtins.type

(suggested by PR review discussion)
urnest added a commit to urnest/mypy that referenced this issue Jun 1, 2024
…back

... the original fallback ABCMeta is "correct" in that it aligns
with the (abstract) base class of builtins.tuple. But rather than
explicitly specify abc.ABCMeta as fallback, use the same
fallback as the type we're applying arguments to (and that is
abc.ABCMeta in our "tuple" case)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants