# \`Sendable\` values in non-\`Sendable\` containers

**URL:** <https://forums.swift.org/t/sendable-values-in-non-sendable-containers/75807>\
**Category:** Using Swift\
**Tags:** concurrency\
**Created:** [November 4, 2024, 11:33am UTC](https://forums.swift.org/t/sendable-values-in-non-sendable-containers/75807 "2024-11-04T11:33:32Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![sjavora](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/sjavora/32/9323_2.png) [@sjavora](https://forums.swift.org/u/sjavora)\
**Post date:** [November 4, 2024, 11:33am UTC](https://forums.swift.org/t/sendable-values-in-non-sendable-containers/75807/1 "2024-11-04T11:33:32Z")

</div>

Disclaimer: this code is simplified for demonstration purposes.

Suppose I have a value only available asynchronously:

```swift
struct Source: Sendable {
    var someAsyncValue: Int {
        get async {
            42
        }
    }
}

```

That value is a part of a dependency:

```swift
class Dependency {
    let source = Source()

    var someAsyncValue: Int {
        get async {
            await source.someAsyncValue
        }
    }
}

```

And this is then used in some code:

```swift
struct Container {

    let dependency = Dependency()

    @MainActor func worksFine() async { 
        _ = await self.dependency.source.someAsyncValue // ✅
    }
}

```

This is a repeated pattern, so I introduce a "shortcut" into `Dependency`, so I don't have to write `.source` every time:

```swift
extension Dependency {
    var someAsyncValue: Int {
        get async {
            await source.someAsyncValue
        }
    }
}

```

Predictably, this doesn't work, because `dependency` is neither `Sendable`, nor `@MainActor`.

```swift
struct Container {

    let dependency = Dependency()

    @MainActor func doesNotWork() async {
        _ = await self.dependency.someAsyncValue // ❌ Non-sendable type 'Dependency' exiting main actor-isolated context in call to nonisolated property 'someAsyncValue' cannot cross actor boundary
    }
}

```

This `Dependency` could easily be made `Sendable`, but the real one has mutable state, so that's out. It could be made into an `actor` or isolated to `@MainActor`, but the real version also conforms to protocols, which is another can of worms.

The method on `Container` is `@MainActor` because some other non-`Sendable` classes are later involved, calling more `async` methods. Removing `@MainActor` would just shift the problem elsewhere.

I could mark `someAsyncValue` with `@MainActor`, but it's a simple value... there is really no reason it should have to be isolated.

I only want to be able to avoid having to write `.source`, not rearchitect the whole app 😅. My question is whether I've overlooked something (please) or whether I'll just have to bite the bullet here.

---

<div class="post-metadata">

**Author:** ![ole](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ole/32/18720_2.png) [@ole](https://forums.swift.org/u/ole)\
**Post date:** [November 30, 2024, 7:37pm UTC](https://forums.swift.org/t/sendable-values-in-non-sendable-containers/75807/2 "2024-11-30T19:37:53Z")

</div>

It works (I think) if you turn your `var someAsyncValue` into a function and pass the caller's isolation along:

```swift
class Dependency {
    let source = Source()

    func someAsyncValue(isolation: isolated (any Actor)? = #isolation) async -> Int {
        await source.someAsyncValue
    }
}

struct Container {
    let dependency = Dependency()

    @MainActor func worksFineToo() async {
        _ = await self.dependency.someAsyncValue() // ✅
    }
}

```

This compiles in Swift 6 mode and seems to work fine in my very limited testing.

So you have to add a pair of parentheses at the call site and the implementation of the convenience function requires more boilerplate. You have to decide whether this is good enough for you.

Passing a dynamic isolation to computed properties [is mentioned as a future direction in SE-0420](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0420-inheritance-of-actor-isolation.md#syntax-sugar-for-inheriting-actor-isolation). And if [[Pitch] Inherit isolation by default for async functions](https://forums.swift.org/t/pitch-inherit-isolation-by-default-for-async-functions/74862) gets implemented, your code should work as-is, I think.
