Skip to content

Commit a27cf55

Browse files
authored
Merge pull request #71763 from artemcm/DepScanMainTargetCycles
[Dependency Scanning] Detect cycles of main target module depending on an existing Swift textual or prebuilt binary module
2 parents b3f302b + 8734d2e commit a27cf55

File tree

2 files changed

+31
-7
lines changed

2 files changed

+31
-7
lines changed

lib/DependencyScan/ScanDependencies.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1410,6 +1410,9 @@ static bool diagnoseCycle(CompilerInstance &instance,
14101410
[&buffer](const ModuleDependencyID &id) {
14111411
buffer.append(id.ModuleName);
14121412
switch (id.Kind) {
1413+
case swift::ModuleDependencyKind::SwiftSource:
1414+
buffer.append(" (Source Target)");
1415+
break;
14131416
case swift::ModuleDependencyKind::SwiftInterface:
14141417
buffer.append(".swiftinterface");
14151418
break;
@@ -1429,11 +1432,12 @@ static bool diagnoseCycle(CompilerInstance &instance,
14291432
[&buffer] { buffer.append(" -> "); });
14301433
};
14311434

1432-
auto emitCycleDiagnostic = [&](const ModuleDependencyID &dep) {
1433-
auto startIt = std::find(openSet.begin(), openSet.end(), dep);
1435+
auto emitCycleDiagnostic = [&](const ModuleDependencyID &sourceId,
1436+
const ModuleDependencyID &sinkId) {
1437+
auto startIt = std::find(openSet.begin(), openSet.end(), sourceId);
14341438
assert(startIt != openSet.end());
14351439
std::vector<ModuleDependencyID> cycleNodes(startIt, openSet.end());
1436-
cycleNodes.push_back(*startIt);
1440+
cycleNodes.push_back(sinkId);
14371441
llvm::SmallString<64> errorBuffer;
14381442
emitModulePath(cycleNodes, errorBuffer);
14391443
instance.getASTContext().Diags.diagnose(
@@ -1472,13 +1476,20 @@ static bool diagnoseCycle(CompilerInstance &instance,
14721476
auto beforeSize = openSet.size();
14731477
assert(cache.findDependency(lastOpen).has_value() &&
14741478
"Missing dependency info during cycle diagnosis.");
1475-
for (const auto &dep : cache.getAllDependencies(lastOpen)) {
1476-
if (closeSet.count(dep))
1479+
for (const auto &depId : cache.getAllDependencies(lastOpen)) {
1480+
if (closeSet.count(depId))
14771481
continue;
1478-
if (openSet.insert(dep)) {
1482+
// Ensure we detect dependency of the Source target
1483+
// on an existing Swift module with the same name
1484+
if (kindIsSwiftDependency(depId) &&
1485+
depId.ModuleName == mainId.ModuleName && openSet.contains(mainId)) {
1486+
emitCycleDiagnostic(mainId, depId);
1487+
return true;
1488+
}
1489+
if (openSet.insert(depId)) {
14791490
break;
14801491
} else {
1481-
emitCycleDiagnostic(dep);
1492+
emitCycleDiagnostic(depId, depId);
14821493
return true;
14831494
}
14841495
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %empty-directory(%t/module-cache)
3+
4+
// RUN: not %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -module-name CycleOverlay &> %t/out.txt
5+
6+
// RUN: %FileCheck %s < %t/out.txt
7+
8+
// CHECK: module dependency cycle: 'CycleOverlay (Source Target) -> CycleSwiftMiddle.swiftinterface -> CycleOverlay.swiftinterface'
9+
// CHECK: Swift Overlay dependency of 'CycleSwiftMiddle' on 'CycleOverlay' via Clang module dependency: 'CycleSwiftMiddle.swiftinterface -> CycleClangMiddle.pcm -> CycleOverlay.pcm'
10+
11+
import CycleSwiftMiddle
12+
13+

0 commit comments

Comments
 (0)