swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.48k stars 10.35k forks source link

Unable to send a bridged String to ObjC API #76492

Open mattmassicotte opened 4 weeks ago

mattmassicotte commented 4 weeks ago

Description

I'm having a very difficult time making an Objective-C API that interoperates with Swift. Specifcally, something is going wrong with my use of NSString here.

Reproduction

NS_HEADER_AUDIT_BEGIN(nullability, sendability)

NS_SWIFT_SENDABLE
@interface DataModel : NSObject

@property (nonatomic, copy) NSString* name;

@end

NS_SWIFT_UI_ACTOR
@interface DataStore : NSObject

- (void)loadModelNamed:(NSString *)name withCompletionHandler:(void (^)(DataModel *))block NS_SWIFT_NAME(loadModel(named:completionHandler:));

@end

NS_HEADER_AUDIT_END(nullability, sendability)

try 1:

func useThing() async {
  let store = DataStore()

  // ERROR: Sending value of non-Sendable type 'String' with later accesses from nonisolated context to main actor-isolated context risks causing data races
  _ = await store.loadModel(named: "value")
}

try 2:

func useThing() async {
  let store = DataStore()
  let value = "value"

  // ERROR: Sending 'value._bridgeToObjectiveC' risks causing data races
  _ = await store.loadModel(named: value)
}

Expected behavior

I would have expected both of these versions to bridge NSString to String and just work fine. It seems like that's happening, but in a way that isn't keeping isolation checking happy.

Environment

swift-driver version: 1.113 Apple Swift version 6.0 (swiftlang-6.0.0.7.6 clang-1600.0.24.1) Target: arm64-apple-macosx14.0

Additional information

No response

gottesmm commented 4 days ago

Ok, partially what is happening here is that String is Sendable, but NSString is not.

gottesmm commented 4 days ago

Hmm... so what is actually happening here is that we are using a fix_lifetime to guarantee that the bridged NSString stays around long enough and we are treating a fix_lifetime as a real require use. That being said, perhaps, we shouldn't actually treat it that way