# Cannot use subscripts to modify @MainActor Dictionaries…?

**URL:** <https://forums.swift.org/t/cannot-use-subscripts-to-modify-mainactor-dictionaries/69522>\
**Category:** Using Swift\
**Tags:** subscripts, dictionary, compiler-error\
**Created:** [January 18, 2024, 11:55pm UTC](https://forums.swift.org/t/cannot-use-subscripts-to-modify-mainactor-dictionaries/69522 "2024-01-18T23:55:15Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![wadetregaskis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/wadetregaskis/32/8494_2.png) [@wadetregaskis](https://forums.swift.org/u/wadetregaskis)\
**Post date:** [January 18, 2024, 11:55pm UTC](https://forums.swift.org/t/cannot-use-subscripts-to-modify-mainactor-dictionaries/69522/1 "2024-01-18T23:55:15Z")

</div>

```swift
@MainActor
struct Example {
    var dict: [String: String] = [:]

    mutating func demonstrateBug() {
        Task.detached {
            await MainActor.run {
                self.dict["Oh"] = "no"
            }
        }
    }
}

```

That fails with the error message:

> Actor-isolated property 'dict' cannot be passed 'inout' to 'async' function call

Yet if I use the equivalent - but verbose - `updateValue(:forKey)` method, it works fine.

Am I missing something? The above code seems correct.

---

<div class="post-metadata">

**Author:** ![mbrandonw](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mbrandonw/32/349_2.png) [@mbrandonw](https://forums.swift.org/u/mbrandonw)\
**Post date:** [January 19, 2024, 12:26am UTC](https://forums.swift.org/t/cannot-use-subscripts-to-modify-mainactor-dictionaries/69522/2 "2024-01-19T00:26:06Z")

</div>

> [@wadetregaskis](#):
>
> Yet if I use the equivalent - but verbose - `updateValue(:forKey)` method, it works fine.

Are you sure that worked? It doesn't for me:

```swift
@MainActor
struct Example {
  var dict: [String: String] = [:]

  mutating func demonstrateBug() {
    Task.detached { // 🛑 Escaping closure captures mutating 'self' parameter
      await MainActor.run {
        self.dict.updateValue("", forKey: "")
      }
    }
  }
}

```

I don't think this has anything to do with `@MainActor` or dictionaries, but rather you cannot capture mutable variables in sendable/escaping closures. The trailing closure of `Task.detached` is sendable, and `self` is mutable since it is a mutating method.

If this kind of code were allowed it would mean value types could be mutated from outside lexical scopes, and that would not be what is expected from value types. Even in a pre-concurrency Swift this kind of code was not allowed:

```swift
struct Example {
  var dict: [String: String] = [:]

  mutating func demonstrateBug() {
    DispatchQueue.main.async { // 🛑 Escaping closure captures mutating 'self' parameter
      self.dict["a"] = "b"
    }
  }
}

```

---

<div class="post-metadata">

**Author:** ![wadetregaskis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/wadetregaskis/32/8494_2.png) [@wadetregaskis](https://forums.swift.org/u/wadetregaskis)\
**Post date:** [January 19, 2024, 12:54am UTC](https://forums.swift.org/t/cannot-use-subscripts-to-modify-mainactor-dictionaries/69522/3 "2024-01-19T00:54:13Z")

</div>

> [@mbrandonw](#):
>
> Are you sure that worked? It doesn't for me

Ah yes, I distilled my real-world case too far. In my real case it definitely works - not just compiles but works at runtime just fine - but it's a SwiftUI View and the variable in question is `@State`.

Equivalently, change `Example` to a class.

Assuming the compiler error were correct (and that `updateValue(:forKey:)` didn't exist), what would be the alternative way to do this?

I'm also confused as to why it thinks the `Dictionary` subscript is an async function call. As far as I can tell, it is not.

The problem occurs for subscripting on all standard collections, as far as I can tell.

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [January 19, 2024, 1:11am UTC](https://forums.swift.org/t/cannot-use-subscripts-to-modify-mainactor-dictionaries/69522/4 "2024-01-19T01:11:45Z")

</div>

Looks like a bug:

```swift
@MainActor final class Example {
    var dict: [String: String] = [:]

    func demonstrateBug() {
        Task.detached {
            await MainActor.run {
                self.foo() // ✅
                dict["Oh"] = "no" // 🛑 Actor-isolated property 'dict' cannot be passed 'inout' to 'async' function call
            }
        }
    }
    func foo() {
        dict["Oh"] = "no"
    }
}

```

Interestingly the "self." before "dict" is not even insisted upon here.

OTOH, this works fine:

```swift
    print(self.dict["Oh"])

```

---

<div class="post-metadata">

**Author:** ![hborla](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hborla/32/27563_2.png) [@hborla](https://forums.swift.org/u/hborla)\
**Post date:** [January 19, 2024, 5:45am UTC](https://forums.swift.org/t/cannot-use-subscripts-to-modify-mainactor-dictionaries/69522/5 "2024-01-19T05:45:14Z")

</div>

> [@wadetregaskis](#):
>
> That fails with the error message:
> 
> > Actor-isolated property 'dict' cannot be passed 'inout' to 'async' function call
> 
> Yet if I use the equivalent - but verbose - `updateValue(:forKey)` method, it works fine.
> 
> Am I missing something? The above code seems correct.

The diagnostic is bogus and fixed in [[5.10][Concurrency] Fix a few issues with actor-isolated `inout` argument diagnostics by hborla · Pull Request #69126 · apple/swift · GitHub](https://github.com/apple/swift/pull/69126)
