Skip to content

Work around Foundation NS_TYPED_ENUM bug #78697

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 22, 2025

Conversation

beccadax
Copy link
Contributor

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 when we are compiling Foundation) to assume that String is bridgeable even if the extension declaring this hasn’t been bound yet.

This PR also incorporates minor improvements to type dumping that I added while debugging this issue.

Fixes rdar://142693093.

@beccadax
Copy link
Contributor Author

Will look into adding a unit test shortly.

@beccadax
Copy link
Contributor Author

@swift-ci please smoke test

@beccadax
Copy link
Contributor Author

@swift-ci please smoke test

@Xazax-hun
Copy link
Contributor

Do we have a plan how to fix this issue properly in the future? Is there a ticket to track that?

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.
@beccadax
Copy link
Contributor Author

@Xazax-hun Filed as #78731, though there is no specific timeline for when this work might be carried out. In practice, the vast majority of projects are not supposed to be declaring _ObjectiveCBridgeable conformances, and NSString is nearly the only (bridged) underlying type used for newtypes, so this bug basically only affects Foundation and String.

@beccadax
Copy link
Contributor Author

@swift-ci please smoke test

@beccadax beccadax marked this pull request as ready for review January 18, 2025 01:33
@Xazax-hun
Copy link
Contributor

so this bug basically only affects Foundation and String.

I see, thanks!

@beccadax
Copy link
Contributor Author

@swift-ci please smoke test

@beccadax beccadax enabled auto-merge January 21, 2025 19:10
These would have helped us to debug rdar://142693093 more quickly.
@beccadax
Copy link
Contributor Author

Build wrangler has disabled the failing Linux test.

@beccadax
Copy link
Contributor Author

@swift-ci please smoke test

@beccadax beccadax merged commit ebea19d into swiftlang:main Jan 22, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants