Skip to content

[cxx-interop] Prioritize C++ modules over namespaces in interface files #79180

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

Closed
wants to merge 7 commits into from

Conversation

j-hui
Copy link
Contributor

@j-hui j-hui commented Feb 6, 2025

In Swift, there is currently no way to refer to a module that has been shadowed by a top-level declaration. This is a problem in Swift module interfaces, which fully (*most) qualifies identifiers, e.g., modulename.member. If there is another top-level declaration named modulename, modulename.member will resolve the first component to that declaration rather than to the module; attempting to look up member in the declaration will lead to a missing member error (or resolve to the wrong member if the declaration happens to also define member).

*One exception is within the body of @inlinable functions, which are splatted in interface files almost exactly as written by the user (i.e., usually unqualified). This is also why it is potentially dangerous to attempt any fix that assumes all module interface identifiers are fully qualified.

This problem is more pronounced with C++ interop, where naming a namespace the same as the module is a fairly common idiom (e.g., os, and simd). Worse, this problem is difficult to detect ahead of time---i.e., when a module interface is being generated---because the module might originally be compiled without C++ interop, where header guards prevent the C++ namespace from being defined. The problem only arises when the module is later recompiled from its interface with C++ interop (in fact, the module may need to be recompiled because its user is using C++ interop; see #77754).

This patch fixes this issue specifically for C++ namespace/module name collisions, to avoid potential fall-out that may ensue from a broader fix. With this patch, we only favor a module over a colliding member if (1) we are in an interface file, and (2) the member is a namespace.

It should be possible to drop condition (2) if we can ensure all identifiers are fully-qualified in interface files, but that is not currently the case. That would also fix this issue for Swift modules whose name conflicts with one of its members'.

Related:

rdar://143352205

@j-hui
Copy link
Contributor Author

j-hui commented Feb 6, 2025

@swift-ci Please test

@j-hui
Copy link
Contributor Author

j-hui commented Feb 6, 2025

@swift-ci Please test

@j-hui j-hui marked this pull request as ready for review February 6, 2025 02:51
@j-hui
Copy link
Contributor Author

j-hui commented Feb 6, 2025

@swift-ci Please test

@tshortli tshortli requested a review from artemcm February 6, 2025 22:20
@@ -282,6 +282,10 @@ void UnqualifiedLookupFactory::lookUpTopLevelNamesInModuleScopeContext(
return;
}

bool inInterface = false;
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: You can use DeclContext::isInSwiftinterface() to simplify this code a bit

@Xazax-hun
Copy link
Contributor

@swift-ci Please test

@j-hui j-hui requested a review from fahadnayyar as a code owner March 5, 2025 20:42
@j-hui
Copy link
Contributor Author

j-hui commented Mar 5, 2025

Closing this in favor of a different approach

@j-hui j-hui closed this Mar 5, 2025
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