Skip to content

[ClangImporter] Can't correct import closure that returns NSString #81984

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

DataCorrupted
Copy link
Contributor

No description provided.


// RUN: %target-swift-frontend -emit-silgen %t/Theme.swift -import-objc-header %t/Theme.h | %FileCheck %t/Theme.swift

// REQUIRES: objc_interop
Copy link
Member

Choose a reason for hiding this comment

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

Do we need ObjC interop? Can we not simply create a header that declares @class NSString and use a module to import that?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If I remove objc_interop and change #import <Foundation/Foundation.h> to @class NSString;, the file triggers a type check error (shown below) instead of crashing SILGen.

/Users/peterrong/swift-project/build/Ninja-RelWithDebInfoAssert/swift-macosx-arm64/test-macosx-arm64/ClangImporter/Output/objc_method_with_NSString_clousure.swift.tmp/Theme.swift:2:16: error: closure passed to parameter of type 'OpaquePointer' that does not accept a closure
1 | let _ = ThemeFuncTable(
2 |     keyGetter: { "1" }
  |                `- error: closure passed to parameter of type 'OpaquePointer' that does not accept a closure
3 | )
4 | 

/Users/peterrong/swift-project/build/Ninja-RelWithDebInfoAssert/swift-macosx-arm64/test-macosx-arm64/ClangImporter/Output/objc_method_with_NSString_clousure.swift.tmp/Theme.h:2:16: note: 'init(keyGetter:)' declared here
1 | @class NSString;
2 | typedef struct ThemeFuncTable {
  |                `- note: 'init(keyGetter:)' declared here
3 |   NSString *_Nonnull (*_Nonnull keyGetter)();
4 | } ThemeFuncTable;

Copy link
Member

Choose a reason for hiding this comment

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

You will likely need to pass -enable-objc-interop to the %target-swift-frontend when you do that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just tried. The type check error is the same. I assume this crash can't be triggered through @class NSString and has to #import <Foundation/Foundation.h>.

Copy link
Member

Choose a reason for hiding this comment

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

That doesn't make any sense - #import <Foundation/Foundation.h> still creates a clang module that is imported the same as here. The declaration is different. Perhaps you need something a bit more complete? Something like:

@interface NSString: NSObject
@end

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Using this, swift side complains it can't convert String into NSString, and the point of this bug is incorrect type conversion, so I guess some bridging code in Foundation matters?

Copy link
Member

Choose a reason for hiding this comment

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

I don't know the declarations off the top of my head, you should see what the declaration for NSString is.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually @CodaFi 's suggestion worked. Kindly resolve the comment if that works for you.

Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: objc_method_with_NSString_closure.swift

Copy link
Contributor

@CodaFi CodaFi Jun 6, 2025

Choose a reason for hiding this comment

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

There's also no CHECK lines in this test so it's going to fail. Consider

// RUN: not --crash %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-silgen %t/Theme.swift -import-objc-header %t/Theme.h

instead

Copy link
Contributor Author

@DataCorrupted DataCorrupted Jun 6, 2025

Choose a reason for hiding this comment

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

It works, thanks. Now the code crashes on both my Mac and linux server.

However, I'm not sure we want to merge it by putting not --crash there without a fix. I wonder if anyone has any insight on why there is a crash.

Signed-off-by: Peter Rong <[email protected]>
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.

3 participants