# Cycles ## Function signature Deferred annotations can result in cycles in resolving a function signature: ```py from __future__ import annotations # error: [invalid-type-form] def f(x: f): pass reveal_type(f) # revealed: def f(x: Unknown) -> Unknown ``` ## Unpacking See: ```py class Point: def __init__(self, x: int = 0, y: int = 0) -> None: self.x = x self.y = y def replace_with(self, other: "Point") -> None: self.x, self.y = other.x, other.y p = Point() reveal_type(p.x) # revealed: Unknown | int reveal_type(p.y) # revealed: Unknown | int ``` ## Parameter default values This is a regression test for . When a parameter has a default value that references the callable itself, we currently prevent infinite recursion by simply falling back to `Unknown` for the type of the default value, which does not have any practical impact except for the displayed type. We could also consider inferring `Divergent` when we encounter too many layers of nesting (instead of just one), but that would require a type traversal which could have performance implications. So for now, we mainly make sure not to panic or stack overflow for these seeminly rare cases. ### Functions ```py class C: def f(self: "C"): def inner_a(positional=self.a): return self.a = inner_a # revealed: def inner_a(positional=Unknown | (def inner_a(positional=Unknown) -> Unknown)) -> Unknown reveal_type(inner_a) def inner_b(*, kw_only=self.b): return self.b = inner_b # revealed: def inner_b(*, kw_only=Unknown | (def inner_b(*, kw_only=Unknown) -> Unknown)) -> Unknown reveal_type(inner_b) def inner_c(positional_only=self.c, /): return self.c = inner_c # revealed: def inner_c(positional_only=Unknown | (def inner_c(positional_only=Unknown, /) -> Unknown), /) -> Unknown reveal_type(inner_c) def inner_d(*, kw_only=self.d): return self.d = inner_d # revealed: def inner_d(*, kw_only=Unknown | (def inner_d(*, kw_only=Unknown) -> Unknown)) -> Unknown reveal_type(inner_d) ``` We do, however, still check assignability of the default value to the parameter type: ```py class D: def f(self: "D"): # error: [invalid-parameter-default] "Default value of type `Unknown | (def inner_a(a: int = Unknown | (def inner_a(a: int = Unknown) -> Unknown)) -> Unknown)` is not assignable to annotated parameter type `int`" def inner_a(a: int = self.a): ... self.a = inner_a ``` ### Lambdas ```py class C: def f(self: "C"): self.a = lambda positional=self.a: positional self.b = lambda *, kw_only=self.b: kw_only self.c = lambda positional_only=self.c, /: positional_only self.d = lambda *, kw_only=self.d: kw_only # revealed: (positional=Unknown | ((positional=Unknown) -> Unknown)) -> Unknown reveal_type(self.a) # revealed: (*, kw_only=Unknown | ((*, kw_only=Unknown) -> Unknown)) -> Unknown reveal_type(self.b) # revealed: (positional_only=Unknown | ((positional_only=Unknown, /) -> Unknown), /) -> Unknown reveal_type(self.c) # revealed: (*, kw_only=Unknown | ((*, kw_only=Unknown) -> Unknown)) -> Unknown reveal_type(self.d) ```