ponyc
                                
                                
                                
                                    ponyc copied to clipboard
                            
                            
                            
                        iftype compile error at runtime
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.
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;
                                    
                                    
                                    
                                
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.
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...
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.
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.
@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
I've assigned myself to this, but anyone who wants this is welcome to take it.