Open patternspandemic opened 6 years ago
A variation on this, admittedly no very useful, but nonetheless results in an assertion:
I thought I could perhaps reference the literal under construction within itself by capturing the variable o
to which it's being assigned. Of course o
had to be made tag
so that it's sendable to the literal.
// ...
let o: Initable tag = object is Initable
let _state: StateHelper iso =
recover iso StateHelper("hello", o) end
be _init() =>
// Do stuff relying on _state
env.out.print(_state.s)
end
// ...
results in :
src/libponyc/codegen/genreference.c:286: gen_localptr: Assertion `value != NULL` failed.
Backtrace:
This is an optimised version of ponyc: the backtrace may be imprecise or incorrect.
Use a debug version to get more meaningful information.
ponyc(ponyint_assert_fail+0x90) [0x731ff0]
ponyc(gen_localload+0xc9) [0x6f5379]
ponyc(gen_expr+0x173) [0x71e8e3]
ponyc(gen_seq+0x2b) [0x7300db]
ponyc(gen_expr+0x203) [0x71e973]
ponyc(gen_call+0x256) [0x71cbf6]
ponyc(gen_expr+0x1eb) [0x71e95b]
ponyc(gen_seq+0x2b) [0x7300db]
ponyc(gen_expr+0x203) [0x71e973]
ponyc(gen_recover+0x2f) [0x7314ef]
ponyc(gen_expr+0x34b) [0x71eabb]
ponyc(gen_seq+0x2b) [0x7300db]
ponyc(gen_expr+0x203) [0x71e973]
ponyc(gen_call+0x256) [0x71cbf6]
ponyc(gen_expr+0x1eb) [0x71e95b]
ponyc(gen_assign+0x55) [0x724d75]
ponyc(gen_expr+0xcb) [0x71e83b]
ponyc(gen_seq+0x2b) [0x7300db]
ponyc(gen_expr+0x203) [0x71e973]
ponyc(genfun_method_bodies+0xac1) [0x726ff1]
ponyc(gentypes+0xd1b) [0x7198eb]
ponyc(genexe+0x16b) [0x72025b]
ponyc(codegen+0xcc) [0x6e7b4c]
ponyc(main+0x1cd) [0x61604d]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7fb8c5b9a830]
ponyc(_start+0x29) [0x675cc9]
Aborted (core dumped)
We discussed on the sync call. The summary of my realization is that because of how lamba/object literal sugaring works (in the expr
pass) by moving the content of the lambda/object literal to a new anonymous type, and running the refer
or expr
as "catch up" passes later, and because of how the refer
pass works by only keeping track of the current/latest definition state of those variables, the result is that when you refer to a variable inside a lambda or object literal, you get the answer about its status as being whatever it was at the end of the function, instead of at the place in the function where it was actually supposed to have been captured.
Here's an example that demonstrates this:
actor Main
new create(env: Env) =>
let x: String = {(): String =>
x + "foo"
}()
consume x
Error:
main.pony:4:7: can't use a consumed local or field in an expression
x + "foo"
^
I'm not sure how we would address this facet of the issue, to be honest. It seems that either the refer pass or the way we do lambdas/object literals might need re-architecting.
Here's a minimal example:
interface Foo
fun test(): Foo tag
actor Main
new create(env: Env) =>
let o: Foo tag =
object is Foo
fun test(): Foo tag =>
o
end
Surprisingly, if we remove the Foo tag
type annotation, then the compiler will catch that o
is not used:
Error:
/.../dev/ponyc/examples/crash/main.pony:42:11: can't find declaration of 'o'
o
^
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT * frame #0: 0x00007fff726e42c2 libsystem_kernel.dylib`__pthread_kill + 10 frame #1: 0x00007fff7279fbf1 libsystem_pthread.dylib`pthread_kill + 284 frame #2: 0x00007fff7264e6a6 libsystem_c.dylib`abort + 127 frame #3: 0x0000000100114e0d ponyc`ponyint_assert_fail(expr="value != NULL", file="/Users/ryan/dev/ponyc/src/libponyc/codegen/genreference.c", line=283, func="gen_localptr") at ponyassert.c:65:3 frame #4: 0x0000000100064f3a ponyc`gen_localptr(c=0x00007ffeefbfefb8, ast=0x000000010b569240) at genreference.c:283:3 frame #5: 0x0000000100064f6d ponyc`gen_localload(c=0x00007ffeefbfefb8, ast=0x000000010b569240) at genreference.c:290:28 frame #6: 0x000000010004b7dd ponyc`gen_expr(c=0x00007ffeefbfefb8, ast=0x000000010b569240) at genexpr.c:56:13 frame #7: 0x0000000100045864 ponyc`gen_seq(c=0x00007ffeefbfefb8, ast=0x000000010b5691c0) at gencontrol.c:22:13 frame #8: 0x000000010004b759 ponyc`gen_expr(c=0x00007ffeefbfefb8, ast=0x000000010b5691c0) at genexpr.c:26:13 frame #9: 0x0000000100041981 ponyc`gen_call(c=0x00007ffeefbfefb8, ast=0x000000010b56bbc0) at gencall.c:776:26 frame #10: 0x000000010004b885 ponyc`gen_expr(c=0x00007ffeefbfefb8, ast=0x000000010b56bbc0) at genexpr.c:92:13 frame #11: 0x00000001000594c5 ponyc`gen_assign(c=0x00007ffeefbfefb8, ast=0x000000010bee5640) at genoperator.c:919:26 frame #12: 0x000000010004ba0c ponyc`gen_expr(c=0x00007ffeefbfefb8, ast=0x000000010bee5640) at genexpr.c:148:13 frame #13: 0x0000000100045864 ponyc`gen_seq(c=0x00007ffeefbfefb8, ast=0x000000010bee44c0) at gencontrol.c:22:13 frame #14: 0x000000010004b759 ponyc`gen_expr(c=0x00007ffeefbfefb8, ast=0x000000010bee44c0) at genexpr.c:26:13 frame #15: 0x000000010004e577 ponyc`genfun_newbe(c=0x00007ffeefbfefb8, t=0x000000010c213c00, m=0x000000010c05e900) at genfun.c:589:24 frame #16: 0x000000010004d70f ponyc`genfun_method(c=0x00007ffeefbfefb8, t=0x000000010c213c00, n=0x000000010c05e880, m=0x000000010c05e900) at genfun.c:784:15 frame #17: 0x000000010004d542 ponyc`genfun_method_bodies(c=0x00007ffeefbfefb8, t=0x000000010c213c00) at genfun.c:946:11 frame #18: 0x000000010006a096 ponyc`gentypes(c=0x00007ffeefbfefb8) at gentype.c:861:9 frame #19: 0x000000010004b07c ponyc`genexe(c=0x00007ffeefbfefb8, program=0x000000010c7bfd00) at genexe.c:561:7 frame #20: 0x000000010003ca7a ponyc`codegen(program=0x000000010c7bfd00, opt=0x00007ffeefbff488) at codegen.c:923:10 frame #21: 0x00000001000b78b3 ponyc`generate_passes(program=0x000000010c7bfd00, options=0x00007ffeefbff488) at pass.c:360:10 frame #22: 0x0000000100001fa1 ponyc`compile_package(path="examples/crash/", opt=0x00007ffeefbff488, print_program_ast=false, print_package_ast=false) at main.c:67:13 frame #23: 0x0000000100001e3f ponyc`main(argc=2, argv=0x00007ffeefbff598) at main.c:112:15 frame #24: 0x00007fff725a93d5 libdyld.dylib`start + 1 frame #25: 0x00007fff725a93d5 libdyld.dylib`start + 1
There is no equivelant way to refer to the literal under construction, like how
this
can be used in class/actor constructors.pony version:
source (run in playground)