Skip to content

Allow recursive aliases at class scope #13754

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
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: 4 additions & 2 deletions mypy/semanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -5086,7 +5086,9 @@ class C:
X = X # Initializer refers to outer scope

Nested classes are an exception, since we want to support
arbitrary forward references in type annotations.
arbitrary forward references in type annotations. Also, we
allow forward references to type aliases to support recursive
types.
"""
# TODO: Forward reference to name imported in class body is not
# caught.
Expand All @@ -5097,7 +5099,7 @@ class C:
node is None
or self.is_textually_before_statement(node)
or not self.is_defined_in_current_module(node.fullname)
or isinstance(node, TypeInfo)
or isinstance(node, (TypeInfo, TypeAlias))
or (isinstance(node, PlaceholderNode) and node.becomes_typeinfo)
)

Expand Down
16 changes: 16 additions & 0 deletions test-data/unit/check-recursive-types.test
Original file line number Diff line number Diff line change
Expand Up @@ -810,3 +810,19 @@ std: STD[str]
reveal_type(std) # N: Revealed type is "TypedDict('__main__.STD', {'val': builtins.str, 'other': ..., 'sval': builtins.str, 'one': TypedDict('__main__.TD', {'val': builtins.str, 'other': ...})})"
[builtins fixtures/dict.pyi]
[typing fixtures/typing-typeddict.pyi]

[case testRecursiveClassLevelAlias]
# flags: --enable-recursive-aliases
from typing import Union, Sequence

class A:
Children = Union[Sequence['Children'], 'A', None]
x: A.Children
reveal_type(x) # N: Revealed type is "Union[typing.Sequence[...], __main__.A, None]"

class B:
Foo = Sequence[Bar]
Bar = Sequence[Foo]
y: B.Foo
reveal_type(y) # N: Revealed type is "typing.Sequence[typing.Sequence[...]]"
[builtins fixtures/tuple.pyi]