Skip to content

C++ Interop: import call operators #36075

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 3, 2021

Conversation

egorzhdan
Copy link
Contributor

This change adds support for calling operator() from Swift code.

As the C++ interop manifesto describes, operator() is imported into Swift as callAsFunction.

@egorzhdan
Copy link
Contributor Author

@swift-ci please smoke test

@egorzhdan
Copy link
Contributor Author

@zoecarver could you please take a look at this PR?

The test failure on macOS is unrelated, I'll rerun the CI a bit later.

@zoecarver zoecarver self-requested a review February 21, 2021 22:41
@zoecarver zoecarver added the c++ interop Feature: Interoperability with C++ label Feb 21, 2021
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.

@egorzhdan thank you so much! This patch looks great! The main thing I'd like to see is some more tests, but other than that, this lgtm.

auto FD = dyn_cast<clang::FunctionDecl>(D);
if (!FD) {
// This can happen for example for templated operators functions.
// We don't support those, yet.
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this comment is still true. We can import templated operators.

If you wanted to make a patch to support templated operators, that would also be super helpful. Probably a nfc.

Additionally, I'm not sure we still need the check for !FD, but better safe than sorry, so I'd probably leave it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I haven't really looked yet into how this behaves for templated operators. I'll try & if it works, I'll remove this comment in a separate PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

Even better. Thank you!

@@ -1469,6 +1469,10 @@ bool shouldSuppressDeclImport(const clang::Decl *decl);
/// but are now renamed using the swift_name attribute.
bool isSpecialUIKitStructZeroProperty(const clang::NamedDecl *decl);

/// Whether this operator should be imported as a static function
/// even if implemented as a non-static member function.
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not tied to this change, but what would you think about replacing implemented with imported, I think that makes a bit more sense here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay, rephrased this comment a little bit

@@ -19,4 +19,12 @@ OperatorsTestSuite.test("LoadableIntWrapper.plus") {
expectEqual(19, result.value)
}

OperatorsTestSuite.test("LoadableIntWrapper.call") {
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add the same tests for non-loadable types.

Also, it might be good to have a test with no arguments and two arguments, but I wouldn't mind if you just check the module interface dumps for that one.

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe also an out-of-line test. The only reason I think it might be good to have all this test coverage here is that this operator is imported as a normal member, whereas all previous operators were static members.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeap, sounds fair. I've added a few tests for non-loadable type, and an out-of-line declaration.

@egorzhdan
Copy link
Contributor Author

Turned out this change could cause a crash in SIL: it assumed that all kinds of operators are imported as static functions, and this was problematic when passing this to the underlying method.

I've adjusted the SIL logic for that, hopefully it's correct now.

@egorzhdan
Copy link
Contributor Author

@swift-ci please smoke test

@egorzhdan egorzhdan requested a review from zoecarver February 23, 2021 12:06
if (index == 0)
return getCXXMethodSelfPattern(paramType);
} else {
// The last parameter is 'self'.
Copy link
Contributor

Choose a reason for hiding this comment

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

This logic might need to change once #34993 lands, but nothing you need to do.

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.

The only two action items here are adding a SILGen test and an IRGen test for address-only types. Other than that, this LGTM. Thanks for working on this!

I think it's really important to support/test address only types in the initial PR, otherwise, we'll have to fix them later, which is a pain (see #32869).

initSwiftType(signature, origType, kind);
CXXMethod = method;
OtherData = memberStatus.getRawValue();
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems like it basically mimics the logic for CFunctionAsMethodType.

@zoecarver
Copy link
Contributor

@swift-ci please test Windows.

@zoecarver
Copy link
Contributor

@egorzhdan it's really important to run the Windows CI for the C++ interop changes because Windows uses a different ABI so the function names will look different.

@egorzhdan
Copy link
Contributor Author

Oh that's right, I forgot about the Windows differences, thanks for the heads up!

@zoecarver
Copy link
Contributor

@egorzhdan let me know if you need help figuring out the Windows names. Once #36082 lands this will be a whole lot easier. Until then, if you don't have a windows VM/PC, you can usually use Godbolt to figure it out. Here's an example: https://godbolt.org/z/44MWbr

@egorzhdan
Copy link
Contributor Author

Thanks a lot @zoecarver! I actually do have a Windows VM for Swift-related things, but Godbolt is much more convenient. I didn't realize it helps here, I'll try using it instead.

This change adds support for calling `operator()` from Swift code.

As the C++ interop manifesto describes, `operator()` is imported into Swift as `callAsFunction`.
@egorzhdan egorzhdan force-pushed the cxx-operator-call branch from 4c09312 to 7141ae2 Compare March 2, 2021 18:15
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.

This looks great, thanks!

@egorzhdan
Copy link
Contributor Author

@swift-ci please smoke test

@egorzhdan
Copy link
Contributor Author

@swift-ci please test Windows platform

@egorzhdan
Copy link
Contributor Author

@swift-ci please test Windows

@zoecarver
Copy link
Contributor

@swift-ci please test Windows.

@zoecarver
Copy link
Contributor

zoecarver commented Mar 2, 2021

@shahmishal it would appear that @egorzhdan is unable to trigger the Windows bots. Any ideas about why this might be?

Edit: not just in this PR but also in others.

@egorzhdan
Copy link
Contributor Author

@swift-ci please smoke test Linux

@egorzhdan egorzhdan merged commit 55e5d69 into swiftlang:main Mar 3, 2021
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.

2 participants