Skip to content

Commit

Permalink
Downgrade iso and trn to ref when replacing this in a box method.
Browse files Browse the repository at this point in the history
  • Loading branch information
plietar committed Jan 17, 2018
1 parent 8b6bb05 commit 51981e9
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ All notable changes to the Pony compiler and standard library will be documented

### Fixed

- Fix unsoundness when replacing `this` viewpoint in method calls. ([PR #2503](https://github.com/ponylang/ponyc/pull/2503))

### Added

Expand Down
42 changes: 42 additions & 0 deletions src/libponyc/type/lookup.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,44 @@
static deferred_reification_t* lookup_base(pass_opt_t* opt, ast_t* from,
ast_t* orig, ast_t* type, const char* name, bool errors);

// If a box method is being called with an iso/trn receiver, we mustn't replace
// this-> by iso/trn as this would be unsound, but by ref. See #1887
//
// This method (recursively) replaces occurences of iso and trn in `receiver` by
// ref. If a modification was required then a copy is returned, otherwise the
// original pointer is.
static ast_t* downcast_iso_trn_receiver_to_ref(ast_t* receiver) {
switch (ast_id(receiver))
{
case TK_NOMINAL:
case TK_TYPEPARAMREF:
switch (cap_single(receiver))
{
case TK_TRN:
case TK_ISO:
return set_cap_and_ephemeral(receiver, TK_REF, TK_NONE);

default:
return receiver;
}

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

ast_t* downcasted_right = downcast_iso_trn_receiver_to_ref(right);
if(right != downcasted_right)
return viewpoint_type(left, downcasted_right);
else
return receiver;
}

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

static deferred_reification_t* lookup_nominal(pass_opt_t* opt, ast_t* from,
ast_t* orig, ast_t* type, const char* name, bool errors)
{
Expand Down Expand Up @@ -178,6 +216,10 @@ static deferred_reification_t* lookup_nominal(pass_opt_t* opt, ast_t* from,
}

ast_t* typeargs = ast_childidx(type, 2);

if(ast_id(find) == TK_FUN && ast_id(ast_child(find)) == TK_BOX)
orig = downcast_iso_trn_receiver_to_ref(orig);

return deferred_reify_new(find, typeparams, typeargs, orig);
}

Expand Down
17 changes: 17 additions & 0 deletions test/libponyc/badpony.cc
Original file line number Diff line number Diff line change
Expand Up @@ -954,3 +954,20 @@ TEST_F(BadPonyTest, ApplySugarInferredLambdaArgument)

TEST_COMPILE(src);
}

TEST_F(BadPonyTest, ThisViewpointWithIsoReceiver)
{
// From issue #1887
const char* src =
"class A\n"
"class Revealer\n"
" fun box reveal(x: this->A ref): A box => x\n"

"actor Main\n"
"new create(env: Env) =>\n"
" let revealer : Revealer iso = Revealer.create()\n"
" let opaque : A tag = A.create()\n"
" let not_opaque : A box = (consume revealer).reveal(opaque)\n";

TEST_ERRORS_1(src, "argument not a subtype of parameter");
}

0 comments on commit 51981e9

Please sign in to comment.