Skip to content

[cxx-interop] Allow AppKit & UIKit to be rebuilt with C++ interop enabled #79822

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 1 commit into from
Mar 7, 2025

Conversation

egorzhdan
Copy link
Contributor

This removes a workaround from the module interface loader, which was forcing AppKit and UIKit to be rebuilt from their textual interfaces with C++ interop disabled, even if the current compilation explicitly enables it.

The workaround was previously put in place because of a compiler error:

error: type 'AttributeScopes.AppKitAttributes.StrikethroughStyleAttribute' does not conform to protocol 'AttributedStringKey'
note: possibly intended match 'AttributeScopes.AppKitAttributes.StrikethroughStyleAttribute.Value' (aka 'NSUnderlineStyle') does not conform to 'Hashable'

NSUnderlineStyle is a C/C++ type from AppKit that is declared using NS_OPTIONS macro. NS_OPTIONS/CF_OPTIONS macros have different expansions in C vs C++ language modes. The C++ expansions weren't handled correctly by ClangImporter, resulting in two distinct Swift types being created: a typealias NSUnderlineStyle which was marked as unavailable in Swift, and enum NSUnderlineStyle. This mostly worked fine, since the lookup logic was picking the enum during regular name lookup. However, this silently broke down when rebuilding the explicit conformance from AppKit.swiftinterface:

extension AppKit.NSUnderlineStyle : Swift.Hashable {}

Swift was picking the (unavailable) typealias when rebuilding this extension, which means the (available) enum wasn't getting the conformance.

This is verified by an existing test (test/Interop/Cxx/objc-correctness/appkit-uikit.swift).

rdar://142961112

@egorzhdan egorzhdan added the c++ interop Feature: Interoperability with C++ label Mar 6, 2025
@egorzhdan
Copy link
Contributor Author

@swift-ci please test

Copy link
Contributor

@j-hui j-hui left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the really clear summary of why the previous workaround was in place!

Just to make sure I understand (and because I don't think this was explicitly stated in your commit message): in addition to removing the C++ interoperability mode workaround in the module interface loader, you've also adjusted the name importing logic to account for the C/C++ discrepancy for the CF_OPTIONS and NS_OPTIONS macros, to address the specific problem that necessitated the module interface workaround in the first place. Is that correct?

@egorzhdan egorzhdan force-pushed the egorzhdan/NSUnderlineStyle branch from e1e1531 to 876c00b Compare March 7, 2025 11:47
@egorzhdan
Copy link
Contributor Author

you've also adjusted the name importing logic to account for the C/C++ discrepancy for the CF_OPTIONS and NS_OPTIONS macros, to address the specific problem that necessitated the module interface workaround in the first place. Is that correct

Yeap, exactly!

@egorzhdan
Copy link
Contributor Author

@swift-ci please test

…bled

This removes a workaround from the module interface loader, which was forcing AppKit and UIKit to be rebuilt from their textual interfaces with C++ interop disabled, even if the current compilation explicitly enables it.

The workaround was previously put in place because of a compiler error:
```
error: type 'AttributeScopes.AppKitAttributes.StrikethroughStyleAttribute' does not conform to protocol 'AttributedStringKey'
note: possibly intended match 'AttributeScopes.AppKitAttributes.StrikethroughStyleAttribute.Value' (aka 'NSUnderlineStyle') does not conform to 'Hashable'
```

`NSUnderlineStyle` is a C/C++ type from AppKit that is declared using `NS_OPTIONS` macro. `NS_OPTIONS`/`CF_OPTIONS` macros have different expansions in C vs C++ language modes. The C++ expansions weren't handled correctly by ClangImporter, resulting in two distinct Swift types being created: a `typealias NSUnderlineStyle` which was marked as unavailable in Swift, and `enum NSUnderlineStyle`. This mostly worked fine, since the lookup logic was picking the enum during regular name lookup. However, this silently broke down when rebuilding the explicit conformance from `AppKit.swiftinterface`:
```
extension AppKit.NSUnderlineStyle : Swift.Hashable {}
```
Swift was picking the (unavailable) typealias when rebuilding this extension, which means the (available) enum wasn't getting the conformance.

This is verified by an existing test (`test/Interop/Cxx/objc-correctness/appkit-uikit.swift`).

rdar://142961112
@egorzhdan egorzhdan force-pushed the egorzhdan/NSUnderlineStyle branch from 876c00b to 3791ccb Compare March 7, 2025 13:27
@egorzhdan
Copy link
Contributor Author

@swift-ci please test

@nkcsgexi
Copy link
Contributor

nkcsgexi commented Mar 7, 2025

Thank you for fixing this, Egor!

@egorzhdan egorzhdan merged commit c7ddbee into main Mar 7, 2025
5 checks passed
@egorzhdan egorzhdan deleted the egorzhdan/NSUnderlineStyle branch March 7, 2025 23:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ interop Feature: Interoperability with C++
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants