Skip to content

Commit 6d7c4e5

Browse files
Merge pull request #35849 from AnthonyLatsis/fix-debug-cycles
2 parents 16f3306 + 978db47 commit 6d7c4e5

File tree

3 files changed

+42
-6
lines changed

3 files changed

+42
-6
lines changed

docs/RequestEvaluator.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ All existing requests inherit the [`SimpleRequest`](https://github.com/apple/swi
2121

2222
Each request can issue other requests, also through the evaluator. The evaluator automatically tracks such dependencies (by keeping a stack of the currently-active request evaluations). This information is valuable for a few reasons. First, it can help with debugging both correctness and performance, allowing one to visualize the dependencies evaluated when compiling a program. The current protocol has both full-graph visualization (via GraphViz output) and dependencies-for-a-single-request visualization (via a tree-like dump). Second, it ensures that we can detect cyclic dependencies (e.g., a cyclic inheritance hierarchy) correctly, because they show up as cycles in the dependency graph, allowing for proper diagnostics (for the user) and recovery (in the compiler). Third, it can eventually be leveraged to enable better incremental compilation--providing the ability to discover what information affected a particular type-checking decision, and propagate the effects of a specific change through the dependency graph.
2323

24-
The complete dependency graph formed by processing a source file can be visualized by passing the frontend option `-output-request-graphviz <filename>`. The dependency graph will be emitted using the [GraphViz](https://www.graphviz.org) format.
25-
2624
The frontend option `-debug-cycles` will provide debugging output for any cycle detected while processing the given source files. For example, running the [`circular_inheritance.swift` test](https://github.com/apple/swift/blob/main/test/decl/class/circular_inheritance.swift) from the Swift repository using this flag, e.g.,
2725

2826
```

lib/AST/Evaluator.cpp

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,37 @@ bool Evaluator::checkDependency(const ActiveRequest &request) {
7171

7272
void Evaluator::diagnoseCycle(const ActiveRequest &request) {
7373
if (debugDumpCycles) {
74-
llvm::errs() << "===CYCLE DETECTED===\n";
75-
for (auto &req : activeRequests) {
76-
simple_display(llvm::errs(), req);
77-
llvm::errs() << "\n";
74+
const auto printIndent = [](llvm::raw_ostream &OS, unsigned indent) {
75+
OS.indent(indent);
76+
OS << "`--";
77+
};
78+
79+
unsigned indent = 1;
80+
auto &OS = llvm::errs();
81+
82+
OS << "===CYCLE DETECTED===\n";
83+
for (const auto &step : activeRequests) {
84+
printIndent(OS, indent);
85+
if (step == request) {
86+
OS.changeColor(llvm::raw_ostream::GREEN);
87+
simple_display(OS, step);
88+
OS.resetColor();
89+
} else {
90+
simple_display(OS, step);
91+
}
92+
OS << "\n";
93+
indent += 4;
7894
}
95+
96+
printIndent(OS, indent);
97+
OS.changeColor(llvm::raw_ostream::GREEN);
98+
simple_display(OS, request);
99+
100+
OS.changeColor(llvm::raw_ostream::RED);
101+
OS << " (cyclic dependency)";
102+
OS.resetColor();
103+
104+
OS << "\n";
79105
}
80106

81107
request.diagnoseCycle(diags);

test/Frontend/debug-cycles.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
// RUN: not %target-swift-frontend -typecheck -debug-cycles %s 2>&1 | %FileCheck %s --match-full-lines --strict-whitespace --color=false
3+
4+
class Outer2: Outer2.Inner {
5+
class Inner {}
6+
}
7+
// CHECK:===CYCLE DETECTED===
8+
// CHECK-NEXT: `--TypeCheckSourceFileRequest({{.*}})
9+
// CHECK-NEXT: `--SuperclassDeclRequest({{.*}})
10+
// CHECK-NEXT: `--InheritedDeclsReferencedRequest({{.*}})
11+
// CHECK-NEXT: `--QualifiedLookupRequest({{.*}})
12+
// CHECK-NEXT: `--SuperclassDeclRequest({{.*}}) (cyclic dependency)

0 commit comments

Comments
 (0)