Introduce separately-imported stdlib overlays

The `_Concurrency` and `_StringProcessing` modules are implementation details of the standard library; to developers, their contents should behave as though they are declared directly within module `Swift`. This is the exact same behavior we expect of cross-import overlays, so treat these modules as though they are cross-import overlays with no bystanding module.

Because these modules don’t re-export the standard library, it’s also necessary to treat `Swift` as a separately imported overlay of itself; do so and make that actually work.
This commit is contained in:
Becca Royal-Gordon
2025-09-17 13:00:53 -07:00
parent 83629977da
commit 3abbfaa9cb
10 changed files with 93 additions and 27 deletions

View File

@@ -2374,28 +2374,41 @@ void ModuleDecl::findDeclaredCrossImportOverlaysTransitive(
if (auto *clangModule = getUnderlyingModuleIfOverlay())
worklist.push_back(clangModule);
auto addOverlay = [&](Identifier overlay) {
// We don't present non-underscored overlays as part of the underlying
// module, so ignore them.
if (!overlay.hasUnderscoredNaming())
return;
ModuleDecl *overlayMod =
getASTContext().getModuleByIdentifier(overlay);
if (!overlayMod && overlayMod != this)
return;
if (seen.insert(overlayMod).second) {
overlayModules.push_back(overlayMod);
worklist.push_back(overlayMod);
if (auto *clangModule = overlayMod->getUnderlyingModuleIfOverlay())
worklist.push_back(clangModule);
}
};
while (!worklist.empty()) {
ModuleDecl *current = worklist.back();
worklist.pop_back();
if (current->isStdlibModule()) {
for (auto overlay : getASTContext().StdlibOverlayNames) {
addOverlay(overlay);
}
}
for (auto &pair: current->declaredCrossImports) {
Identifier &bystander = std::get<0>(pair);
for (auto *file: std::get<1>(pair)) {
auto overlays = file->getOverlayModuleNames(current, unused, bystander);
for (Identifier overlay: overlays) {
// We don't present non-underscored overlays as part of the underlying
// module, so ignore them.
if (!overlay.hasUnderscoredNaming())
continue;
ModuleDecl *overlayMod =
getASTContext().getModuleByName(overlay.str());
if (!overlayMod)
continue;
if (seen.insert(overlayMod).second) {
overlayModules.push_back(overlayMod);
worklist.push_back(overlayMod);
if (auto *clangModule = overlayMod->getUnderlyingModuleIfOverlay())
worklist.push_back(clangModule);
}
addOverlay(overlay);
}
}
}
@@ -2432,6 +2445,12 @@ ModuleDecl::getDeclaringModuleAndBystander() {
if (!hasUnderscoredNaming())
return *(declaringModuleAndBystander = {nullptr, Identifier()});
// If this is one of the stdlib overlays, indicate as much.
auto &ctx = getASTContext();
if (llvm::is_contained(ctx.StdlibOverlayNames, getRealName()))
return *(declaringModuleAndBystander = { ctx.getStdlibModule(),
Identifier() });
// Search the transitive set of imported @_exported modules to see if any have
// this module as their overlay.
SmallPtrSet<ModuleDecl *, 16> seen;
@@ -2511,7 +2530,8 @@ bool ModuleDecl::getRequiredBystandersIfCrossImportOverlay(
auto *clangModule = declaring->getUnderlyingModuleIfOverlay();
auto current = std::make_pair(this, Identifier());
while ((current = current.first->getDeclaringModuleAndBystander()).first) {
bystanderNames.push_back(current.second);
if (!current.second.empty())
bystanderNames.push_back(current.second);
if (current.first == declaring || current.first == clangModule)
return true;
}