I was thinking of the rules for isolation as laid out here: <https://github.com/nim-lang/RFCs/issues/244>. According to that `f(...)` is isolated if it can't have side effects and the return type can't alias the input types. In my example I return a `Tree` type which can only alias `Branch` types, and I pass in a `Test` type. So according to those rules I should be good, but apparently I'm not, and I'm not sure why, partially because it doesn't tell me which of the rules of isolation that I break.
The scenarios where I want to use `isolate` are fairly simple. One of them is even mentioned in the RFC itself. Essentially I want to avoid using expensive copying between threads, and I want to avoid using atomic refs when I'm not passing stuff between threads. Atomic refs are fine if you want threads to be able to access the same memory, but they don't really do all that much for moving data from one thread to another (of course it would help solve the problem, but now you're paying for atomic refs everywhere and only ever using them once in a while). Consider the two following use-cases: Work balancer: I want to have one thread read data from a file, then create "work objects" and pass them to a pool of worker threads, these threads then pass "result objects" back to a final thread which computes the end result. This is maybe the simplest of scenarios, and similar to the one from the RFC (where a string is turned into a `JsonNode` to be passed over a channel). Basically the data is always transformed from one thing to another and it should be easier to prove that X can't alias Y and that isolation is valid. I feel like the current situation is almost there, and in fact if the code I shared above had worked I believe it would already be here. Computation pipeline: This is the more complex scenario. Basically passing an object along a chain of worker threads which perform some computation. In this case one object would only be in use by one thread at a time, with each thread moving it to another thread over a channel. This would require a more complex check as a thread could theoretically keep an alias to this object, or to anything that it adds a reference to inside the object. I'm not sure if there is any way to do this apart from performing the kind of check Zevv was talking about, but it would be great if we could have some way of doing that properly. This would require quite a bit of work to get right, but it would allow pretty much any usecase involving channels and moving memory around. All in all I'd say that having some more (preferably compile-time) guarantees that memory is cleanly moved between threads would really allow a lot of neat multithreading systems to be built which in turn would allow Nim with its amazing macros system to really have some ergonomic multithreading. If we just got better primitives for moving memory around I am sure we will see some really cool stuff in this space which would really elevate the language.
