Skip to content

Commit 51a2a07

Browse files
authored
Merge pull request #30758 from nathawes/cross-import-fixes
2 parents 14ef485 + 1a65b84 commit 51a2a07

17 files changed

+395
-281
lines changed

include/swift/AST/Module.h

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -338,26 +338,41 @@ class ModuleDecl : public DeclContext, public TypeDecl {
338338
void getDeclaredCrossImportBystanders(
339339
SmallVectorImpl<Identifier> &bystanderNames);
340340

341-
/// A lazily populated mapping from each declared cross import overlay this
342-
/// module transitively underlies to its bystander and immediate underlying
343-
/// module.
344-
llvm::SmallDenseMap<ModuleDecl *, std::pair<Identifier, ModuleDecl *>, 1>
345-
declaredCrossImportsTransitive;
341+
private:
342+
/// A cache of this module's underlying module and required bystander if it's
343+
/// an underscored cross-import overlay.
344+
Optional<std::pair<ModuleDecl *, Identifier>> declaringModuleAndBystander;
346345

347-
/// Determines if the given \p overlay is a declarared cross-import overlay of
348-
/// this module, or an of its transitively declared overlay modules.
349-
///
350-
/// This is used by tooling to map overlays to their underlying modules, and t
351-
bool isUnderlyingModuleOfCrossImportOverlay(const ModuleDecl *overlay);
346+
/// If this module is an underscored cross import overlay, gets the underlying
347+
/// module that declared it (which may itself be a cross-import overlay),
348+
/// along with the name of the required bystander module. Used by tooling to
349+
/// present overlays as if they were part of their underlying module.
350+
std::pair<ModuleDecl *, Identifier> getDeclaringModuleAndBystander();
351+
352+
public:
353+
354+
/// Returns true if this module is an underscored cross import overlay
355+
/// declared by \p other, either directly or transitively (via intermediate
356+
/// cross-import overlays - for cross-imports involving more than two
357+
/// modules).
358+
bool isCrossImportOverlayOf(ModuleDecl *other);
359+
360+
/// If this module is an underscored cross-import overlay, returns the
361+
/// non-underscored underlying module that declares it as an overlay, either
362+
/// directly or transitively (via intermediate cross-import overlays - for
363+
/// cross-imports involving more than two modules).
364+
ModuleDecl *getDeclaringModuleIfCrossImportOverlay();
365+
366+
/// If this module is an underscored cross-import overlay of \p declaring
367+
/// either directly or transitively, populates \p bystanderNames with the set
368+
/// of bystander modules that must be present alongside \p declaring for
369+
/// the overlay to be imported and returns true. Returns false otherwise.
370+
bool getRequiredBystandersIfCrossImportOverlay(
371+
ModuleDecl *declaring, SmallVectorImpl<Identifier> &bystanderNames);
352372

353-
/// If \p overlay is a transitively declared cross-import overlay of this
354-
/// module, gets the list of bystander modules that need to be imported
355-
/// alongside this module for the overlay to be loaded.
356-
void getAllBystandersForCrossImportOverlay(
357-
ModuleDecl *overlay, SmallVectorImpl<Identifier> &bystanders);
358373

359-
/// Walks and loads the declared cross-import overlays of this module,
360-
/// transitively, to find all overlays this module underlies.
374+
/// Walks and loads the declared, underscored cross-import overlays of this
375+
/// module, transitively, to find all overlays this module underlies.
361376
///
362377
/// This is used by tooling to present these overlays as part of this module.
363378
void findDeclaredCrossImportOverlaysTransitive(

include/swift/AST/PrintOptions.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -432,12 +432,10 @@ struct PrintOptions {
432432
/// The information for converting archetypes to specialized types.
433433
llvm::Optional<TypeTransformContext> TransformContext;
434434

435-
/// Before printing the name of a ModuleDecl, this callback will be called and
436-
/// the name of the ModuleDecl it returns will be printed instead. This is
437-
/// currently used to present cross import overlays as if they were their
438-
/// underlying module.
439-
std::function<const ModuleDecl*(const ModuleDecl *)> mapModuleToUnderlying =
440-
[] (const ModuleDecl *D) { return D; };
435+
/// Whether cross-import overlay modules are printed with their own name (e.g.
436+
/// _MyFrameworkYourFrameworkAdditions) or that of their underlying module
437+
/// (e.g. MyFramework).
438+
bool MapCrossImportOverlaysToDeclaringModule = false;
441439

442440
bool PrintAsMember = false;
443441

@@ -525,6 +523,7 @@ struct PrintOptions {
525523
result.PrintDocumentationComments = true;
526524
result.SkipUnderscoredKeywords = true;
527525
result.EnumRawValues = EnumRawValueMode::PrintObjCOnly;
526+
result.MapCrossImportOverlaysToDeclaringModule = true;
528527
return result;
529528
}
530529

include/swift/AST/SourceFile.h

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -194,16 +194,6 @@ class SourceFile final : public FileUnit {
194194
/// mechanism which is not SourceFile-dependent.)
195195
SeparatelyImportedOverlayMap separatelyImportedOverlays;
196196

197-
using SeparatelyImportedOverlayReverseMap =
198-
llvm::SmallDenseMap<ModuleDecl *, ModuleDecl *>;
199-
200-
/// A lazily populated mapping from a separately imported overlay to its
201-
/// underlying shadowed module.
202-
///
203-
/// This is used by tooling to substitute the name of the underlying module
204-
/// wherever the overlay's name would otherwise be reported.
205-
SeparatelyImportedOverlayReverseMap separatelyImportedOverlaysReversed;
206-
207197
/// A pointer to PersistentParserState with a function reference to its
208198
/// deleter to handle the fact that it's forward declared.
209199
using ParserStatePtr =
@@ -384,7 +374,6 @@ class SourceFile final : public FileUnit {
384374
/// \returns true if the overlay was added; false if it already existed.
385375
bool addSeparatelyImportedOverlay(ModuleDecl *overlay,
386376
ModuleDecl *declaring) {
387-
separatelyImportedOverlaysReversed.clear();
388377
return std::get<1>(separatelyImportedOverlays[declaring].insert(overlay));
389378
}
390379

@@ -402,12 +391,6 @@ class SourceFile final : public FileUnit {
402391
overlays.append(value.begin(), value.end());
403392
}
404393

405-
/// Retrieves a module shadowed by the provided separately imported overlay
406-
/// \p shadowed. If such a module is returned, it should be presented to users
407-
/// as owning the symbols in \p overlay.
408-
ModuleDecl *
409-
getModuleShadowedBySeparatelyImportedOverlay(const ModuleDecl *overlay);
410-
411394
void cacheVisibleDecls(SmallVectorImpl<ValueDecl *> &&globals) const;
412395
const SmallVectorImpl<ValueDecl *> &getCachedVisibleDecls() const;
413396

lib/AST/ASTPrinter.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2153,7 +2153,16 @@ void PrintAST::visitImportDecl(ImportDecl *decl) {
21532153
interleave(decl->getFullAccessPath(),
21542154
[&](const ImportDecl::AccessPathElement &Elem) {
21552155
if (!Mods.empty()) {
2156-
Printer.printModuleRef(Mods.front(), Elem.Item);
2156+
Identifier Name = Elem.Item;
2157+
if (Options.MapCrossImportOverlaysToDeclaringModule) {
2158+
if (auto *MD = Mods.front().getAsSwiftModule()) {
2159+
ModuleDecl *Declaring = const_cast<ModuleDecl*>(MD)
2160+
->getDeclaringModuleIfCrossImportOverlay();
2161+
if (Declaring)
2162+
Name = Declaring->getName();
2163+
}
2164+
}
2165+
Printer.printModuleRef(Mods.front(), Name);
21572166
Mods = Mods.slice(1);
21582167
} else {
21592168
Printer << Elem.Item.str();
@@ -3591,8 +3600,12 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
35913600
template <typename T>
35923601
void printModuleContext(T *Ty) {
35933602
FileUnit *File = cast<FileUnit>(Ty->getDecl()->getModuleScopeContext());
3594-
const ModuleDecl *Mod =
3595-
Options.mapModuleToUnderlying(File->getParentModule());
3603+
ModuleDecl *Mod = File->getParentModule();
3604+
3605+
if (Options.MapCrossImportOverlaysToDeclaringModule) {
3606+
if (ModuleDecl *Declaring = Mod->getDeclaringModuleIfCrossImportOverlay())
3607+
Mod = Declaring;
3608+
}
35963609

35973610
Identifier Name = Mod->getName();
35983611
if (Options.UseExportedModuleNames)

lib/AST/Module.cpp

Lines changed: 95 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1776,78 +1776,118 @@ void ModuleDecl::getDeclaredCrossImportBystanders(
17761776
otherModules.push_back(std::get<0>(pair));
17771777
}
17781778

1779-
using TransitiveOverlays =
1780-
llvm::SmallDenseMap<ModuleDecl *, std::pair<Identifier, ModuleDecl *>, 1>;
1781-
1782-
static void populateTransitiveCrossImports(ModuleDecl *base,
1783-
TransitiveOverlays &result) {
1784-
if (!result.empty() || !base->mightDeclareCrossImportOverlays())
1785-
return;
1786-
1787-
SmallVector<Identifier, 1> bystanders;
1788-
SmallVector<Identifier, 1> overlays;
1779+
void ModuleDecl::findDeclaredCrossImportOverlaysTransitive(
1780+
SmallVectorImpl<ModuleDecl *> &overlayModules) {
17891781
SmallVector<ModuleDecl *, 1> worklist;
1790-
SourceLoc diagLoc; // ignored
1782+
SmallPtrSet<ModuleDecl *, 1> seen;
1783+
SourceLoc unused;
17911784

1792-
worklist.push_back(base);
1785+
worklist.push_back(this);
17931786
while (!worklist.empty()) {
17941787
ModuleDecl *current = worklist.back();
17951788
worklist.pop_back();
1796-
if (!current->mightDeclareCrossImportOverlays())
1797-
continue;
1798-
bystanders.clear();
1799-
current->getDeclaredCrossImportBystanders(bystanders);
1800-
for (Identifier bystander: bystanders) {
1801-
overlays.clear();
1802-
current->findDeclaredCrossImportOverlays(bystander, overlays, diagLoc);
1803-
for (Identifier overlay: overlays) {
1804-
if (!overlay.str().startswith("_"))
1805-
continue;
1806-
ModuleDecl *overlayMod =
1807-
base->getASTContext().getModuleByName(overlay.str());
1808-
if (!overlayMod)
1809-
continue;
1810-
if (result.insert({overlayMod, {bystander, current}}).second)
1811-
worklist.push_back(overlayMod);
1789+
for (auto &pair: current->declaredCrossImports) {
1790+
Identifier &bystander = std::get<0>(pair);
1791+
for (auto *file: std::get<1>(pair)) {
1792+
auto overlays = file->getOverlayModuleNames(current, unused, bystander);
1793+
for (Identifier overlay: overlays) {
1794+
// We don't present non-underscored overlays as part of the underlying
1795+
// module, so ignore them.
1796+
if (!overlay.str().startswith("_"))
1797+
continue;
1798+
ModuleDecl *overlayMod =
1799+
getASTContext().getModuleByName(overlay.str());
1800+
if (!overlayMod)
1801+
continue;
1802+
if (seen.insert(overlayMod).second) {
1803+
overlayModules.push_back(overlayMod);
1804+
worklist.push_back(overlayMod);
1805+
}
1806+
}
18121807
}
18131808
}
18141809
}
18151810
}
18161811

1817-
bool ModuleDecl::isUnderlyingModuleOfCrossImportOverlay(
1818-
const ModuleDecl *overlay) {
1819-
if (!overlay->getNameStr().startswith("_"))
1820-
return false;
1812+
std::pair<ModuleDecl *, Identifier>
1813+
ModuleDecl::getDeclaringModuleAndBystander() {
1814+
if (declaringModuleAndBystander)
1815+
return *declaringModuleAndBystander;
18211816

1822-
populateTransitiveCrossImports(this, declaredCrossImportsTransitive);
1823-
return declaredCrossImportsTransitive.find(overlay) !=
1824-
declaredCrossImportsTransitive.end();
1825-
}
1817+
if (!hasUnderscoredNaming())
1818+
return *(declaringModuleAndBystander = {nullptr, Identifier()});
18261819

1827-
void ModuleDecl::getAllBystandersForCrossImportOverlay(
1828-
ModuleDecl *overlay, SmallVectorImpl<Identifier> &bystanders) {
1829-
if (!overlay->getNameStr().startswith("_"))
1830-
return;
1820+
// Search the transitive set of imported @_exported modules to see if any have
1821+
// this module as their overlay.
1822+
SmallPtrSet<ModuleDecl *, 16> seen;
1823+
SmallVector<ModuleDecl::ImportedModule, 16> imported;
1824+
SmallVector<ModuleDecl::ImportedModule, 16> furtherImported;
1825+
ModuleDecl *overlayModule = this;
1826+
1827+
getImportedModules(imported, ModuleDecl::ImportFilterKind::Public);
1828+
while (!imported.empty()) {
1829+
ModuleDecl *importedModule = std::get<1>(imported.back());
1830+
imported.pop_back();
1831+
if (!seen.insert(importedModule).second)
1832+
continue;
1833+
1834+
using CrossImportMap =
1835+
llvm::SmallDenseMap<Identifier, SmallVector<OverlayFile *, 1>>;
1836+
CrossImportMap &crossImports = importedModule->declaredCrossImports;
1837+
1838+
// If any of MD's cross imports declare this module as its overlay, report
1839+
// MD as the underlying module.
1840+
auto ret = std::find_if(crossImports.begin(), crossImports.end(),
1841+
[&](CrossImportMap::iterator::value_type &pair) {
1842+
for (OverlayFile *file: std::get<1>(pair)) {
1843+
ArrayRef<Identifier> overlays = file->getOverlayModuleNames(
1844+
importedModule, SourceLoc(), std::get<0>(pair));
1845+
if (std::find(overlays.begin(), overlays.end(),
1846+
overlayModule->getName()) != overlays.end())
1847+
return true;
1848+
}
1849+
return false;
1850+
});
1851+
if (ret != crossImports.end())
1852+
return *(declaringModuleAndBystander = {importedModule, ret->first});
18311853

1832-
populateTransitiveCrossImports(this, declaredCrossImportsTransitive);
1854+
if (!importedModule->hasUnderscoredNaming())
1855+
continue;
18331856

1834-
auto end = declaredCrossImportsTransitive.end();
1835-
for (auto i = declaredCrossImportsTransitive.find(overlay);
1836-
i != end;
1837-
i = declaredCrossImportsTransitive.find(i->second.second)) {
1838-
bystanders.push_back(i->second.first);
1857+
furtherImported.clear();
1858+
importedModule->getImportedModules(furtherImported,
1859+
ModuleDecl::ImportFilterKind::Public);
1860+
imported.append(furtherImported.begin(), furtherImported.end());
18391861
}
1862+
1863+
return *(declaringModuleAndBystander = {nullptr, Identifier()});
18401864
}
18411865

1842-
void ModuleDecl::findDeclaredCrossImportOverlaysTransitive(
1843-
SmallVectorImpl<ModuleDecl *> &overlayModules) {
1844-
populateTransitiveCrossImports(this, declaredCrossImportsTransitive);
1845-
std::transform(declaredCrossImportsTransitive.begin(),
1846-
declaredCrossImportsTransitive.end(),
1847-
std::back_inserter(overlayModules),
1848-
[](TransitiveOverlays::iterator::value_type &i) {
1849-
return i.first;
1850-
});
1866+
bool ModuleDecl::isCrossImportOverlayOf(ModuleDecl *other) {
1867+
ModuleDecl *current = this;
1868+
while ((current = current->getDeclaringModuleAndBystander().first)) {
1869+
if (current == other)
1870+
return true;
1871+
}
1872+
return false;
1873+
}
1874+
1875+
ModuleDecl *ModuleDecl::getDeclaringModuleIfCrossImportOverlay() {
1876+
ModuleDecl *current = this, *declaring = nullptr;
1877+
while ((current = current->getDeclaringModuleAndBystander().first))
1878+
declaring = current;
1879+
return declaring;
1880+
}
1881+
1882+
bool ModuleDecl::getRequiredBystandersIfCrossImportOverlay(
1883+
ModuleDecl *declaring, SmallVectorImpl<Identifier> &bystanderNames) {
1884+
auto current = std::make_pair(this, Identifier());
1885+
while ((current = current.first->getDeclaringModuleAndBystander()).first) {
1886+
bystanderNames.push_back(current.second);
1887+
if (current.first == declaring)
1888+
return true;
1889+
}
1890+
return false;
18511891
}
18521892

18531893
namespace {
@@ -2170,32 +2210,6 @@ bool SourceFile::shouldCrossImport() const {
21702210
getASTContext().LangOpts.EnableCrossImportOverlays;
21712211
}
21722212

2173-
ModuleDecl*
2174-
SourceFile::getModuleShadowedBySeparatelyImportedOverlay(const ModuleDecl *overlay) {
2175-
if (separatelyImportedOverlaysReversed.empty() &&
2176-
!separatelyImportedOverlays.empty()) {
2177-
for (auto &entry: separatelyImportedOverlays) {
2178-
ModuleDecl *shadowed = entry.first;
2179-
for (ModuleDecl *overlay: entry.second) {
2180-
// If for some reason the same overlay shadows more than one module,
2181-
// pick the one whose name is alphabetically first.
2182-
ModuleDecl *old = separatelyImportedOverlaysReversed[overlay];
2183-
if (!old || shadowed->getNameStr() < old->getNameStr())
2184-
separatelyImportedOverlaysReversed[overlay] = shadowed;
2185-
}
2186-
}
2187-
}
2188-
2189-
ModuleDecl *underlying = const_cast<ModuleDecl *>(overlay);
2190-
while (underlying->getNameStr().startswith("_")) {
2191-
auto next = separatelyImportedOverlaysReversed.find(underlying);
2192-
if (next == separatelyImportedOverlaysReversed.end())
2193-
return nullptr;
2194-
underlying = std::get<1>(*next);
2195-
}
2196-
return underlying;
2197-
};
2198-
21992213
void ModuleDecl::clearLookupCache() {
22002214
getASTContext().getImportCache().clear();
22012215

0 commit comments

Comments
 (0)