From be7bc522210be11d917781047dbf61b96d4450a0 Mon Sep 17 00:00:00 2001 From: Brian Schubert Date: Tue, 19 Nov 2024 16:29:29 -0500 Subject: [PATCH 1/4] Disallow implicitly generic aliases when using PEP 613 explicit aliases --- mypy/semanal.py | 13 +++++++------ test-data/unit/check-type-aliases.test | 12 ++++++++++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 59e4594353f0..14f4b1bcedf9 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -2765,15 +2765,15 @@ def get_declared_metaclass( return None, True, False # defer later in the caller # Support type aliases, like `_Meta: TypeAlias = type` + metaclass_info: Node | None = sym.node if ( isinstance(sym.node, TypeAlias) - and sym.node.no_args - and isinstance(sym.node.target, ProperType) - and isinstance(sym.node.target, Instance) + and not sym.node.python_3_12_type_alias + and not sym.node.alias_tvars ): - metaclass_info: Node | None = sym.node.target.type - else: - metaclass_info = sym.node + target = get_proper_type(sym.node.target) + if isinstance(target, Instance): + metaclass_info = target.type if not isinstance(metaclass_info, TypeInfo) or metaclass_info.tuple_type is not None: self.fail(f'Invalid metaclass "{metaclass_name}"', metaclass_expr) @@ -4040,6 +4040,7 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> bool: and not res.args and not empty_tuple_index and not pep_695 + and not pep_613 ) if isinstance(res, ProperType) and isinstance(res, Instance): if not validate_instance(res, self.fail, empty_tuple_index): diff --git a/test-data/unit/check-type-aliases.test b/test-data/unit/check-type-aliases.test index c7b9694a9188..6018efff4e64 100644 --- a/test-data/unit/check-type-aliases.test +++ b/test-data/unit/check-type-aliases.test @@ -1238,3 +1238,15 @@ from typing import List, Union A = Union[int, List[A]] def func(x: A) -> int: ... [builtins fixtures/tuple.pyi] + +[case testAliasExplicitNoArgsNotGeneric] +from typing import List, assert_type +from typing_extensions import TypeAlias + +Implicit = List +Explicit: TypeAlias = List + +x1: Implicit[str] +x2: Explicit[str] # E: Bad number of arguments for type alias, expected 0, given 1 +assert_type(x1, List[str]) +[builtins fixtures/tuple.pyi] From 6563c362fd5ee8e1fbf17775eab5dcad5a0a7459 Mon Sep 17 00:00:00 2001 From: Brian Schubert Date: Tue, 19 Nov 2024 16:29:56 -0500 Subject: [PATCH 2/4] Delete stale comment referencing non-existent attribute --- mypy/nodes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/nodes.py b/mypy/nodes.py index 56c61ce26d63..db5ef829a41a 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -3593,7 +3593,7 @@ def f(x: B[T]) -> T: ... # without T, Any would be used here type will be initially an instance type with wrong number of type arguments. Such instances are all fixed either during or after main semantic analysis passes. We therefore store the difference between `List` and `List[Any]` rvalues (targets) - using the `no_args` flag. See also TypeAliasExpr.no_args. + using the `no_args` flag. Meaning of other fields: From a5e3cb51c7421a7855a7a0883d8da76d7b55de3b Mon Sep 17 00:00:00 2001 From: Brian Schubert Date: Tue, 19 Nov 2024 19:15:18 -0500 Subject: [PATCH 3/4] Update test: no-args PEP 613 aliases are no longer eagerly expanded This is expected, now that the below branch is no longer taken for PEP 613 aliases. Implicit aliases are now the only case with eager expansion. https://github.com/python/mypy/blob/21587f01045246a9ecb54a054a5ba03e20cbbd19/mypy/typeanal.py#L2147-L2151 --- test-data/unit/diff.test | 1 - 1 file changed, 1 deletion(-) diff --git a/test-data/unit/diff.test b/test-data/unit/diff.test index 4acf451e2c34..b7c71c7f37f2 100644 --- a/test-data/unit/diff.test +++ b/test-data/unit/diff.test @@ -1563,7 +1563,6 @@ type H[T] = int __main__.A __main__.C __main__.D -__main__.E __main__.G __main__.H From d1c756bc5a8b93359f2b094e9edfeee293b65029 Mon Sep 17 00:00:00 2001 From: Brian Schubert Date: Thu, 21 Nov 2024 11:18:58 -0500 Subject: [PATCH 4/4] Add tests for generic classes and tuple/callable special cases --- test-data/unit/check-type-aliases.test | 45 ++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/test-data/unit/check-type-aliases.test b/test-data/unit/check-type-aliases.test index 6018efff4e64..dd8e46bad261 100644 --- a/test-data/unit/check-type-aliases.test +++ b/test-data/unit/check-type-aliases.test @@ -1239,8 +1239,8 @@ A = Union[int, List[A]] def func(x: A) -> int: ... [builtins fixtures/tuple.pyi] -[case testAliasExplicitNoArgsNotGeneric] -from typing import List, assert_type +[case testAliasExplicitNoArgsBasic] +from typing import Any, List, assert_type from typing_extensions import TypeAlias Implicit = List @@ -1249,4 +1249,45 @@ Explicit: TypeAlias = List x1: Implicit[str] x2: Explicit[str] # E: Bad number of arguments for type alias, expected 0, given 1 assert_type(x1, List[str]) +assert_type(x2, List[Any]) +[builtins fixtures/tuple.pyi] + +[case testAliasExplicitNoArgsGenericClass] +# flags: --python-version 3.9 +from typing import Any, assert_type +from typing_extensions import TypeAlias + +Implicit = list +Explicit: TypeAlias = list + +x1: Implicit[str] +x2: Explicit[str] # E: Bad number of arguments for type alias, expected 0, given 1 +assert_type(x1, list[str]) +assert_type(x2, list[Any]) +[builtins fixtures/tuple.pyi] + +[case testAliasExplicitNoArgsTuple] +from typing import Any, Tuple, assert_type +from typing_extensions import TypeAlias + +Implicit = Tuple +Explicit: TypeAlias = Tuple + +x1: Implicit[str] # E: Bad number of arguments for type alias, expected 0, given 1 +x2: Explicit[str] # E: Bad number of arguments for type alias, expected 0, given 1 +assert_type(x1, Tuple[Any, ...]) +assert_type(x2, Tuple[Any, ...]) +[builtins fixtures/tuple.pyi] + +[case testAliasExplicitNoArgsCallable] +from typing import Any, Callable, assert_type +from typing_extensions import TypeAlias + +Implicit = Callable +Explicit: TypeAlias = Callable + +x1: Implicit[str] # E: Bad number of arguments for type alias, expected 0, given 1 +x2: Explicit[str] # E: Bad number of arguments for type alias, expected 0, given 1 +assert_type(x1, Callable[..., Any]) +assert_type(x2, Callable[..., Any]) [builtins fixtures/tuple.pyi]