Assign operation checks ======================= Also applies to "writeonly" ref parameters. Internal type states: * var/const * readable/writeonly * known-uninitialized/maybe-initialized/initialized * ownerless/arena-allocated/unowned/owned/ownership-returned/ownership-seeking * tracked/untracked (const + known-uninitialized/maybe-initialized are forbidden combinations) Target mutability check ----------------------- Ok if: * target is var, or * target is known-uninitialized Source read possibility check ----------------------------- Ok if: * source if initialized and readable Disappearing reference check ---------------------------- Ok if: * target is ownerless/unowned, or * target is arena-allocated (any arena), or * target is ownership-returned Appearing reference check ------------------------- Ok if: * source is ownerless, or * target-variable is tracked, or * target-variable is ownership-seeking Tracked variables ================= * Local variables From these we can determine when the variable is first assinged and when it is last read from. Variable state and exceptions ============================= "longjmp" exceptions make variable state tracking difficult. We would need to track which functions can throw/longjmp (or assume that all functions in external modules can throw/longjmp) (or use jmpbuf's that we pass around) try FatalErrorHandler jmpbuf1 { # jmpbuf1 is owned by the try-block, during its whole execution, # so ownership of it may not be transferred # - should arenas still be valid when a fatal error occurs? own ref List otherlist = .prealloc(list) for ElemType elem in list { own ref TransformedElem transformed = transform(elem, jmpbuff1) otherlist.add(list) } } catch error { # What is the status of otherlist and its elements here? # Can we solve this be restricting exceptions: # - No stack-owned variables at least # - Arenas could be OK if the arena outlives the try-catch block switch error { # open enum! case .OutOfMemory: # ... default: # ... } }