fix(checker): early define fully-typed function
to handle simple recursion cases where the function has an explicit return type hint, the function must be defined before evaluating its body
This commit is contained in:
@@ -7,3 +7,8 @@ def minimum(x: int, y: int):
|
|||||||
a = 15
|
a = 15
|
||||||
b = 72
|
b = 72
|
||||||
c = minimum(a, b)
|
c = minimum(a, b)
|
||||||
|
|
||||||
|
def factorial(n: int) -> int:
|
||||||
|
if n <= 1:
|
||||||
|
return 1
|
||||||
|
return n * factorial(n - 1)
|
||||||
@@ -224,6 +224,19 @@ class Checker(
|
|||||||
for arg in pos_args + args + kw_args:
|
for arg in pos_args + args + kw_args:
|
||||||
env.define(arg.name, arg.type)
|
env.define(arg.name, arg.type)
|
||||||
|
|
||||||
|
returns_hint: Optional[Type] = None
|
||||||
|
if stmt.returns is not None:
|
||||||
|
returns_hint = stmt.returns.accept(self)
|
||||||
|
# Early define to handle simple fully-typed recursion
|
||||||
|
inside_function: Function = Function(
|
||||||
|
name=stmt.name,
|
||||||
|
pos_args=pos_args,
|
||||||
|
args=args,
|
||||||
|
kw_args=kw_args,
|
||||||
|
returns=returns_hint,
|
||||||
|
)
|
||||||
|
self.env.define(stmt.name, inside_function)
|
||||||
|
|
||||||
returned: bool = self.evaluate_block(stmt.body, env)
|
returned: bool = self.evaluate_block(stmt.body, env)
|
||||||
inferred_return: Type = UnknownType()
|
inferred_return: Type = UnknownType()
|
||||||
if not returned:
|
if not returned:
|
||||||
@@ -236,9 +249,11 @@ class Checker(
|
|||||||
stmt.location,
|
stmt.location,
|
||||||
f"Mixed return types: {env.return_types}",
|
f"Mixed return types: {env.return_types}",
|
||||||
)
|
)
|
||||||
|
|
||||||
returns: Type = UnknownType()
|
returns: Type = UnknownType()
|
||||||
if stmt.returns is not None:
|
if returns_hint is not None:
|
||||||
returns = stmt.returns.accept(self)
|
assert stmt.returns is not None
|
||||||
|
returns = returns_hint
|
||||||
if returns != inferred_return:
|
if returns != inferred_return:
|
||||||
self.error(
|
self.error(
|
||||||
stmt.returns.location,
|
stmt.returns.location,
|
||||||
|
|||||||
Reference in New Issue
Block a user