# Mutex error

**URL:** <https://forums.swift.org/t/mutex-error/76653>\
**Category:** Using Swift\
**Created:** [December 15, 2024, 2:05am UTC](https://forums.swift.org/t/mutex-error/76653 "2024-12-15T02:05:47Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![carlhung](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/carlhung/32/4446_2.png) [@carlhung](https://forums.swift.org/u/carlhung)\
**Post date:** [December 15, 2024, 2:05am UTC](https://forums.swift.org/t/mutex-error/76653/1 "2024-12-15T02:05:47Z")

</div>

I have the code below:

```swift
import Synchronization

final class BoxValue {
    let value = 0
}

final class Model: Sendable {
    var value: BoxValue {
        get {
            _value.withLock(\.self)
        }
        set {
            _value.withLock {
                $0 = newValue
            }
            |- error: 'inout sending' parameter '$0' cannot be task-isolated at end of function
            `- note: task-isolated '$0' risks causing races in between task-isolated uses and caller uses since caller assumes value is not actor isolated 
        }
    }

    private let _value = Mutex(BoxValue())
}

```

I really don't understand the error. For me, it smells like a bug.

---

<div class="post-metadata">

**Author:** ![Jon\_Shier](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jon_shier/32/921_2.png) [@Jon\_Shier](https://forums.swift.org/u/Jon_Shier)\
**Post date:** [December 15, 2024, 2:09am UTC](https://forums.swift.org/t/mutex-error/76653/2 "2024-12-15T02:09:00Z")

</div>

Pretty sure it's correct, it just doesn't clearly tell you why. Since `BoxValue` isn't `Sendable`, and you pass a new instance in with `value.set`, technically it's possible you kept another reference to the value passed in and can use it unsafely, despite the passed reference in the `Mutex`.

---

<div class="post-metadata">

**Author:** ![jamieQ](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jamieq/32/5117_2.png) [@jamieQ](https://forums.swift.org/u/jamieQ)\
**Post date:** [December 15, 2024, 4:55pm UTC](https://forums.swift.org/t/mutex-error/76653/3 "2024-12-15T16:55:40Z")

</div>

Jon's assessment seems correct to me – the `Mutex` API is designed to try and enforce that you cannot 'sneak' something into it that isn't Sendable and could potentially still be referenced elsewhere, thus introducing potential data races despite protecting mutable state with a lock.

to deal with this constraint, the language offers the `sending` parameter attribute\[1\], which indicates that a value is known to be in a 'disconnected' isolation region, so can't be aliased in a different one. currently, however, i don't think there's any way to indicate that property accessors deal in `sending` values, so i'm not sure the style of convenience accessor you've outlined here can be made to work in this manner (perhaps something like it could be done with macros).

the natural thing to try next to achieve the goal of fully replacing the non-sendable value would be to perform the assignment with a value that is known to be 'disconnected' in this way. i.e. something like:

```swift
func assign(_ newValue: sending BoxValue) {
  _value.withLock { $0 = newValue }
}

```

unfortunately, this formulation currently also fails to compile in the Swift 6 mode, which seems like a bug\[2\]. the only workarounds i'm aware of involve boxing the `sending` value within a closure somehow and performing the assignment via that, e.g.

```swift
func assign(_ newValue: sending BoxValue) {
  let workaround = { newValue }
  _value.withLock { $0 = workaround() }
}

```

alternatively, if you pass in a 'producer' closure of sorts, that also seems to work:

```swift
func assign(_ newValueFactory: () -> sending BoxValue) {
  // in general this pattern should be avoided
  _value.withLock { $0 = newValueFactory() }
}

```

however, this latter approach seems quite undesirable since in general one should typically not invoke arbitrary closures while holding a lock.

* * *

1. [SE-430](https://github.com/swiftlang/swift-evolution/blob/427383544b616b2c491641f3b6d1b91ad0d2cb88/proposals/0430-transferring-parameters-and-results.md) 

2. a similar issue has been reported [here](https://github.com/swiftlang/swift/issues/77199)

---

<div class="post-metadata">

**Author:** ![mattie](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mattie/32/13267_2.png) [@mattie](https://forums.swift.org/u/mattie)\
**Post date:** [February 26, 2026, 4:25pm UTC](https://forums.swift.org/t/mutex-error/76653/4 "2026-02-26T16:25:09Z")

</div>

> [@jamieQ](#):
>
> ```swift
> func assign(_ newValue: sending BoxValue) {
> let workaround = { newValue }
> _value.withLock { $0 = workaround() }
> }
> 
> ```

I was playing around with something like this. And unfortunately it looks like returning the values of local closures gives you a way to side-step sendability checks.

> <https://github.com/swiftlang/swift/issues/87540>
>
> \### Description
> 
> I \*think\* this might be a more general and minimal example of #…87503. But it could also be distinct so I figured it was worth a separate bug.
> 
> \### Reproduction
> 
> \`\`\`swift
> class NonSendable {}
> 
> func bad(\_ newValue: NonSendable) async {
> let workaround = { newValue }
> 	
> send(workaround())
> send(workaround())
> }
> 
> func send(\_ value: sending NonSendable) {}
> \`\`\`
> 
> 
> \### Expected behavior
> 
> This should fail to compile.
> 
> \### Environment
> 
> Apple Swift version 6.3-dev (LLVM c92da8f1f2ebce7, Swift a99985ff7f68089)
> Target: arm64-apple-macosx26.0
> Build config: +assertions
> 
> \### Additional information
> 
> \_No response\_
