From f989414d9db8c94268e593200ab94b4aec2cc3d3 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 6 Jun 2024 10:34:06 +0100 Subject: [PATCH] [PEP 695] Don't crash when redefining something as a type alias (#17335) Generate an error instead. Work on #15238. --- mypy/semanal.py | 9 +++++++- test-data/unit/check-python312.test | 36 +++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 8505b3a9ccac..8592a6f05e1f 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -5323,6 +5323,14 @@ def visit_type_alias_stmt(self, s: TypeAliasStmt) -> None: all_type_params_names = [p.name for p in s.type_args] try: + existing = self.current_symbol_table().get(s.name.name) + if existing and not ( + isinstance(existing.node, TypeAlias) + or (isinstance(existing.node, PlaceholderNode) and existing.node.line == s.line) + ): + self.already_defined(s.name.name, s, existing, "Name") + return + tag = self.track_incomplete_refs() res, alias_tvars, depends_on, qualified_tvars, empty_tuple_index = self.analyze_alias( s.name.name, @@ -5378,7 +5386,6 @@ def visit_type_alias_stmt(self, s: TypeAliasStmt) -> None: python_3_12_type_alias=True, ) - existing = self.current_symbol_table().get(s.name.name) if ( existing and isinstance(existing.node, (PlaceholderNode, TypeAlias)) diff --git a/test-data/unit/check-python312.test b/test-data/unit/check-python312.test index 2b67f56e679c..52f77243fd0a 100644 --- a/test-data/unit/check-python312.test +++ b/test-data/unit/check-python312.test @@ -1453,3 +1453,39 @@ class E[T]: reveal_type(E[str]().a) # N: Revealed type is "builtins.list[Any]" [builtins fixtures/tuple.pyi] [typing fixtures/typing-full.pyi] + +[case testPEP695RedefineAsTypeAlias1] +# flags: --enable-incomplete-feature=NewGenericSyntax +class C: pass +type C = int # E: Name "C" already defined on line 2 + +A = 0 +type A = str # E: Name "A" already defined on line 5 +reveal_type(A) # N: Revealed type is "builtins.int" + +[case testPEP695RedefineAsTypeAlias2] +# flags: --enable-incomplete-feature=NewGenericSyntax +from m import D +type D = int # E: Name "D" already defined (possibly by an import) +a: D +reveal_type(a) # N: Revealed type is "m.D" +[file m.py] +class D: pass + +[case testPEP695RedefineAsTypeAlias3] +# flags: --enable-incomplete-feature=NewGenericSyntax +D = list["Forward"] +type D = int # E: Name "D" already defined on line 2 +Forward = str +x: D +reveal_type(x) # N: Revealed type is "builtins.list[builtins.str]" + +[case testPEP695MultiDefinitionsForTypeAlias] +# flags: --enable-incomplete-feature=NewGenericSyntax +if int(): + type A[T] = list[T] +else: + type A[T] = str # E: Name "A" already defined on line 3 +x: T # E: Name "T" is not defined +a: A[int] +reveal_type(a) # N: Revealed type is "builtins.list[builtins.int]"