Skip to content

Commit

Permalink
Allow recursive aliases at class scope (#13754)
Browse files Browse the repository at this point in the history
As `mypy_primer` in #13516 shows,
some people actually use this, and I don't see any good reason to not
allow this. (Note: I tried to enable the same for recursive NamedTuples
and TypedDicts, but this affects how nested classes work in general, so
people will need to use qualified names there).
  • Loading branch information
ilevkivskyi authored Sep 28, 2022
1 parent 9783b46 commit 2562140
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 2 deletions.
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]

0 comments on commit 2562140

Please sign in to comment.