ponyc icon indicating copy to clipboard operation
ponyc copied to clipboard

Compiler error on trying to assign a value to a cast object's property

Open adri326 opened this issue 4 years ago • 5 comments

Demonstration

When casting an object using the as operator and trying to assign a value to one of its properties ((object as Something).property = value), the compiler errors out with a failed assertion:

/build/ponyc/src/ponyc-0.35.1/src/libponyc/pass/refer.c:142: generate_multi_dot_name: Assertion `0` failed.

The error also appears if there are intermediary methods ((object as Something).some_method().property = value).

adri326 avatar Jul 30 '20 19:07 adri326

I should also note that one can currently work around the bug using a match expression.

adri326 avatar Jul 30 '20 19:07 adri326

Given the assert location, this regression was probably introduced in #3304

jemc avatar Jul 31 '20 05:07 jemc

My old build from january, 2020 was still affected

adri326 avatar Aug 01 '20 13:08 adri326

The linked code no longer fails with an assertion error; it now emits the following error:

can't reassign to a consumed identifier in a try expression if there is a partial call involved
      (a as Wumpus).hunger = 1
                           ^

which definitely points to #3304 as the source of this. It's not clear to me why the AST_FLAG_CNSM_REASGN is assigned here, since no field is being consumed here, afaik.

ergl avatar Oct 13 '20 20:10 ergl

The updated Pony code from OP should now be:

class Wumpus
  var hunger: USize = 0

actor Main
  new create(env: Env) =>
    let a: (Wumpus | None) = Wumpus
    try
      (a as Wumpus).hunger = 1
    end

The error message notes "can't reassign to a consumed identifier", although there's no visible consume in the code. The issue comes from the fact that as desugars to a consume: https://github.com/ponylang/ponyc/blob/deb1494a4ba423b5c46743062b00ccf5f4bf7942/src/libponyc/ast/parser.c#L1012-L1021

There are a few possibilities to go forward:

  • The desugaring takes place during the expr pass. At this point we already know if we need to consume the variable, so it would be possible to place the consume expression only if it was needed.

  • Similarly to what we did with with, we could stop treating as as sugar for a match block, and treat it as its own, separate thing that we bring all the way down to IR. One concern with this is that it would lead to duplication of the different checks that we apply to match blocks, so they could get out of sync in the future.

ergl avatar Apr 12 '22 19:04 ergl