ponyc
ponyc copied to clipboard
Compiler error on trying to assign a value to a cast object's property
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
).
I should also note that one can currently work around the bug using a match
expression.
Given the assert location, this regression was probably introduced in #3304
My old build from january, 2020 was still affected
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 consume
d here, afaik.
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 toconsume
the variable, so it would be possible to place theconsume
expression only if it was needed. -
Similarly to what we did with
with
, we could stop treatingas
as sugar for amatch
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 tomatch
blocks, so they could get out of sync in the future.