Sendable conformance bug?

Hi,

I am a bit confused with Sendable conformance

Overview

I am not sure why all the code below compiles, particularly the class with a mutable state.

Environment

  • Xcode command line project
  • Xcode Version 14.0 beta 3 (14A5270f))
  • macOS 13.0 Beta (22A5295i)

Questions

  1. Do all value types conform to Sendable by default?
  2. Why is a class with a mutable state allowed to be assigned to a Sendable?
  3. Or am I missing something?

Code

struct S {}
enum E { case ok }
actor A {}
class Engine {}

class Car {
    var engine: Engine
    init(engine: Engine) {
        self.engine = engine
    }
}

var c1 = Car(engine: Engine()) //class with a mutable state
let s1: Sendable = S()
let s2: Sendable = E.ok
let s3: Sendable = A()
let s4: Sendable = c1 //Why is this allowed?

That's weird and afaik should not happen.
A quick check with fresh Xcode 13.4.1 iOS and macOS playgrounds gives the expected error message Value of type 'Car' does not conform to specified type 'Sendable'.
I don't have a newer Xcode handy atm to test, but perhaps this is a bug you should report? I'd be very surprised if there was a recent change that actually gives that class implicit conformance as I don't think that's even feasible...

It could also be that it is related to your previous post (I just noticed it's you), in that due to this being a command line project it "overlooks" this also concurrency related error, but then I'm surprised it catches on in a simple playground this time...

1 Like

Thanks a lot @Gero, it doesn't work when defined within a scope (example: do { })

I will try to file a bug and post the bug ID.

Question:

  • Do value types conform to Sendable by default?

Observations:

Using the following:

  • Xcode Version 14.0 beta 3 (14A5270f))
  • macOS 13.0 Beta (22A5295i)

Compiles fine (without warnings / errors) on the following projects on:

  • SwiftUI multiplatform app
  • iOS playground
  • Command line project
1 Like

It depends a bit, the Swift 5.7 version of TSPL has a new section about this, specifically the very last paragraph explains this via an example:

Because TemperatureReading is a structure that has only sendable properties, and the structure isn’t marked public or @usableFromInline , it’s implicitly sendable. Here’s a version of the structure where conformance to the Sendable protocol is implied:

In short, if your type has no mutable properties or if all its mutable properties conform to Sendable and it's neither marked as public or @usableFromInline then Sendable conformance is implicit.

For your initial example that means that S, E, and A are implicitly Sendable.
I guess the main rationale for allowing this was that value types specifically (but probably often enough also reference types with only let properties) were used by people to cross thread/queue boundaries already in existing code (if you ever had to read something from a Core Data stack in a background queue and then needed to pass it to the UI thread without shooting yourself in the foot you had to basically come up with something like a helper type for that reason).
It would suck if all your code now needed to adopt Sendable explicitly although you were already a good developer taking care of this, so I personally welcome that even if it looks weird when you come at it from the other direction.

2 Likes

Thanks a lot @Gero for the reference and explanation

I have filed a bug, would be great if someone could review it

1 Like

This is intentional—most warnings about Sendable were backed out because they are too noisy:

You should re-enable the warnings explicitly if you want them:

If you compile your test example with -warn-concurrency enabled, you will be warned that Car does not conform to Sendable, as expected.

To check it out, I put your reduced example from the GitHub bug in a file named “test.swift”, and on the command line I ran:

swiftc test.swift
# No diagnostic output, compiles as expected

swiftc -Xfrontend -warn-concurrency test.swift 
test.swift:10:19: warning: type 'Car' does not conform to the 'Sendable' protocol
let s: Sendable = car
                  ^
test.swift:2:7: note: class 'Car' does not conform to the 'Sendable' protocol
class Car {
      ^
4 Likes

Thanks a lot @xwu for clarifying that.

I am able to see the warning after turning on the other swift flags (-Xfrontend -warn-concurrency -Xfrontend -enable-actor-data-race-checks)

From Sendable-related warnings (SE-0302) backed out of Swift 5.6, it seems that they would continue to refine for Swift 5.7, so is the issue that I pointed out worth the review? (should I leave the bug open for it to be considered or should I close the bug?)

I think it’s reasonable to leave the bug open (just my own opinion); the relevant people can triage and determine what they want to do about it.

1 Like

Thanks a lot @xwu !!

In Eliminate data races using Swift Concurrency - WWDC22 - Videos - Apple Developer (24:41 min) they mention the Build Setting > Strict Concurrency Checking (SWIFT_STRICT_CONCURRENCY)

Setting SWIFT_STRICT_CONCURRENCY = complete; throws the warning Type 'Car' does not conform to the 'Sendable' protocol

1 Like