Skip to content

Commit

Permalink
Fix compiler crash related to type parameter references
Browse files Browse the repository at this point in the history
This fixes a bug in rescoping. Rescoping happens after a method was
copied from a trait/interface to another type. It starts with a fresh
scope, visits all of the method's AST nodes and adds the visited symbols
to the method's symbol table. This includes type parameters. If a type
parameter reference is visited, the referenced type parameter is looked
up and added as data to the node.

As rescoping starts with a fresh scope, adding the type parameter to the
reference fails if the type parameter itself is not defined yet. This is
fixed by eagerly adding type parameters to the scope before visiting
type parameter references.

Fixes #3285
  • Loading branch information
Trundle authored and SeanTAllen committed Feb 28, 2021
1 parent 22df673 commit 57cc552
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .release-notes/fix-param-type-reference-crash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## Fix compiler crash related to type parameter references

Previously, if a method signature in a trait or interface referenced a type
parameter before the type parameter itself was defined, the compiler would
crash. This is now fixed.
14 changes: 13 additions & 1 deletion src/libponyc/pass/traits.c
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,6 @@ static ast_result_t rescope(ast_t** astp, pass_opt_t* options)
case TK_EMBED:
case TK_PARAM:
case TK_MATCH_CAPTURE:
case TK_TYPEPARAM:
{
pony_assert(ast_child(ast) != NULL);
ast_set(ast, ast_name(ast_child(ast)), ast, SYM_DEFINED, true);
Expand All @@ -432,6 +431,19 @@ static ast_result_t rescope(ast_t** astp, pass_opt_t* options)
break;
}

case TK_TYPEPARAMS:
{
ast_t* typeparam = ast_child(ast);
while(typeparam != NULL)
{
pony_assert(ast_child(typeparam) != NULL);
ast_set(ast, ast_name(ast_child(typeparam)), typeparam, SYM_DEFINED, true);

typeparam = ast_sibling(typeparam);
}
break;
}

case TK_TYPEPARAMREF:
{
pony_assert(ast_child(ast) != NULL);
Expand Down
12 changes: 12 additions & 0 deletions test/libponyc/traits.cc
Original file line number Diff line number Diff line change
Expand Up @@ -722,3 +722,15 @@ TEST_F(TraitsTest, TypeargInFunction2)
// Tests typearg reification in methods inherited from parameterised traits.
DO(test_compile(src, "expr"));
}


TEST_F(TraitsTest, TypeParamRefBeforeTypeParam)
{
const char* src =
"trait T\n"
" fun f[X: Y, Y: U32]() => None\n"

"class C is T";

TEST_COMPILE(src);
}

0 comments on commit 57cc552

Please sign in to comment.