ponyc icon indicating copy to clipboard operation
ponyc copied to clipboard

Failure during typechecking of loops that jump away

Open ii8 opened this issue 6 years ago • 4 comments

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

ii8 avatar Jun 15 '18 07:06 ii8

This is definitely coming from an else that has a "jump away" like error or return

SeanTAllen avatar Jan 29 '22 22:01 SeanTAllen

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?

SeanTAllen avatar Nov 16 '22 18:11 SeanTAllen

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.

SeanTAllen avatar Nov 16 '22 19:11 SeanTAllen

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))

jemc avatar Dec 06 '22 19:12 jemc