Skip to content

Commit

Permalink
Don't assume that method bodies produce the correct tuple type already
Browse files Browse the repository at this point in the history
It's possible that the method body returns a subtype of the return type.
For example, a return value with type `((U32, U32) | (U32, None))` is
legal for a method with return type `(U32, (U32 | None))`, but it
requires a cast.

Fixes #2609, #2808
  • Loading branch information
Trundle committed Feb 27, 2021
1 parent dd0583d commit 338bc8a
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 10 deletions.
3 changes: 3 additions & 0 deletions .release-notes/3723.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## Fix tuple related compiler segfaults

Andreas Stührk indentified and fixed the source of two different open issues with tuple handling that caused the pony compiler to crash.
10 changes: 0 additions & 10 deletions src/libponyc/codegen/genfun.c
Original file line number Diff line number Diff line change
Expand Up @@ -468,17 +468,7 @@ static bool genfun_fun(compile_t* c, reach_type_t* t, reach_method_t* m)
LLVMTypeRef f_type = LLVMGetElementType(LLVMTypeOf(c_m->func));
LLVMTypeRef r_type = LLVMGetReturnType(f_type);

// If the result type is known to be a tuple, do the correct assignment
// cast even if the body type is not a tuple.
ast_t* body_type = deferred_reify(m->fun, ast_type(body), c->opt);

if((ast_id(result) == TK_TUPLETYPE) && (ast_id(body_type) != TK_TUPLETYPE))
{
ast_free_unattached(body_type);
body_type = r_result;
r_result = NULL;
}

LLVMValueRef ret = gen_assign_cast(c, r_type, value, body_type);

ast_free_unattached(body_type);
Expand Down
18 changes: 18 additions & 0 deletions test/libponyc/codegen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -989,3 +989,21 @@ TEST_F(CodegenTest, IfBlockEndingWithDontCareAssign)
int exit_code = 0;
ASSERT_TRUE(run_program(&exit_code));
}

TEST_F(CodegenTest, UnionValueForTupleReturnType)
{
const char* src =
"actor Main\n"
" new create(env: Env) =>\n"
" try _create_tuple()._2 as Bool end\n"

" fun _create_tuple(): (U32, (Bool | None)) =>\n"
" let x: ((U32, Bool) | (U32, None)) = (1, true)\n"
" x\n";

TEST_COMPILE(src);

int exit_code = 0;
ASSERT_TRUE(run_program(&exit_code));
ASSERT_EQ(exit_code, 0);
}

0 comments on commit 338bc8a

Please sign in to comment.