Skip to content

Commit

Permalink
Fix iftype where the type variable appears as a type parameter. (#2007)
Browse files Browse the repository at this point in the history
Fixes #2006
  • Loading branch information
plietar authored and Benoit Vey committed Jul 3, 2017
1 parent 9c04a37 commit 61bd461
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 24 deletions.
50 changes: 26 additions & 24 deletions src/libponyc/type/typeparam.c
Original file line number Diff line number Diff line change
Expand Up @@ -552,67 +552,66 @@ void typeparam_set_cap(ast_t* typeparamref)
ast_setid(cap, tcap);
}

static ast_t* typeparamref_current(ast_t* typeparamref, ast_t* scope)
static void typeparamref_current(ast_t* typeparamref, ast_t* scope)
{
pony_assert(ast_id(typeparamref) == TK_TYPEPARAMREF);

ast_t* def = (ast_t*)ast_data(typeparamref);
ast_t* id = ast_child(typeparamref);

ast_t* current_def = ast_get(scope, ast_name(id), NULL);
ast_t* new_typeparamref = ast_dup(typeparamref);
ast_setdata(new_typeparamref, current_def);
if(def == current_def)
return new_typeparamref;

typeparam_set_cap(new_typeparamref);
return new_typeparamref;
if(def != current_def)
{
ast_setdata(typeparamref, current_def);
typeparam_set_cap(typeparamref);
}
}

static ast_t* typeparam_current_inner(ast_t* type, ast_t* scope)
static void typeparam_current_inner(ast_t* type, ast_t* scope)
{
switch(ast_id(type))
{
case TK_TYPEPARAMREF:
return typeparamref_current(type, scope);

case TK_NOMINAL:
return ast_dup(type);
{
ast_t* typeargs = ast_childidx(type, 2);
ast_t* typearg = ast_child(typeargs);

while(typearg != NULL)
{
typeparam_current_inner(typearg, scope);
typearg = ast_sibling(typearg);
}
break;
}

case TK_UNIONTYPE:
case TK_ISECTTYPE:
case TK_TUPLETYPE:
{
ast_t* new_type = ast_from(type, ast_id(type));
ast_t* child = ast_child(type);

while(child != NULL)
{
ast_t* new_child = typeparam_current_inner(child, scope);
ast_append(new_type, new_child);
typeparam_current_inner(child, scope);
child = ast_sibling(child);
}

return new_type;
break;
}

case TK_ARROW:
{
AST_GET_CHILDREN(type, left, right);

ast_t* new_type = ast_from(type, TK_ARROW);
ast_t* new_left = typeparam_current_inner(left, scope);
ast_t* new_right = typeparam_current_inner(right, scope);

ast_add(type, new_right);
ast_add(type, new_left);

return new_type;
typeparam_current_inner(left, scope);
typeparam_current_inner(right, scope);
}

default:
pony_assert(0);
return NULL;
}
}

Expand All @@ -621,5 +620,8 @@ ast_t* typeparam_current(pass_opt_t* opt, ast_t* type, ast_t* scope)
if(opt->check.frame->iftype_body == NULL)
return type;

return typeparam_current_inner(type, scope);
type = ast_dup(type);
typeparam_current_inner(type, scope);

return type;
}
18 changes: 18 additions & 0 deletions test/libponyc/iftype.cc
Original file line number Diff line number Diff line change
Expand Up @@ -345,3 +345,21 @@ TEST_F(IftypeTest, NestedCond)

TEST_COMPILE(src);
}


TEST_F(IftypeTest, ReplaceTypeargs)
{
const char* src =
"class A\n"
" fun m() => None\n"
"trait Cell[X]\n"
" fun get(): X\n"

"actor Main\n"
" fun foo[X: Any #read](cell: Cell[X]) =>\n"
" iftype X <: A #read\n"
" then cell.get().m()\n"
" end\n"
" new create(env: Env) => None";
TEST_COMPILE(src);
}

0 comments on commit 61bd461

Please sign in to comment.