ponyc icon indicating copy to clipboard operation
ponyc copied to clipboard

iftype compile error at runtime

Open Liasain opened this issue 2 years ago • 7 comments

use "debug"

actor Main
  new create(env: Env) =>
    Debug(foo[U8]())
    Debug(foo[U16]())
    
  fun foo[A: Any val](): String =>
    iftype A <: U16 then
      Debug("U16 is a match")
      return "u16"
    else
      Debug("no match")
    end
    "default"

Prints the follow on the Playground:

no match
default
U16 is a match

Compilation failed.

On my machine it prints the first part, then segfaults. It only happens when you return from the iftype, and if something is returned later. Moving default to the else branch removes the error.

Liasain avatar Mar 17 '23 00:03 Liasain

I think this is what needs to happen:

diff --git a/src/libponyc/codegen/gencontrol.c b/src/libponyc/codegen/gencontrol.c
index d36f7813..74531c8c 100644
--- a/src/libponyc/codegen/gencontrol.c
+++ b/src/libponyc/codegen/gencontrol.c
@@ -605,6 +605,7 @@ LLVMValueRef gen_return(compile_t* c, ast_t* ast)
     codegen_scope_lifetime_end(c);
     LLVMBuildRetVoid(c->builder);
   }
+  // Make a new basic block and set it to current
 
   codegen_debugloc(c, NULL);
   return GEN_NOVALUE;

jemc avatar Mar 17 '23 18:03 jemc

I don't think the problem is in gen_return. "fixing" the issue there results in other issues.

Looking at iftype, it doesn't do the branches as branches, based on "is subtype" check, it drops an expression directly in which is just not correct. It will work if you have:

  fun foo[A: Any val](): String =>
    iftype A <: U16 then
      Debug("U16 is a match")
      return "u16"
    else
      Debug("no match")
      "default"
    end

but it won't for the example we have.

SeanTAllen avatar Mar 19 '23 03:03 SeanTAllen

It seems like it's transformed to the equivalent of

  fun foo(): String =>
    Debug("U16 is a match")
    return "u16"
    "default"

which does not compile. I'm not sure how it should be working, or even if, but in that case it should be rejected. It would be nice if you could return from iftype though...

Liasain avatar Mar 20 '23 03:03 Liasain

So @Liasain, that would be the equivalent to what it transforms to if it transformed to source, but it doesn't so it ends up with bad LLVM ir. You can return from iftype, but you can't if there is code after the iftype. That's what we need to fix.

SeanTAllen avatar Mar 21 '23 17:03 SeanTAllen

We did an excellent discussion of this during sync and came up with some ideas, I will discuss them with Joe and we can discuss again at another sync to make a final determination on how we want to fix.

SeanTAllen avatar Mar 21 '23 18:03 SeanTAllen

@jemc and I discussed this today and we have a solution that I will probably implement.

Basically, gen_iftype doesn't create a scope for iftype'd code (but earlier steps act as though it does have a scope). We intend to create a scope and make iftype operate like if except that it will have a single branch that ends up in the compiled code with an "always true" condition + the scope that one intuitively expects from iftype BLAH then ... end

SeanTAllen avatar Apr 01 '23 03:04 SeanTAllen

I've assigned myself to this, but anyone who wants this is welcome to take it.

SeanTAllen avatar Apr 01 '23 03:04 SeanTAllen