[Bailout] When Inputs Detected In DepGraph Cycle
Inputs occured in depGraph cycle is dangenrous and should be treated as an invariant since Forget _may_ generate broken code in this case, despite that technically this is a stricter then what we needed for the particular case of #633 and #634 and there could be case that this is safe (like many `cfg-` tests that I have to mark as `bailout.`) I expect the next diff will fix them though. commit-id:0b13ed02
Xuan Huang (黄玄) committed
Oct 5, 2022 at 18:42 UTC
19b08e67add524fa0c8c5e19b3b8da22f2528c46
2 files changed
+27
compiler/forget/src/Diagnostic.ts
+8
@@ -126,6 +126,7 @@ export type ErrorCode =
126
| ParseCode<"E0018">
127
| ParseCode<"E0019">
128
| ParseCode<"E0020">
129
+ | ParseCode<"E0021">
130
;
131
132
// prettier-ignore
@@ -168,6 +169,7 @@ export type DiagnosticOpts =
169
| { code: "E0018"; path: NodePath; context: null }
170
| { code: "E0019"; path: NodePath; context: null }
171
| { code: "E0020"; path: NodePath; context: null }
172
+ | { code: "E0021"; path: NodePath; context: { name: Name } }
173
;
174
175
function getDiagnosticMessage(opts: DiagnosticOpts): DiagnosticMessage {
@@ -320,6 +322,12 @@ ${getSource(opts.path)}
322
body: "Forget does not support the use of the arguments object.",
323
suggestion: null,
324
};
325
+ case "E0021":
326
+ return {
327
+ level: DiagnosticLevel.Error,
328
+ body: `Input "${opts.context.name}" is detected in a DepGraph cycle. This is dangenrous since Forget may (though not always) generate broken code like accessing "c_input" before it is defined.`,
329
+ suggestion: null,
330
+ };
331
default:
332
assertExhaustive(opts, `Unhandled error code ${opts}`);
333
}
compiler/forget/src/MiddleEnd/DepGraphAnalysis.ts
+19
@@ -47,6 +47,7 @@ function run(
47
}
48
49
const sccGraph = valGraph.condense();
50
+ checkSCCGraph(sccGraph, context);
51
52
if (outputKinds.includes(OutputKind.SCCGraph)) {
53
context.outputs[OutputKind.SCCGraph].push(sccGraph.snapshot());
@@ -184,6 +185,24 @@ function checkValGraph(valGraph: DepGraph.ValGraph) {
185
}
186
}
187
188
+function checkSCCGraph(sccGraph: DepGraph.SCCGraph, context: CompilerContext) {
189
+ for (const scc of sccGraph.vertices) {
190
+ if (scc.isInput()) continue;
191
+
192
+ for (const valVertex of scc.members) {
193
+ if (IR.isInputVal(valVertex.val)) {
194
+ context.bailout("InputInDepGraphCycle", {
195
+ code: "E0021",
196
+ path: valVertex.val.ast.path,
197
+ context: {
198
+ name: valVertex.val.binding.identifier.name,
199
+ },
200
+ });
201
+ }
202
+ }
203
+ }
204
+}
205
+
206
export function computeCfgControlDeps(
207
irFunc: IR.Func,
208
cfg: CFG