Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -3270,7 +3270,11 @@ def apply_type_arguments_to_callable(
tp = get_proper_type(tp)

if isinstance(tp, CallableType):
if len(tp.variables) != len(args):
if tp.is_type_obj() and tp.type_object().fullname == 'builtins.tuple':
# We special case `tuple` callable, because it can accept
# a different amount of args: `tuple[int]`, `tuple[int, str, str]`
return tp
elif len(tp.variables) != len(args):
self.msg.incompatible_type_application(len(tp.variables),
len(args), ctx)
return AnyType(TypeOfAny.from_error)
Expand Down
24 changes: 24 additions & 0 deletions test-data/unit/check-type-aliases.test
Original file line number Diff line number Diff line change
Expand Up @@ -728,3 +728,27 @@ from typing_extensions import TypeAlias
A: TypeAlias = str
[builtins fixtures/bool.pyi]
[out]

[case testTupleWithDifferentArgsPy38]
# flags: --python-version 3.8
NotYet1 = tuple[float] # E: "tuple" is not subscriptable
NotYet2 = tuple[float, float] # E: "tuple" is not subscriptable
[builtins fixtures/tuple.pyi]

[case testTupleWithDifferentArgsStub]
# https://github.com/python/mypy/issues/11098
import tup
[file tup.pyi]
Correct1 = str | tuple[float, float, str]
Correct2 = tuple[float] | str
Correct3 = tuple[float, ...] | str

RHSAlias1: type = tuple[int, int]
RHSAlias2: type = tuple[int]
RHSAlias3: type = tuple[int, ...]

# Wrong:

WrongTypeElement = str | tuple[float, 1] # E: Invalid type: try using Literal[1] instead?
WrongEllipsis = str | tuple[float, float, ...] # E: Unexpected "..."
[builtins fixtures/tuple.pyi]
18 changes: 18 additions & 0 deletions test-data/unit/pythoneval.test
Original file line number Diff line number Diff line change
Expand Up @@ -1586,3 +1586,21 @@ class Foo(Enum):
_testEnumValueWithPlaceholderNodeType.py:5: error: Incompatible types in assignment (expression has type "object", variable has type "Foo")
_testEnumValueWithPlaceholderNodeType.py:6: error: Incompatible types in assignment (expression has type "object", variable has type "Foo")
_testEnumValueWithPlaceholderNodeType.py:6: error: Name "Missing" is not defined

[case testTupleWithDifferentArgsPy310]
# https://github.com/python/mypy/issues/11098
# flags: --python-version 3.10
Correct1 = str | tuple[float, float, str]
Correct2 = tuple[float] | str
Correct3 = tuple[float, ...] | str

RHSAlias1: type = tuple[int, int]
RHSAlias2: type = tuple[int]
RHSAlias3: type = tuple[int, ...]

# Wrong:
WrongTypeElement = str | tuple[float, 1]
WrongEllipsis = tuple[float, float, ...] | str
[out]
_testTupleWithDifferentArgsPy310.py:12: error: Invalid type: try using Literal[1] instead?
_testTupleWithDifferentArgsPy310.py:13: error: Unexpected "..."