From 6eafc5e3487866001d0447514e67d3861c13bb7b Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Mon, 5 Jul 2021 14:52:15 +0100 Subject: [PATCH] Fixes to generic builtin types (#10766) This fixes these issues: * Allow variable-length tuple (tuple[int, ...]) in type aliases * Allow generic built-in types (e.g. list[int]) in stubs in all Python versions Fixes #9980. Fixes #10303. Fixes #10731. --- mypy/semanal.py | 11 +++++-- mypy/typeanal.py | 3 +- test-data/unit/check-generic-alias.test | 43 +++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index ae3d176aa154..96ef7401bf42 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -76,7 +76,7 @@ get_nongen_builtins, get_member_expr_fullname, REVEAL_TYPE, REVEAL_LOCALS, is_final_node, TypedDictExpr, type_aliases_source_versions, EnumCallExpr, RUNTIME_PROTOCOL_DECOS, FakeExpression, Statement, AssignmentExpr, - ParamSpecExpr + ParamSpecExpr, EllipsisExpr ) from mypy.tvar_scope import TypeVarLikeScope from mypy.typevars import fill_typevars @@ -91,7 +91,8 @@ FunctionLike, UnboundType, TypeVarDef, TupleType, UnionType, StarType, CallableType, Overloaded, Instance, Type, AnyType, LiteralType, LiteralValue, TypeTranslator, TypeOfAny, TypeType, NoneType, PlaceholderType, TPDICT_NAMES, ProperType, - get_proper_type, get_proper_types, TypeAliasType) + get_proper_type, get_proper_types, TypeAliasType +) from mypy.typeops import function_type from mypy.type_visitor import TypeQuery from mypy.nodes import implicit_module_attrs @@ -3867,7 +3868,8 @@ def analyze_type_application(self, expr: IndexExpr) -> None: # ...or directly. else: n = self.lookup_type_node(base) - if n and n.fullname in get_nongen_builtins(self.options.python_version): + if (n and n.fullname in get_nongen_builtins(self.options.python_version) and + not self.is_stub_file): self.fail(no_subscript_builtin_alias(n.fullname, propose_alt=False), expr) def analyze_type_application_args(self, expr: IndexExpr) -> Optional[List[Type]]: @@ -3883,6 +3885,9 @@ def analyze_type_application_args(self, expr: IndexExpr) -> Optional[List[Type]] types: List[Type] = [] if isinstance(index, TupleExpr): items = index.items + is_tuple = isinstance(expr.base, RefExpr) and expr.base.fullname == 'builtins.tuple' + if is_tuple and len(items) == 2 and isinstance(items[-1], EllipsisExpr): + items = items[:-1] else: items = [index] for item in items: diff --git a/mypy/typeanal.py b/mypy/typeanal.py index bcec18bd925f..503a9bb99cf5 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -281,7 +281,8 @@ def try_analyze_special_unbound_type(self, t: UnboundType, fullname: str) -> Opt return AnyType(TypeOfAny.from_error) elif (fullname == 'typing.Tuple' or (fullname == 'builtins.tuple' and (self.options.python_version >= (3, 9) or - self.api.is_future_flag_set('annotations')))): + self.api.is_future_flag_set('annotations') or + self.allow_unnormalized))): # Tuple is special because it is involved in builtin import cycle # and may be not ready when used. sym = self.api.lookup_fully_qualified_or_none('builtins.tuple') diff --git a/test-data/unit/check-generic-alias.test b/test-data/unit/check-generic-alias.test index 5cfe77b9c0fc..b6060f3922fe 100644 --- a/test-data/unit/check-generic-alias.test +++ b/test-data/unit/check-generic-alias.test @@ -239,3 +239,46 @@ t09: tuple[int, ...] = (1, 2, 3) from typing import Tuple t10: Tuple[int, ...] = t09 [builtins fixtures/tuple.pyi] + +[case testTypeAliasWithBuiltinTuple] +# flags: --python-version 3.9 + +A = tuple[int, ...] +a: A = () +b: A = (1, 2, 3) +c: A = ('x', 'y') # E: Incompatible types in assignment (expression has type "Tuple[str, str]", variable has type "Tuple[int, ...]") + +B = tuple[int, str] +x: B = (1, 'x') +y: B = ('x', 1) # E: Incompatible types in assignment (expression has type "Tuple[str, int]", variable has type "Tuple[int, str]") + +reveal_type(tuple[int, ...]()) # N: Revealed type is "builtins.tuple[builtins.int*]" +[builtins fixtures/tuple.pyi] + +[case testTypeAliasWithBuiltinTupleInStub] +# flags: --python-version 3.6 +import m +reveal_type(m.a) # N: Revealed type is "builtins.tuple[builtins.int]" +reveal_type(m.b) # N: Revealed type is "Tuple[builtins.int, builtins.str]" + +[file m.pyi] +A = tuple[int, ...] +a: A +B = tuple[int, str] +b: B +[builtins fixtures/tuple.pyi] + +[case testTypeAliasWithBuiltinListInStub] +# flags: --python-version 3.6 +import m +reveal_type(m.a) # N: Revealed type is "builtins.list[builtins.int]" +reveal_type(m.b) # N: Revealed type is "builtins.list[builtins.list[builtins.int]]" + +[file m.pyi] +A = list[int] +a: A +B = list[list[int]] +b: B +class C(list[int]): + pass +[builtins fixtures/list.pyi]