diff --git a/mypy/newsemanal/semanal.py b/mypy/newsemanal/semanal.py index eb0840be9d77..db25b6c87ee3 100644 --- a/mypy/newsemanal/semanal.py +++ b/mypy/newsemanal/semanal.py @@ -2347,7 +2347,9 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> bool: self.analyze_alias(rvalue, allow_placeholder=True) if not res: return False - if self.found_incomplete_ref(tag) or isinstance(res, PlaceholderType): + # TODO: Maybe we only need to reject top-level placeholders, similar + # to base classes. + if self.found_incomplete_ref(tag) or has_placeholder(res): # Since we have got here, we know this must be a type alias (incomplete refs # may appear in nested positions), therefore use becomes_typeinfo=True. placeholder = PlaceholderNode(self.qualified_name(lvalue.name), @@ -2381,9 +2383,6 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> bool: alias_tvars=alias_tvars, no_args=no_args) if existing: # An alias gets updated. - if self.final_iteration: - self.cannot_resolve_name(lvalue.name, 'name', s) - return True updated = False if isinstance(existing.node, TypeAlias): if existing.node.target != res: @@ -2397,7 +2396,10 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> bool: # Otherwise just replace existing placeholder with type alias. existing.node = alias_node updated = True - if updated: + if self.final_iteration: + self.cannot_resolve_name(lvalue.name, 'name', s) + return True + elif updated: self.progress = True # We need to defer so that this change can get propagated to base classes. self.defer() diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index 5096bf8e885a..27efeb8d7cd1 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -2469,10 +2469,10 @@ x: int = C()[0][0] from typing import List, Generic, TypeVar, NamedTuple T = TypeVar('T') -class C(A, B): #type: ignore +class C(A, B): # type: ignore pass class G(Generic[T]): pass -A = G[C] +A = G[C] # type: ignore class B(NamedTuple): x: int @@ -2482,7 +2482,7 @@ C(1)[0] [out] [case testSerializeRecursiveAliases1] -# flags: --no-new-semantic-analyzer +# flags: --new-semantic-analyzer from typing import Type, Callable, Union A = Union[A, int] # type: ignore @@ -2491,7 +2491,7 @@ C = Type[C] # type: ignore [out] [case testSerializeRecursiveAliases2] -# flags: --no-new-semantic-analyzer +# flags: --new-semantic-analyzer from typing import Type, Callable, Union A = Union[B, int] # type: ignore @@ -2500,7 +2500,7 @@ C = Type[A] # type: ignore [out] [case testSerializeRecursiveAliases3] -# flags: --no-new-semantic-analyzer +# flags: --new-semantic-analyzer from typing import Type, Callable, Union, NamedTuple A = Union[B, int] # type: ignore @@ -4514,15 +4514,12 @@ from lib import A B = List[A] [builtins fixtures/list.pyi] [out] -tmp/other.pyi:2: error: Module 'lib' has no attribute 'A' tmp/other.pyi:3: error: Cannot resolve name "B" (possible cyclic definition) tmp/lib.pyi:2: error: Module 'other' has no attribute 'B' [out2] -tmp/other.pyi:2: error: Module 'lib' has no attribute 'A' tmp/other.pyi:3: error: Cannot resolve name "B" (possible cyclic definition) tmp/lib.pyi:2: error: Module 'other' has no attribute 'B' -tmp/a.py:2: error: Cannot resolve name "lib.A" (possible cyclic definition) -tmp/a.py:3: note: Revealed type is 'Any' +tmp/a.py:3: note: Revealed type is 'builtins.list[Any]' [case testRecursiveNamedTupleTypedDict] # flags: --no-new-semantic-analyzer diff --git a/test-data/unit/check-newsemanal.test b/test-data/unit/check-newsemanal.test index f8755b2ab7d4..40d6670d68c0 100644 --- a/test-data/unit/check-newsemanal.test +++ b/test-data/unit/check-newsemanal.test @@ -1383,9 +1383,15 @@ x: B B = List[C] class C(B): pass -reveal_type(x) # N: Revealed type is 'builtins.list[__main__.C]' -reveal_type(x[0][0]) # N: Revealed type is '__main__.C*' +reveal_type(x) +reveal_type(x[0][0]) [builtins fixtures/list.pyi] +[out] +main:3: error: Cannot resolve name "B" (possible cyclic definition) +main:4: error: Cannot resolve name "B" (possible cyclic definition) +main:4: error: Cannot resolve name "C" (possible cyclic definition) +main:7: note: Revealed type is 'Any' +main:8: note: Revealed type is 'Any' [case testNewAnalyzerAliasToNotReadyTwoDeferralsFunction] import a @@ -1410,14 +1416,18 @@ from typing import List from b import D def f(x: B) -> List[B]: ... -B = List[C] +B = List[C] # E class C(B): pass [file b.py] from a import f class D: ... -reveal_type(f) # N: Revealed type is 'def (x: builtins.list[a.C]) -> builtins.list[builtins.list[a.C]]' +reveal_type(f) # N [builtins fixtures/list.pyi] +[out] +tmp/b.py:3: note: Revealed type is 'def (x: builtins.list[Any]) -> builtins.list[builtins.list[Any]]' +tmp/a.py:5: error: Cannot resolve name "B" (possible cyclic definition) +tmp/a.py:5: error: Cannot resolve name "C" (possible cyclic definition) [case testNewAnalyzerAliasToNotReadyMixed] from typing import List, Union @@ -1947,7 +1957,7 @@ class B(List[C]): from typing import NewType, List x: D -reveal_type(x[0][0]) # N: Revealed type is '__main__.C*' +reveal_type(x[0][0]) D = List[C] C = NewType('C', B) @@ -1955,6 +1965,13 @@ C = NewType('C', B) class B(D): pass [builtins fixtures/list.pyi] +[out] +main:3: error: Cannot resolve name "D" (possible cyclic definition) +main:4: note: Revealed type is 'Any' +main:6: error: Cannot resolve name "D" (possible cyclic definition) +main:6: error: Cannot resolve name "C" (possible cyclic definition) +main:7: error: Argument 2 to NewType(...) must be a valid type +main:7: error: Cannot resolve name "B" (possible cyclic definition) -- Copied from check-classes.test (tricky corner cases). [case testNewAnalyzerNoCrashForwardRefToBrokenDoubleNewTypeClass] @@ -1974,10 +1991,10 @@ class C: from typing import List, Generic, TypeVar, NamedTuple T = TypeVar('T') -class C(A, B): +class C(A, B): # E: Cannot resolve name "A" (possible cyclic definition) pass class G(Generic[T]): pass -A = G[C] +A = G[C] # E: Cannot resolve name "A" (possible cyclic definition) class B(NamedTuple): x: int diff --git a/test-data/unit/check-type-aliases.test b/test-data/unit/check-type-aliases.test index 1b1cb66218fd..41434cd43c64 100644 --- a/test-data/unit/check-type-aliases.test +++ b/test-data/unit/check-type-aliases.test @@ -178,30 +178,31 @@ Alias = Tuple[int, T] [out] [case testRecursiveAliasesErrors1] -# flags: --no-new-semantic-analyzer +# flags: --new-semantic-analyzer # Recursive aliases are not supported yet. from typing import Type, Callable, Union -A = Union[A, int] -B = Callable[[B], int] -C = Type[C] -[out] -main:5: error: Recursive types not fully supported yet, nested types replaced with "Any" -main:6: error: Recursive types not fully supported yet, nested types replaced with "Any" -main:7: error: Recursive types not fully supported yet, nested types replaced with "Any" +A = Union[A, int] # E: Cannot resolve name "A" (possible cyclic definition) +B = Callable[[B], int] # E: Cannot resolve name "B" (possible cyclic definition) +C = Type[C] # E: Cannot resolve name "C" (possible cyclic definition) [case testRecursiveAliasesErrors2] -# flags: --no-new-semantic-analyzer +# flags: --new-semantic-analyzer # Recursive aliases are not supported yet. from typing import Type, Callable, Union A = Union[B, int] B = Callable[[C], int] C = Type[A] +x: A +reveal_type(x) [out] -main:5: error: Recursive types not fully supported yet, nested types replaced with "Any" -main:6: error: Recursive types not fully supported yet, nested types replaced with "Any" -main:7: error: Recursive types not fully supported yet, nested types replaced with "Any" +main:5: error: Cannot resolve name "A" (possible cyclic definition) +main:5: error: Cannot resolve name "B" (possible cyclic definition) +main:6: error: Cannot resolve name "B" (possible cyclic definition) +main:6: error: Cannot resolve name "C" (possible cyclic definition) +main:7: error: Cannot resolve name "C" (possible cyclic definition) +main:9: note: Revealed type is 'Union[Any, builtins.int]' [case testDoubleForwardAlias] from typing import List @@ -223,12 +224,12 @@ reveal_type(x[0].x) # N: Revealed type is 'builtins.str' [out] [case testJSONAliasApproximation] -# flags: --no-new-semantic-analyzer +# flags: --new-semantic-analyzer # Recursive aliases are not supported yet. from typing import List, Union, Dict -x: JSON -JSON = Union[int, str, List[JSON], Dict[str, JSON]] # type: ignore -reveal_type(x) # N: Revealed type is 'Union[builtins.int, builtins.str, builtins.list[Any], builtins.dict[builtins.str, Any]]' +x: JSON # E: Cannot resolve name "JSON" (possible cyclic definition) +JSON = Union[int, str, List[JSON], Dict[str, JSON]] # E: Cannot resolve name "JSON" (possible cyclic definition) +reveal_type(x) # N: Revealed type is 'Any' if isinstance(x, list): reveal_type(x) # N: Revealed type is 'builtins.list[Any]' [builtins fixtures/isinstancelist.pyi]