SendableKeyPath?

what an awful hack!

extension KeyPath:@unchecked Sendable
{
}

it seems this was noticed nearly two years ago, and yet nothing has been done about it.

i guess this has something to do with keypaths capturing accessor parameters, and we have no way of representing the sendability of those parameters in KeyPath’s type signature. but what could we possibly use besides a KeyPath to do keypath things? (except for… escaping closures…?)

do we need SendableKeyPath, that can only capture Sendable accessor parameters?

3 Likes

Hmm, maybe a key path literal that only captures Sendable accessor parameters could return a type: KeyPath & Sendable?

1 Like

As the bug report notes, KeyPaths should be Sendable, and captures should already be restricted to Sendable values.

SE-0302 - Sendable and @Sendable closures:

Key path literals

Key paths themselves conform to the Sendable protocol. However, to ensure that it is safe to share key paths, key path literals can only capture values of types that conform to the Sendable protocol. This affects uses of subscripts in key paths:

class SomeClass: Hashable {
  var value: Int
}

class SomeContainer {
  var dict: [SomeClass : String]
}

let sc = SomeClass(...)

// error: capture of 'sc' in key path requires 'SomeClass' to conform
// to 'Sendable'
let keyPath = \SomeContainer.dict[sc]

But apparently that hasn't been implemented. That snippet doesn't produce the expected error.

There was some discussion about loosening this, and having sendable keypath literals produce KeyPath & Sendable, but AFAICT that never made it in to a proposal.

4 Likes

With -strict-concurrency=complete, I get:

t.swift:20:36: warning: cannot form key path that captures non-sendable type 'SomeClass'
  let keyPath = \SomeContainer.dict[sc]
                                   ^

Right. I continue to think this is the right way forward, because the currently set of restrictions makes it impossible to form key paths to actor-isolated state.

Doug

4 Likes