Work around Foundation NS_TYPED_ENUM bug

Consider code like:

```
// Foo.h
typealias NSString * FooKey NS_EXTENSIBLE_TYPED_ENUM;

// Foo.swift
extension FooKey { … }
```

When Swift binds the extension to `FooKey`, that forces ClangImporter to import `FooKey`. ClangImporter’s newtype logic, among other things, checks whether the underlying type (`Swift.String` here) is Objective-C bridgeable and, if so, makes `FooKey` bridgeable too.

But what happens if this code is actually *in* Foundation, which is where the `extension String: _ObjectiveCBridgeable` lives? Well, if the compiler has already bound that extension, it works fine…but if it hasn’t, `FooKey` ends up unbridgeable, which can cause both type checking failures and IRGen crashes when code tries to use its bridging capabilities. And these symptoms are sensitive to precise details of the order Swift happens to bind extensions in, so e.g. adding empty files to the project can make the bug appear or disappear. Spooky.

Add a narrow hack to ClangImporter (only active for types in Foundation) to *assume* that `String` is bridgeable even if the extension declaring this hasn’t been bound yet.

Fixes rdar://142693093.
This commit is contained in:
Becca Royal-Gordon
2025-01-16 15:42:36 -08:00
parent 992d9af8b7
commit 56b20351e3
4 changed files with 23 additions and 1 deletions

View File

@@ -4,6 +4,11 @@
public let NSUTF8StringEncoding: UInt = 8
// This extension will cause ClangImporter/newtype_conformance.swift to fail
// unless rdar://142693093 is fixed. To reproduce, it's important that this
// extension come *before* the _ObjectiveCBridgeable extension for String.
extension NSFileAttributeKey { }
extension AnyHashable : _ObjectiveCBridgeable {
public func _bridgeToObjectiveC() -> NSObject {
return NSObject()

View File

@@ -867,6 +867,8 @@ extern void CGColorRelease(CGColorRef color) __attribute__((availability(macosx,
typedef NSString *_Nonnull NSNotificationName
__attribute((swift_newtype(struct)));
typedef NSString *_Nonnull NSFileAttributeKey
__attribute((swift_newtype(struct)));
NS_SWIFT_UNAVAILABLE("Use NSXPCConnection instead")
extern NSString * const NSConnectionReplyMode;