diff --git a/compiler/forget/src/CompilerPipeline.ts b/compiler/forget/src/CompilerPipeline.ts index a7e5db4da1..5848329e07 100644 --- a/compiler/forget/src/CompilerPipeline.ts +++ b/compiler/forget/src/CompilerPipeline.ts @@ -11,9 +11,10 @@ import { lower, mergeConsecutiveBlocks, ReactiveFunction, + validateConsistentIdentifiers, + validateTerminalSuccessors, } from "./HIR"; import { Environment, EnvironmentConfig } from "./HIR/Environment"; -import { validateConsistentIdentifiers } from "./HIR/ValidateConsistentIdentifiers"; import { analyseFunctions, dropMemoCalls, @@ -61,6 +62,7 @@ export function* run( yield log({ kind: "hir", name: "MergeConsecutiveBlocks", value: hir }); validateConsistentIdentifiers(hir); + validateTerminalSuccessors(hir); enterSSA(hir); yield log({ kind: "hir", name: "SSA", value: hir }); diff --git a/compiler/forget/src/HIR/ValidateTerminalSuccessors.ts b/compiler/forget/src/HIR/ValidateTerminalSuccessors.ts new file mode 100644 index 0000000000..6dcd899741 --- /dev/null +++ b/compiler/forget/src/HIR/ValidateTerminalSuccessors.ts @@ -0,0 +1,27 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { CompilerError } from "../CompilerError"; +import { GeneratedSource, HIRFunction } from "./HIR"; +import { printTerminal } from "./PrintHIR"; +import { mapTerminalSuccessors } from "./visitors"; + +export function validateTerminalSuccessors(fn: HIRFunction): void { + for (const [, block] of fn.body.blocks) { + mapTerminalSuccessors(block.terminal, (successor) => { + if (!fn.body.blocks.has(successor)) { + CompilerError.invariant( + `Block bb${successor} does not exist for terminal '${printTerminal( + block.terminal + )}'`, + (block.terminal as any).loc ?? GeneratedSource + ); + } + return successor; + }); + } +} diff --git a/compiler/forget/src/HIR/index.ts b/compiler/forget/src/HIR/index.ts index 6918473071..e4743364ce 100644 --- a/compiler/forget/src/HIR/index.ts +++ b/compiler/forget/src/HIR/index.ts @@ -17,3 +17,5 @@ export { } from "./HIRBuilder"; export { mergeConsecutiveBlocks } from "./MergeConsecutiveBlocks"; export { printFunction, printHIR } from "./PrintHIR"; +export { validateConsistentIdentifiers } from "./ValidateConsistentIdentifiers"; +export { validateTerminalSuccessors } from "./ValidateTerminalSuccessors"; diff --git a/compiler/forget/src/Optimization/ConstantPropagation.ts b/compiler/forget/src/Optimization/ConstantPropagation.ts index 4e9803fa57..3f087cfe16 100644 --- a/compiler/forget/src/Optimization/ConstantPropagation.ts +++ b/compiler/forget/src/Optimization/ConstantPropagation.ts @@ -21,6 +21,8 @@ import { removeUnreachableFallthroughs, reversePostorderBlocks, shrink, + validateConsistentIdentifiers, + validateTerminalSuccessors, } from "../HIR"; import { removeDeadDoWhileStatements } from "../HIR/HIRBuilder"; import { eliminateRedundantPhi } from "../SSA"; @@ -70,6 +72,9 @@ export function constantPropagation(fn: HIRFunction): void { // Finally, merge together any blocks that are now guaranteed to execute // consecutively mergeConsecutiveBlocks(fn); + + validateConsistentIdentifiers(fn); + validateTerminalSuccessors(fn); } } diff --git a/compiler/forget/src/__tests__/fixtures/compiler/error.for-return.expect.md b/compiler/forget/src/__tests__/fixtures/compiler/error.for-return.expect.md new file mode 100644 index 0000000000..851361dd9b --- /dev/null +++ b/compiler/forget/src/__tests__/fixtures/compiler/error.for-return.expect.md @@ -0,0 +1,20 @@ + +## Input + +```javascript +function Component(props) { + for (let i = 0; i < props.count; i++) { + return; + } +} + +``` + + +## Error + +``` +[ReactForget] Invariant: Block bb4 does not exist for terminal '[1] For init=bb3 test=bb1 loop=bb5 update=bb4 fallthrough=bb2' (2:4) +``` + + \ No newline at end of file diff --git a/compiler/forget/src/__tests__/fixtures/compiler/error.for-return.js b/compiler/forget/src/__tests__/fixtures/compiler/error.for-return.js new file mode 100644 index 0000000000..0e3651b75e --- /dev/null +++ b/compiler/forget/src/__tests__/fixtures/compiler/error.for-return.js @@ -0,0 +1,5 @@ +function Component(props) { + for (let i = 0; i < props.count; i++) { + return; + } +}