# What does non-isolated mean in SE-0306?

**URL:** <https://forums.swift.org/t/what-does-non-isolated-mean-in-se-0306/83191>\
**Category:** Using Swift\
**Tags:** actors\
**Created:** [November 13, 2025, 1:59pm UTC](https://forums.swift.org/t/what-does-non-isolated-mean-in-se-0306/83191 "2025-11-13T13:59:38Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![asaadjaber](https://avatars.discourse-cdn.com/v4/letter/a/85f322/32.png) [@asaadjaber](https://forums.swift.org/u/asaadjaber)\
**Post date:** [November 13, 2025, 1:59pm UTC](https://forums.swift.org/t/what-does-non-isolated-mean-in-se-0306/83191/1 "2025-11-13T13:59:38Z")

</div>

I was reading proposal [SE-0306 Actors](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0306-actors.md), and I came across the term “non-isolated”, which is specifically used in:

> _Section about Closures:_
> 
> Actors prevent this data race by specifying that a `@Sendable` closure … is always non-isolated.

What does the term _non-isolated_ mean?

---

<div class="post-metadata">

**Author:** ![Gero](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/gero/32/23571_2.png) [@Gero](https://forums.swift.org/u/Gero)\
**Post date:** [November 13, 2025, 3:10pm UTC](https://forums.swift.org/t/what-does-non-isolated-mean-in-se-0306/83191/2 "2025-11-13T15:10:27Z")

</div>

First, please keep in mind that this proposal was written before we had ´sending´ and isolated parameters (I think), so it doesn't talk about closures that use these features. Basically, as I understand this section, it explains the difference of "regular old closures" and the (back then) new ´@Sendable´ closures.

It explains how isolation is inferred for them. Normally, any "regular old closure" is (at compile time) isolated to the same context that it is defined in.  
So if you're in a function defined in an actor, the closure is _also_ defined in an actor.

However, `Task.detached´ takes a ´@Sendable` annotated closure, so the closure defined in the (actor isolated) ´endOfMonth´ function in the example of that section is not a "regular old closure". The proposal then explains _why_ in this case, the isolation is _not_ kept. Simply put, it doesn't make sense, as `@Sendable` _by definition_ means it will be potentially called in _another_ isolation domain. This means it _cannot_ be isolated to the actor and the only logical alternative is to implicitly assume it's non-isolated (i.e. not isolated to _any_ context).

The example below the section then gives an example for a "regular old closure", one that is defined in the function and then passed to ´forEach´.

For what it's worth, this of course also applies to functions defined on non-actor types that are individually isolated to an actor (e.g. to ´@MainActor´).

---

<div class="post-metadata">

**Author:** ![asaadjaber](https://avatars.discourse-cdn.com/v4/letter/a/85f322/32.png) [@asaadjaber](https://forums.swift.org/u/asaadjaber)\
**Post date:** [November 13, 2025, 4:14pm UTC](https://forums.swift.org/t/what-does-non-isolated-mean-in-se-0306/83191/3 "2025-11-13T16:14:41Z")

</div>

Thanks for your clear answer. For non-Sendable closures (i.e. regular old closures), what does “isolated to the same context” mean? The way I understand _isolation_ (actor isolation in particular) is that it is unsafe to reference a property declared inside the actor from another actor unless I use an asynchronous method to do so. On the other hand, it is safe to read or mutate a property within the same actor. If this is correct, therefore, does _non-isolated_ mean that these rules don’t apply in a way?

---

<div class="post-metadata">

**Author:** ![Gero](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/gero/32/23571_2.png) [@Gero](https://forums.swift.org/u/Gero)\
**Post date:** [November 13, 2025, 4:46pm UTC](https://forums.swift.org/t/what-does-non-isolated-mean-in-se-0306/83191/4 "2025-11-13T16:46:01Z")

</div>

If I understand you correctly, those are basically two questions, so first:

1. What do I mean with "isolated to the same context"? What's "context" here?  
"Context" in a way means "the surrounding code" or "the function/scope the closure is defined in". A function you define on an actor is, naturally, in the isolation domain that _is_ the actor. So if you then, in the implementation of that function, define a "regular old closure", it has the _same_ isolation, i.e. also the actor.

It may help a little to think of as "non-isolated" to be "yet another isolation **domain**". it's the isolation domain of "not being isolated to anything specific" or "free to be used from any _other_ isolation domain". So if I say that a closure is "isolated to the same context [as something else]", I just mean "whatever isolation domain this context belongs to, the closure has the same thing".  
Also note that this does indeed happen at compile time, so wherever you write the actual source for a closure, just check which isolation the code before/around it has and you know what the closure is isolated to (which may, again, also be non-isolated).

1. " does _non-isolated_ mean that these rules don’t apply in a way?"  
Well, when we're speaking of closure definition in actor definitions, yes. The reason why any `@Sendable` closure you define in an actor (like in the proposal's example with `Task.detached`) is indeed interpreted differently (i.e. it does _not_ have the same isolation as its surrounding context, i.e. the actor) is simply that it doesn't make sense to treat it the same as a non-`@Sendable` closure. The only reason why functions like `Task.detached` require a `@Sendable` closure in the first place is that they want to run the closure in a _different_ isolation that the context where the closure is defined. As the example shows, this means that when you're _inside_ the closure and want to access actor state, you have to await it.

Basically the entire section of the proposal explains that "Hey, look, this is how you can isolate state and run code in a concurrent world. But careful, when you somehow explicitly leave your own isolated island, you're obviously no longer on your own island."\[1\]  
Before we had structured concurrency in the language syntax, _everything_ basically always had the same isolation as the surrounding code: non whatsoever (syntax wise). You could always (synchronously) refer to stuff in a closure that was actually defined outside of it. However, when the closure ran in a different thread (let's say you pass the closure to `DispatchQueue.main.async`, this was actually an invisible problem:

```swift
class HurtMe {
    var someValue: String?

    func pain() {
        DispatchQueue.main.async {
            // imagine something complicated here, etc.
            self.someValue = "..."
        }
    }

```

The compiler doesn't somehow "judge" the closure I define and send to `async`. There was no way to express this and it doesn't care that I could also modify `someValue` while the queue is running the closure. With structured concurrency, _everything_ is somehow marked during compile time about "where" it will run. Either implicitly or explicitly.  
And in the case of `@Sendable` closures defined in an actor-isolated context (i.e. any "code block" or scope) the new syntax's meaning is that it is associated to the non-isolated "where", unlike non-`@Sendable` closures\[2\]

* * *

1. my apologies to the original authors for summarizing their great work in this jokingly unhelpful manner 

2. btw, by now there's even more to consider here, as isolated parameters or `sending` offer additional semantics, but that's beside too much for this post now, I think. 😃

---

<div class="post-metadata">

**Author:** ![asaadjaber](https://avatars.discourse-cdn.com/v4/letter/a/85f322/32.png) [@asaadjaber](https://forums.swift.org/u/asaadjaber)\
**Post date:** [November 13, 2025, 5:54pm UTC](https://forums.swift.org/t/what-does-non-isolated-mean-in-se-0306/83191/5 "2025-11-13T17:54:34Z")

</div>

Thanks for the detailed answer! (And your paraphrasing of the authors’ text helps elucidate it better 😃)
