Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow go statements in certain circumstances (#150)
We don't currently allow `go` statements when compiling functions because there's no structured concurrency in Go; goroutines are executed independently (there's no hierarchy; no concept of ownership), and we are unable to suspend execution of related goroutines when another goroutine explicitly yields. The compiler only needs to compile a subset of functions in the program; those that yield, those that may be on the call stack of a coroutine that yields, or those that contain a function literal that yields or may end up on the call stack of a coroutine that yields. All other functions are allowed to use `go`. This PR relaxes the restrictions a bit so that certain functions are now allowed to use `go`. The major use case we unlock is to allow patterns like this, which seems to come up a lot: ```go func outer() { coroutine := func(...) { /* e.g. explicitly yields here */ } go func() { /* do something unrelated */ }() } ``` If the compiler determines that the `coroutine` function literal yields explicitly, or may end up on the call stack of a coroutine that yields explicitly, it needs to compile both the inner function literal and the outer function (since #135). We currently reject the `go` statement in the outer function, even though it may not interact with any coroutines. This PR relaxes the restriction; we allow `go` statements in this one instance. The goroutine could still mutate state from the outer function which is then read/mutated within the inner function literal. Given that we do not support serializing synchronization primitives at this time (e.g. channels, mutexes), the assumption is that the user isn't doing anything unsafe and that it's fine to allow the `go` statement. It prints a warning just in case.
- Loading branch information