Skip to content

SE-0444: Fix interactions with Cxx interop #76756

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 2 commits into from
Sep 28, 2024

Conversation

tshortli
Copy link
Contributor

@tshortli tshortli commented Sep 27, 2024

With the upcoming MemberImportVisibility feature enabled, code built with Cxx interop also enabled could be rejected by the compiler with cryptic errors about the __ObjC module not being imported. This is the result of a surprising implementation detail of Cxx interop. When importing C++ namespaces and their members, the Clang importer puts these declarations in the Clang header import module (a.k.a. the bridging header module, __ObjC). C++ namespaces don't have a logical modular home in the Swift AST because they can span multiple modules, so it's understandable why this implementation was chosen. However, the concrete members of namespaces also get placed in the __ObjC module too, and this really confuses things.

To work around this idiosyncrasy of Cxx interop, I've introduced Decl::getModuleContextForNameLookup() which returns the module that a declaration would ideally belong to if Cxx interop didn't have this behavior. This alternative to Decl::getModuleContext() is now used everywhere that MemberImportVisibility rules are enforced to provide consistency.

Additionally, I found that I also had to further special-case the header import module for Cxx interop because it turns out that there are some additional declarations, beyond imported namespaces, that also live there and need to be implicitly visible in every source file. The __ObjC module is not implicitly imported in source files when Cxx interop is enabled, so these declarations are not deemed visible under normal name lookup rules. When I tried to add an implicit import of __ObjC when Cxx interop is enabled, it broke a bunch tests. So for now, when a decl really belongs to the __ObjC module in Cxx interop mode, we just always allow it to be referenced.

This Cxx interop behavior really needs a re-think in my opinion, but that will require larger discussions.

Resolves rdar://136600598.

With the upcoming `MemberImportVisibility` feature enabled, code built with Cxx
interop also enabled could be rejected by the compiler with cryptic errors
about the `__ObjC` module not being imported. This is the result of a
surprising implementation detail of Cxx interop. When importing C++ namespaces
and their members, the Clang importer puts these declarations in the Clang
header import module (a.k.a. the bridging header module, `__ObjC`). C++
namespaces don't have a logical modular home in the Swift AST because they can
span multiple modules, so it's understandable why this implementation was
chosen. However, the concrete members of namespaces also get placed in the
`__ObjC` module too, and this really confuses things.

To work around this idiosyncrasy of Cxx interop, I've introduced
`Decl::getModuleContextForNameLookup()` which returns the module that a
declaration would ideally belong to if Cxx interop didn't have this behavior.
This alternative to `Decl::getModuleContext()` is now used everywhere that
`MemberImportVisibility` rules are enforced to provide consistency.

Additionally, I found that I also had to further special-case the header import
module for Cxx interop because it turns out that there are some additional
declarations, beyond imported namespaces, that also live there and need to be
implicitly visible in every source file. The `__ObjC` module is not implicitly
imported in source files when Cxx interop is enabled, so these declarations are
not deemed visible under normal name lookup rules. When I tried to add an
implicit import of `__ObjC` when Cxx interop is enabled, it broke a bunch
tests. So for now, when a decl really belongs to the `__ObjC` module in Cxx
interop mode, we just always allow it to be referenced.

This Cxx interop behavior really needs a re-think in my opinion, but that will
require larger discussions.

Resolves rdar://136600598.
@tshortli tshortli force-pushed the member-import-visibility-cxx branch from c18f72c to b11bb1c Compare September 27, 2024 19:16
@tshortli
Copy link
Contributor Author

@swift-ci please smoke test

@tshortli tshortli merged commit d2b562a into swiftlang:main Sep 28, 2024
3 checks passed
@tshortli tshortli deleted the member-import-visibility-cxx branch September 28, 2024 16:31
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.

1 participant