Runtime casts of Sendable type to another Sendable type not possible?

I’m interested in knowing if there’s a direct solution to the following issue: Marker protocol 'Sendable' cannot be used in a conditional cast. Sendable is a marker protocol, and as such, it’s evaluated at compile time. However, the compiler should recognize if both sides of the cast are Sendable, so it should simply ignore the Sendable part. Is this just a limitation of the current compiler or am I overlooking something?

protocol A {}
protocol B: A {
  func f()
}

class Z {
  let c: (any A & Sendable)? = nil

  func e () {
    if let d = c as? (any B & Sendable) {  // Marker protocol 'Sendable' cannot be used in a conditional cast
      { @Sendable in
        d.f()
      }()
    }
  }
}

3 Likes

There is a hole you can exploit to work around this for now:

func conditionalCast<T, U>(_ value: T, to: U.Type) -> U? {
    value as? U
}

class Z {
  let c: (any A & Sendable)? = nil

  func e () {
    if let d = conditionalCast(c, to: (any B & Sendable).self) {
      { @Sendable in
        d.f()
      }()
    }
  }
}
3 Likes

Many thanks for the helpful work around, much appreciated!

I took the opportunity and wrote a report: https://github.com/swiftlang/swift/issues/84254

1 Like