Skip to content

Commit

Permalink
Fix a crash when function-scope recursive alias appears as upper bound (
Browse files Browse the repository at this point in the history
#15159)

Fixes #15018 

The fix is quite straightforward: function-scope aliases are not
supported anyway, so we just give up early and let the error appear.
  • Loading branch information
ilevkivskyi committed May 1, 2023
1 parent 6b1fc86 commit 3097169
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 1 deletion.
8 changes: 7 additions & 1 deletion mypy/typeanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -1110,7 +1110,13 @@ def visit_type_type(self, t: TypeType) -> Type:
return TypeType.make_normalized(self.anal_type(t.item), line=t.line)

def visit_placeholder_type(self, t: PlaceholderType) -> Type:
n = None if not t.fullname else self.api.lookup_fully_qualified(t.fullname)
n = (
None
# No dot in fullname indicates we are at function scope, and recursive
# types are not supported there anyway, so we just give up.
if not t.fullname or "." not in t.fullname
else self.api.lookup_fully_qualified(t.fullname)
)
if not n or isinstance(n.node, PlaceholderNode):
self.api.defer() # Still incomplete
return t
Expand Down
26 changes: 26 additions & 0 deletions test-data/unit/check-recursive-types.test
Original file line number Diff line number Diff line change
Expand Up @@ -897,3 +897,29 @@ Example = NamedTuple("Example", [("rec", List["Example"])])
e: Example
reveal_type(e) # N: Revealed type is "Tuple[builtins.list[...], fallback=__main__.Example]"
[builtins fixtures/tuple.pyi]

[case testRecursiveBoundFunctionScopeNoCrash]
from typing import TypeVar, Union, Dict

def dummy() -> None:
A = Union[str, Dict[str, "A"]] # E: Cannot resolve name "A" (possible cyclic definition) \
# N: Recursive types are not allowed at function scope
T = TypeVar("T", bound=A)

def bar(x: T) -> T:
pass
reveal_type(bar) # N: Revealed type is "def [T <: Union[builtins.str, builtins.dict[builtins.str, Any]]] (x: T`-1) -> T`-1"
[builtins fixtures/dict.pyi]

[case testForwardBoundFunctionScopeWorks]
from typing import TypeVar, Dict

def dummy() -> None:
A = Dict[str, "B"]
B = Dict[str, str]
T = TypeVar("T", bound=A)

def bar(x: T) -> T:
pass
reveal_type(bar) # N: Revealed type is "def [T <: builtins.dict[builtins.str, builtins.dict[builtins.str, builtins.str]]] (x: T`-1) -> T`-1"
[builtins fixtures/dict.pyi]

0 comments on commit 3097169

Please sign in to comment.