ponyc
                                
                                
                                
                                    ponyc copied to clipboard
                            
                            
                            
                        Runtime crash when accessing a field that was captured before it was initialized
The following program crashes in the lambda {() => _foo.n }:
class Foo
  let n: USize
  
  new create(n': USize) =>
    n = n'
class Bar
  let _foo: Foo
  let lazy: {(): USize} = {() => _foo.n }
  
  new create() =>
    _foo = Foo(123)
actor Main
  let _env: Env
  let _bar: Bar
  new create(env: Env) =>
    _env = env
    _bar = Bar
    run_me()
  
  be run_me() =>
    _env.out.print("n is " + _bar.lazy().string())
The lambda captured the pointer to _foo before it was initialized (if you initialize _foo directly and not in the constructor everything works fine).
Here's a revised program showing that it still crashes even when the assignment isn't in a field initializer:
class Foo
  let n: USize
  
  new create(n': USize) =>
    n = n'
class Bar
  let _foo: Foo
  let lazy: {(): USize}
  
  new create() =>
    lazy = {() => _foo.n }
    _foo = Foo(123)
actor Main
  let _env: Env
  let _bar: Bar
  new create(env: Env) =>
    _env = env
    _bar = Bar
    _env.out.print("Hello")
    run_me()
  
  be run_me() =>
    _env.out.print("n is " + _bar.lazy().string())
                                    
                                    
                                    
                                
This program should result in a compile-time error that says you can't access the _foo field on a Bar tag.
The captured Bar must be a tag because it hasn't been fully initialized with all fields yet.