ponyc
ponyc copied to clipboard
Failure during typechecking of loops that jump away
This example hits an assertion:
actor Main
fun a() =>
while true do
break
else
return
end
new create(env: Env) =>
a()
And this example reports that the print statement is unreachable.
actor Main
fun a(env: Env)? =>
env.out.print("hi")
try error else error end
new create(env: Env) =>
try a(env)? end
These only happen if the loop or try are in a separate function instead of create
This issue was separated out from #2788
This is definitely coming from an else
that has a "jump away" like error
or return
So
actor Main
fun a(env: Env)? =>
env.out.print("hi")
try error else error end
new create(env: Env) =>
try a(env)? end
is an interesting error. It isn't actually thinking that the print is unreachable. It is thinking the implicit None return at the end of the function is unreachable which is (typeref x (id None) x)
in the AST.
But when it goes to display that as the error, it points at the print line instead.
@jemc @ergl thoughts on how to address this?
For
actor Main
fun a() =>
while true do
break
else
return
end
new create(env: Env) =>
a()
The error is a typecheck erorr that isn't setting an error message.
In particular, when examining the TK_SEQ that contains our while, we execute this code in expr_seq
:
for(ast_t* p = ast_child(ast); ast_sibling(p) != NULL; p = ast_sibling(p))
{
ast_t* p_type = ast_type(p);
At some point, we get back NULL for the type which will cause this check if(is_typecheck_error(p_type))
to fail. More investigation is needed as to what is coming back with a NULL type.
This diff may fix that particular crash:
diff --git a/src/libponyc/expr/control.c b/src/libponyc/expr/control.c
index 72f3f255..b1aefdbd 100644
--- a/src/libponyc/expr/control.c
+++ b/src/libponyc/expr/control.c
@@ -27,6 +27,9 @@ bool expr_seq(pass_opt_t* opt, ast_t* ast)
// Any expression other than the last that is still literal is an error
for(ast_t* p = ast_child(ast); ast_sibling(p) != NULL; p = ast_sibling(p))
{
+ if(ast_checkflag(p, AST_FLAG_JUMPS_AWAY))
+ continue;
+
ast_t* p_type = ast_type(p);
if(is_typecheck_error(p_type))