Skip to content

Import Forward Declared Objective-C Interfaces and Protocols #61606

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 9, 2023

Conversation

NuriAmari
Copy link
Contributor

@NuriAmari NuriAmari commented Oct 17, 2022

This patch modifies the ClangImporter to synthesize a placeholder for forward declared Objective-C interfaces and Protocols.

This is the implementation for SE-0384

@NuriAmari
Copy link
Contributor Author

@swift-ci Please smoke test

@drodriguez
Copy link
Contributor

@swift-ci Please Test Source Compatibility

@NuriAmari
Copy link
Contributor Author

@swift-ci Please Test Source Compatibility

@NuriAmari
Copy link
Contributor Author

@swift-ci Please test

@NuriAmari
Copy link
Contributor Author

@swift-ci Please Test Source Compatibility

@NuriAmari NuriAmari force-pushed the fwd-declarations branch 2 times, most recently from 150fef5 to 9410ca3 Compare December 6, 2022 19:40
@NuriAmari
Copy link
Contributor Author

@swift-ci Please Test Source Compatibility

@NuriAmari
Copy link
Contributor Author

@swift-ci Please test

@NuriAmari
Copy link
Contributor Author

@swift-ci Please test

@NuriAmari
Copy link
Contributor Author

@swift-ci Please test

@NuriAmari
Copy link
Contributor Author

@swift-ci Please Test Source Compatibility

@NuriAmari
Copy link
Contributor Author

@swift-ci Please Test Source Compatibility

2 similar comments
@NuriAmari
Copy link
Contributor Author

@swift-ci Please Test Source Compatibility

@NuriAmari
Copy link
Contributor Author

@swift-ci Please Test Source Compatibility

@NuriAmari
Copy link
Contributor Author

@swift-ci please test

@NuriAmari
Copy link
Contributor Author

@swift-ci Please Test Source Compatibility

@NuriAmari
Copy link
Contributor Author

@swift-ci please test

@NuriAmari
Copy link
Contributor Author

@swift-ci please test source compatibility

@NuriAmari
Copy link
Contributor Author

@swift-ci please smoke test

@NuriAmari
Copy link
Contributor Author

@swift-ci please test source compatibility

@NuriAmari
Copy link
Contributor Author

@swift-ci Please test

@NuriAmari
Copy link
Contributor Author

@swift-ci Please test source compatibility

@NuriAmari
Copy link
Contributor Author

@beccadax When you get a chance, I've updated the PR with the diagnostic you suggested.

@NuriAmari
Copy link
Contributor Author

Source compat passes with the flag on: #62649. Stress test fails, but other jobs are failing in the same way, seems unrelated. The Windows test here isn't really pending, it finished successfully: https://ci-external.swift.org/job/swift-PR-windows/8806/

@NuriAmari
Copy link
Contributor Author

@swift-ci Please test windows platform

@NuriAmari
Copy link
Contributor Author

@beccadax Could I get a re-review here? Thanks

@NuriAmari
Copy link
Contributor Author

Hi everyone,

I wanted to draw attention to two aspects of this implementation that maybe were not entirely clear.

  1. The ClangImporter option ImportForwardDeclarations existed before this change and was used by swift-ide-test to print interfaces with placeholders to represent forward declared interfaces and protocols. Per the discussion above, we are no longer synthesizing a placeholder if the declaration corresponds to a Swift definition. This also goes for swift-ide-test and will have an immediate effect for anyone using swift-ide-test and passing --enable-objc-forward-declarations. I think swift-ide-test and the compiler should be as consistent with one another as possible, so this makes sense, but I wanted to make sure to call out it is possible we break something here, but only for clients forward declaring Swift types.

  2. I previously voiced some concern about this implementation allowing users to break previously working code by importing a new Swift module:

Drawbacks to consider. Importing new Swift modules will then have the ability to break previously working code. Maybe justly so, but I'm sure users will find this confusing.

Tony's reply to my concern:

Regarding the last point, I don't think that breakage would occur in practice because forward-declaring a Swift @objc class already shouldn't be expected to work. As an example, let's say Swift module A defines an @objc class, and Clang module B only forward declares that class and has some API that references it. Even if Swift module C that imports both A and B, the APIs in B that refer to A won't work, so anyone trying to forward-declare a Swift class in Obj-C is already putting their build in a fragile and unreliable state.

I'm not trying to advocate for forward declaring Swift types as a supported practice, but I do want to call out that I think this breakage can occur in practice. Firstly, Clang module B is usable by Objective-C clients without issue, and anecdotally that is where we run into most forward declaration issues (ie. only Objective-C clients used the interface before and had no problems with forward declarations, then a Swift client arrives and has problems). Even if clients shouldn't expect it to work, unfortunately it has worked for a long time, so I don't think its unlikely for clients to have working code on the ground doing this.

If Swift module C imports only Clang module B, after this patch the APIs will work, since the compiler thinks the forward declarations refer to Clang definitions. It will only break once Swift module A is imported. So it is possible a Swift client starts using a Clang module that forward declares Swift types, and everything works for some time until they import the complete definition of that type. That said, I'm not overly worried about this since I think its relatively uncommon and easy to fix.

I'm comfortable with both these caveats, and I don't see a better solution, but I wanted to make them explicit for others so that there are no surprises down the line.

cc: @allevato @beccadax @drodriguez @plotfi

@NuriAmari NuriAmari added the objective-c interop Feature: Interoperability with Objective-C label Feb 23, 2023
@NuriAmari NuriAmari self-assigned this Feb 23, 2023
}
}

for (Decl *decl : topLevelObjCExposedDeclsInFileUnit) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could Decl *decl be const Decl *decl here?

@plotfi
Copy link
Contributor

plotfi commented Feb 27, 2023

I looked over the patch once myself and once with Nuri. Overall this PR looks good to me, and the set of included test cases looks very goods.

However I am not the code owner, could Nuri please get a re-review for this PR please? Thanks

@beccadax @drodriguez @zoecarver @allevato @hyp

@NuriAmari
Copy link
Contributor Author

@swift-ci Please test

@NuriAmari
Copy link
Contributor Author

Hi @allevato @beccadax,

With the Swift 5.9 branch cut quickly approaching on March 20th, we'd like to merge this in time for the release. The implementation hasn't changed for a month and if no new concerns arise, I intend on merging in the next week. If concerns crop up afterwards, I'll be available to fix them.

That said, @DougGregor it seems you are the 5.9 release manager for the Swift compiler. If you have the time, I'd appreciate a review; an approval from the Apple side before merging would be preferred.

This modifies the ClangImporter to introduce an opaque placeholder
representation for forward declared Objective-C interfaces and
protocols when imported into Swift.

In the compiler, the new functionality is hidden behind a frontend
flag -enable-import-objc-forward-declarations, and is on by default
for language mode >6.

The feature is disabled entirely in LLDB expression evaluation / Swift
REPL, regardless of language version.
Copy link
Contributor

@zoecarver zoecarver left a comment

Choose a reason for hiding this comment

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

I did a quick review (not very in-depth) and this looks good to me. I think it would still be good to get an in depth review from Becca, but I understand that she might not have time.

Please make sure to run the source compatibility test suite before landing this.

@NuriAmari
Copy link
Contributor Author

@swift-ci Please test

@NuriAmari
Copy link
Contributor Author

@swift-ci Please test source compatibility

2 similar comments
@NuriAmari
Copy link
Contributor Author

@swift-ci Please test source compatibility

@NuriAmari
Copy link
Contributor Author

@swift-ci Please test source compatibility

@plotfi plotfi merged commit d55cfd2 into swiftlang:main Mar 9, 2023
Azoy added a commit to Azoy/swift that referenced this pull request Mar 14, 2023
…tions"

This reverts commit d55cfd2, reversing
changes made to c95e11c.
allevato added a commit to swiftlang/swift-evolution that referenced this pull request Mar 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
objective-c interop Feature: Interoperability with Objective-C
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants