From b289aa20809b2391a04eb26f857c5d5ec4cef578 Mon Sep 17 00:00:00 2001 From: Paul Lietar Date: Mon, 12 Jun 2017 05:05:56 +0100 Subject: [PATCH] Keep the data of TK_TYPEPARAM pointing to the original definition. iftype is implemented by shadowing the type parameter with a new definition and a new constraint. Storing the pointer of the original definition allows us to compare identity of type parameters easily. This replaces the more complicated subtyping-based check to determine whether a type parameter should be reified. --- src/libponyc/pass/scope.c | 3 ++- src/libponyc/type/reify.c | 28 +++++++++++----------------- test/libponyc/iftype.cc | 21 +++++++++++++++++++++ 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/libponyc/pass/scope.c b/src/libponyc/pass/scope.c index 83a76e0100..1d7289f4e2 100644 --- a/src/libponyc/pass/scope.c +++ b/src/libponyc/pass/scope.c @@ -193,7 +193,8 @@ static ast_t* make_iftype_typeparam(pass_opt_t* opt, ast_t* subtype, TREE(new_constraint) NONE)); - ast_setdata(typeparam, typeparam); + // keep data pointing to the original def + ast_setdata(typeparam, ast_data(def)); return typeparam; } diff --git a/src/libponyc/type/reify.c b/src/libponyc/type/reify.c index 58ee4433f5..9e96dbe22e 100644 --- a/src/libponyc/type/reify.c +++ b/src/libponyc/type/reify.c @@ -6,31 +6,25 @@ #include "../ast/token.h" #include "ponyassert.h" -static void reify_typeparamref(pass_opt_t* opt, ast_t** astp, ast_t* typeparam, ast_t* typearg) +static void reify_typeparamref(ast_t** astp, ast_t* typeparam, ast_t* typearg) { ast_t* ast = *astp; pony_assert(ast_id(ast) == TK_TYPEPARAMREF); pony_assert(ast_id(typeparam) == TK_TYPEPARAM); ast_t* ref_def = (ast_t*)ast_data(ast); - ast_t* param_def = (ast_t*)ast_data(typeparam); + + // We can't compare ref_def and typeparam, as they could be a copy or + // a iftype shadowing. However, their data points back to the original + // typeparam definition, which can be compared. + ref_def = (ast_t*)ast_data(ref_def); + typeparam = (ast_t*)ast_data(typeparam); pony_assert(ref_def != NULL); - pony_assert(param_def != NULL); - AST_GET_CHILDREN(ref_def, ref_name, ref_constraint); - AST_GET_CHILDREN(param_def, param_name, param_constraint); + pony_assert(typeparam != NULL); - if(ref_def != param_def) - { - if(ast_name(ref_name) == ast_name(param_name)) - { - if((ast_id(param_constraint) != TK_TYPEPARAMREF) && - !is_subtype(ref_constraint, param_constraint, NULL, opt)) - return; - } else { - return; - } - } + if(ref_def != typeparam) + return; // Keep ephemerality. switch(ast_id(ast_childidx(ast, 2))) @@ -117,7 +111,7 @@ static void reify_one(pass_opt_t* opt, ast_t** astp, ast_t* typeparam, ast_t* ty switch(ast_id(ast)) { case TK_TYPEPARAMREF: - reify_typeparamref(opt, astp, typeparam, typearg); + reify_typeparamref(astp, typeparam, typearg); break; case TK_ARROW: diff --git a/test/libponyc/iftype.cc b/test/libponyc/iftype.cc index e4f25af74d..a8311133fc 100644 --- a/test/libponyc/iftype.cc +++ b/test/libponyc/iftype.cc @@ -273,3 +273,24 @@ TEST_F(IftypeTest, UnconstrainedTypeparam) TEST_COMPILE(src); } + +TEST_F(IftypeTest, NestedCond) +{ + const char* src = + "trait T\n" + "class C is T\n" + " fun tag c() => None\n" + + "actor Main\n" + " new create(env: Env) =>\n" + " foo[C](C)\n" + + " fun foo[A](x: A) =>\n" + " iftype A <: T then\n" + " iftype A <: C then\n" + " x.c()\n" + " end\n" + " end"; + + TEST_COMPILE(src); +}