From e7e67f335adea5a24ff59a467b22b92702350a5e Mon Sep 17 00:00:00 2001 From: Lauren Tan Date: Thu, 22 Jun 2023 10:18:42 -0400 Subject: [PATCH] Use CompilerError.invariant consistently This PR updates all current usages of invariant to CompilerError.invariant along with any available locs --- .../src/HIR/BuildHIR.ts | 45 ++++++---- .../src/HIR/Dominator.ts | 11 +-- .../src/HIR/Environment.ts | 17 ++-- .../babel-plugin-react-forget/src/HIR/HIR.ts | 21 +++-- .../src/HIR/HIRBuilder.ts | 41 ++++++--- .../src/HIR/MergeConsecutiveBlocks.ts | 14 +-- .../src/HIR/ObjectShape.ts | 7 +- .../src/HIR/PrintHIR.ts | 7 +- .../src/HIR/Types.ts | 7 +- .../src/Inference/AnalyseFunctions.ts | 7 +- .../src/Inference/InferMutableLifetimes.ts | 7 +- .../src/Inference/InferReferenceEffects.ts | 49 ++++++----- .../src/ReactiveScopes/BuildReactiveBlocks.ts | 29 ++++-- .../ReactiveScopes/BuildReactiveFunction.ts | 88 +++++++++++-------- .../ReactiveScopes/CodegenReactiveFunction.ts | 60 +++++++------ .../DeriveMinimalDependencies.ts | 22 +++-- .../ReactiveScopes/PrintReactiveFunction.ts | 8 +- .../ReactiveScopes/PruneNonEscapingScopes.ts | 17 ++-- .../src/ReactiveScopes/RenameVariables.ts | 4 +- .../src/SSA/EliminateRedundantPhi.ts | 8 +- .../src/SSA/EnterSSA.ts | 16 ++-- .../src/SSA/LeaveSSA.ts | 12 ++- .../src/TypeInference/InferTypes.ts | 8 +- .../src/Utils/DisjointSet.ts | 8 +- ...ucture-assignment-to-context-var.expect.md | 2 +- 25 files changed, 313 insertions(+), 202 deletions(-) diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/HIR/BuildHIR.ts b/compiler/forget/packages/babel-plugin-react-forget/src/HIR/BuildHIR.ts index 364c0afaa4..03adac28bb 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/HIR/BuildHIR.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/HIR/BuildHIR.ts @@ -8,7 +8,6 @@ import { NodePath, Scope } from "@babel/traverse"; import * as t from "@babel/types"; import { Expression } from "@babel/types"; -import invariant from "invariant"; import { CompilerError, ErrorSeverity } from "../CompilerError"; import { Err, Ok, Result } from "../Utils/Result"; import { assertExhaustive } from "../Utils/utils"; @@ -769,9 +768,10 @@ function lowerStatement( case "FunctionDeclaration": { const stmt = stmtPath as NodePath; stmt.skip(); - invariant( + CompilerError.invariant( stmt.get("id").type === "Identifier", - "function declarations must have a name" + "function declarations must have a name", + stmt.node.loc ?? null ); const id = stmt.get("id") as NodePath; @@ -795,9 +795,10 @@ function lowerStatement( ), ]) ); - invariant( + CompilerError.invariant( desugared.length === 1, - "only one declaration is created from desugaring function declaration" + "only one declaration is created from desugaring function declaration", + stmt.node.loc ?? null ); lowerStatement(builder, desugared.at(0)!); return; @@ -843,9 +844,10 @@ function lowerStatement( let test: Place; if (left.isVariableDeclaration()) { const declarations = left.get("declarations"); - invariant( + CompilerError.invariant( declarations.length === 1, - `Expected only one declaration in the init of a ForOfStatement, got ${declarations.length}` + `Expected only one declaration in the init of a ForOfStatement, got ${declarations.length}`, + left.node.loc ?? null ); const id = declarations[0].get("id"); const nextIterableOf = lowerValueToTemporary(builder, { @@ -1517,7 +1519,11 @@ function lowerExpression( }); } } else { - invariant(namePath.isJSXNamespacedName(), "Refinement"); + CompilerError.invariant( + namePath.isJSXNamespacedName(), + "Refinement", + namePath.node.loc ?? null + ); const namespace = namePath.node.namespace.name; const name = namePath.node.name.name; propName = `${namespace}:${name}`; @@ -1586,9 +1592,10 @@ function lowerExpression( }); return { kind: "UnsupportedNode", node: exprNode, loc: exprLoc }; } - invariant( + CompilerError.invariant( expr.get("quasi").get("quasis").length == 1, - "there should be only one quasi as we don't support interpolations yet" + "there should be only one quasi as we don't support interpolations yet", + expr.node.loc ?? null ); const value = expr.get("quasi").get("quasis").at(0)!.node.value; if (value.raw !== value.cooked) { @@ -1836,7 +1843,7 @@ function lowerOptionalMemberExpression( loc, }; }); - invariant(object !== null, "Satisfy type checker"); + CompilerError.invariant(object !== null, "Satisfy type checker", null); // block to evaluate if the callee is non-null/undefined. arguments are lowered in this block to preserve // the semantic of conditional evaluation depending on the callee @@ -2268,10 +2275,10 @@ function lowerJsxMemberExpression( if (object.isJSXMemberExpression()) { objectPlace = lowerJsxMemberExpression(builder, object); } else { - invariant( + CompilerError.invariant( object.isJSXIdentifier(), - "TypeScript refinement fail: expected 'JsxIdentifier', got '%s'", - object.node.type + `TypeScript refinement fail: expected 'JsxIdentifier', got '${object.node.type}'`, + object.node.loc ?? null ); objectPlace = lowerIdentifier(builder, object); } @@ -2303,9 +2310,10 @@ function lowerJsxElement( if (expression.isJSXEmptyExpression()) { return null; } else { - invariant( + CompilerError.invariant( expression.isExpression(), - `(BuildHIR::lowerJsxElement) Expected Expression but found ${expression.type}!` + `(BuildHIR::lowerJsxElement) Expected Expression but found ${expression.type}!`, + expression.node.loc ?? null ); return lowerExpressionToTemporary(builder, expression); } @@ -2554,9 +2562,10 @@ function lowerAssignment( } case "MemberExpression": { // This can only occur because of a coding error, parsers enforce this condition - invariant( + CompilerError.invariant( kind === InstructionKind.Reassign, - "MemberExpression may only appear in an assignment expression" + "MemberExpression may only appear in an assignment expression", + lvaluePath.node.loc ?? null ); const lvalue = lvaluePath as NodePath; const property = lvalue.get("property"); diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/HIR/Dominator.ts b/compiler/forget/packages/babel-plugin-react-forget/src/HIR/Dominator.ts index b9842e77e5..4193d197dd 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/HIR/Dominator.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/HIR/Dominator.ts @@ -5,8 +5,8 @@ * LICENSE file in the root directory of this source tree. */ -import invariant from "invariant"; import prettyFormat from "pretty-format"; +import { CompilerError } from "../CompilerError"; import { BlockId, HIRFunction } from "./HIR"; import { eachTerminalSuccessor } from "./visitors"; @@ -88,7 +88,7 @@ export class Dominator { */ get(id: T): T | null { const dominator = this.#nodes.get(id); - invariant(dominator !== undefined, "Unknown node"); + CompilerError.invariant(dominator !== undefined, "Unknown node", null); return dominator === id ? null : dominator; } @@ -119,7 +119,7 @@ export class PostDominator { */ get(id: T): T | null { const dominator = this.#nodes.get(id); - invariant(dominator !== undefined, "Unknown node"); + CompilerError.invariant(dominator !== undefined, "Unknown node", null); return dominator === id ? null : dominator; } @@ -159,9 +159,10 @@ function computeImmediateDominators(graph: Graph): Map { break; } } - invariant( + CompilerError.invariant( newIdom !== null, - `At least one predecessor must have been visited for block ${id}` + `At least one predecessor must have been visited for block ${id}`, + null ); for (const pred of node.preds) { diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/HIR/Environment.ts b/compiler/forget/packages/babel-plugin-react-forget/src/HIR/Environment.ts index cb3b304364..9a09dbde6f 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/HIR/Environment.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/HIR/Environment.ts @@ -6,7 +6,7 @@ */ import * as t from "@babel/types"; -import invariant from "invariant"; +import { CompilerError } from "../CompilerError"; import { ExternalFunction } from "../Entrypoint/Options"; import { log } from "../Utils/logger"; import { @@ -195,9 +195,10 @@ export class Environment { if (config?.customHooks) { this.#globals = new Map(DEFAULT_GLOBALS); for (const [hookName, hook] of config.customHooks) { - invariant( + CompilerError.invariant( !this.#globals.has(hookName), - `[Globals] Found existing definition in global registry for custom hook ${hookName}` + `[Globals] Found existing definition in global registry for custom hook ${hookName}`, + null ); this.#globals.set( hookName, @@ -270,9 +271,10 @@ export class Environment { // If an object or function has a shapeId, it must have been assigned // by Forget (and be present in a builtin or user-defined registry) const shape = this.#shapes.get(shapeId); - invariant( + CompilerError.invariant( shape !== undefined, - `[HIR] Forget internal error: cannot resolve shape ${shapeId}` + `[HIR] Forget internal error: cannot resolve shape ${shapeId}`, + null ); return shape.properties.get(property) ?? null; } else { @@ -284,9 +286,10 @@ export class Environment { const { shapeId } = type; if (shapeId !== null) { const shape = this.#shapes.get(shapeId); - invariant( + CompilerError.invariant( shape !== undefined, - `[HIR] Forget internal error: cannot resolve shape ${shapeId}` + `[HIR] Forget internal error: cannot resolve shape ${shapeId}`, + null ); return shape.functionType; } diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/HIR/HIR.ts b/compiler/forget/packages/babel-plugin-react-forget/src/HIR/HIR.ts index b2b002ebfe..fc11bd154b 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/HIR/HIR.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/HIR/HIR.ts @@ -6,7 +6,6 @@ */ import * as t from "@babel/types"; -import invariant from "invariant"; import { CompilerError } from "../CompilerError"; import { assertExhaustive } from "../Utils/utils"; import { Environment } from "./Environment"; @@ -922,9 +921,10 @@ const opaqueBlockId = Symbol(); export type BlockId = number & { [opaqueBlockId]: "BlockId" }; export function makeBlockId(id: number): BlockId { - invariant( + CompilerError.invariant( id >= 0 && Number.isInteger(id), - "Expected block id to be a non-negative integer" + "Expected block id to be a non-negative integer", + null ); return id as BlockId; } @@ -937,9 +937,10 @@ const opaqueScopeId = Symbol(); export type ScopeId = number & { [opaqueScopeId]: "ScopeId" }; export function makeScopeId(id: number): ScopeId { - invariant( + CompilerError.invariant( id >= 0 && Number.isInteger(id), - "Expected block id to be a non-negative integer" + "Expected block id to be a non-negative integer", + null ); return id as ScopeId; } @@ -952,9 +953,10 @@ const opaqueIdentifierId = Symbol(); export type IdentifierId = number & { [opaqueIdentifierId]: "IdentifierId" }; export function makeIdentifierId(id: number): IdentifierId { - invariant( + CompilerError.invariant( id >= 0 && Number.isInteger(id), - "Expected identifier id to be a non-negative integer" + "Expected identifier id to be a non-negative integer", + null ); return id as IdentifierId; } @@ -967,9 +969,10 @@ const opaqueInstructionId = Symbol(); export type InstructionId = number & { [opaqueInstructionId]: "IdentifierId" }; export function makeInstructionId(id: number): InstructionId { - invariant( + CompilerError.invariant( id >= 0 && Number.isInteger(id), - "Expected instruction id to be a non-negative integer" + "Expected instruction id to be a non-negative integer", + null ); return id as InstructionId; } diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/HIR/HIRBuilder.ts b/compiler/forget/packages/babel-plugin-react-forget/src/HIR/HIRBuilder.ts index f231307407..f2e0c54f4c 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/HIR/HIRBuilder.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/HIR/HIRBuilder.ts @@ -7,7 +7,6 @@ import { Binding, NodePath } from "@babel/traverse"; import * as t from "@babel/types"; -import invariant from "invariant"; import { CompilerError } from "../CompilerError"; import { assertExhaustive } from "../Utils/utils"; import { Environment } from "./Environment"; @@ -388,12 +387,13 @@ export default class HIRBuilder { }); const value = fn(); const last = this.#scopes.pop(); - invariant( + CompilerError.invariant( last != null && last.kind === "label" && last.label === label && last.breakBlock === breakBlock, - "Mismatched label" + "Mismatched label", + null ); return value; } @@ -406,12 +406,13 @@ export default class HIRBuilder { }); const value = fn(); const last = this.#scopes.pop(); - invariant( + CompilerError.invariant( last != null && last.kind === "switch" && last.label === label && last.breakBlock === breakBlock, - "Mismatched label" + "Mismatched label", + null ); return value; } @@ -440,13 +441,14 @@ export default class HIRBuilder { }); const value = fn(); const last = this.#scopes.pop(); - invariant( + CompilerError.invariant( last != null && last.kind === "loop" && last.label === label && last.continueBlock === continueBlock && last.breakBlock === breakBlock, - "Mismatched loops" + "Mismatched loops", + null ); return value; } @@ -462,7 +464,11 @@ export default class HIRBuilder { return scope.breakBlock; } } - invariant(false, "Expected a loop or switch to be in scope"); + CompilerError.invariant( + false, + "Expected a loop or switch to be in scope", + null + ); } /** @@ -478,10 +484,14 @@ export default class HIRBuilder { return scope.continueBlock; } } else if (label !== null && scope.label === label) { - invariant(false, "Continue may only refer to a labeled loop"); + CompilerError.invariant( + false, + "Continue may only refer to a labeled loop", + null + ); } } - invariant(false, "Expected a loop to be in scope"); + CompilerError.invariant(false, "Expected a loop to be in scope", null); } } @@ -501,7 +511,11 @@ function _shrink(func: HIR): void { return target; } const block = func.blocks.get(blockId); - invariant(block != null, "expected block %s to exist", blockId); + CompilerError.invariant( + block != null, + `expected block ${blockId} to exist`, + null + ); target = getTargetIfIndirection(block); if (target !== null) { // the target might also be a simple goto, recurse @@ -717,9 +731,10 @@ export function markInstructionIds(func: HIR): void { const visited = new Set(); for (const [_, block] of func.blocks) { for (const instr of block.instructions) { - invariant( + CompilerError.invariant( !visited.has(instr), - `${printInstruction(instr)} already visited!` + `${printInstruction(instr)} already visited!`, + instr.loc ); visited.add(instr); instr.id = makeInstructionId(++id); diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/HIR/MergeConsecutiveBlocks.ts b/compiler/forget/packages/babel-plugin-react-forget/src/HIR/MergeConsecutiveBlocks.ts index 2c9a58106d..3a6f5e71ee 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/HIR/MergeConsecutiveBlocks.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/HIR/MergeConsecutiveBlocks.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import invariant from "invariant"; +import { CompilerError } from "../CompilerError"; import { BlockId, Effect, @@ -47,10 +47,10 @@ export function mergeConsecutiveBlocks(fn: HIRFunction): void { const originalPredecessorId = Array.from(block.preds)[0]!; const predecessorId = merged.get(originalPredecessorId); const predecessor = fn.body.blocks.get(predecessorId); - invariant( + CompilerError.invariant( predecessor !== undefined, - "Expected predecessor %s to exist", - predecessorId + `Expected predecessor ${predecessorId} to exist`, + null ); if (predecessor.terminal.kind !== "goto" || predecessor.kind !== "block") { // The predecessor is not guaranteed to transfer control to this block, @@ -60,10 +60,10 @@ export function mergeConsecutiveBlocks(fn: HIRFunction): void { // Replace phis in the merged block with canonical assignments to the single operand value for (const phi of block.phis) { - invariant( + CompilerError.invariant( phi.operands.size === 1, - "Found a block with a single predecessor but where a phi has multiple (%s) operands", - phi.operands.size + `Found a block with a single predecessor but where a phi has multiple (${phi.operands.size}) operands`, + null ); const operand = Array.from(phi.operands.values())[0]!; const instr: Instruction = { diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/HIR/ObjectShape.ts b/compiler/forget/packages/babel-plugin-react-forget/src/HIR/ObjectShape.ts index e4db1f6614..c2a87981ec 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/HIR/ObjectShape.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/HIR/ObjectShape.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import invariant from "invariant"; +import { CompilerError } from "../CompilerError"; import { Effect, ValueKind } from "./HIR"; import { BuiltInType, @@ -103,9 +103,10 @@ function addShape( functionType, }; - invariant( + CompilerError.invariant( !registry.has(id), - `[ObjectShape] Could not add shape to registry: name ${id} already exists.` + `[ObjectShape] Could not add shape to registry: name ${id} already exists.`, + null ); registry.set(id, shape); return shape; diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/HIR/PrintHIR.ts b/compiler/forget/packages/babel-plugin-react-forget/src/HIR/PrintHIR.ts index cf5617111f..f0775f7d33 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/HIR/PrintHIR.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/HIR/PrintHIR.ts @@ -6,7 +6,7 @@ */ import generate from "@babel/generator"; -import invariant from "invariant"; +import { CompilerError } from "../CompilerError"; import DisjointSet from "../Utils/DisjointSet"; import { assertExhaustive } from "../Utils/utils"; import { @@ -467,9 +467,10 @@ export function printInstructionValue(instrValue: ReactiveValue): string { } case "TemplateLiteral": { value = "`"; - invariant( + CompilerError.invariant( instrValue.subexprs.length === instrValue.quasis.length - 1, - "Bad assumption about quasi length." + "Bad assumption about quasi length.", + instrValue.loc ); for (let i = 0; i < instrValue.subexprs.length; i++) { value += instrValue.quasis[i].raw; diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/HIR/Types.ts b/compiler/forget/packages/babel-plugin-react-forget/src/HIR/Types.ts index 8d26868bdc..3b8a3c08be 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/HIR/Types.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/HIR/Types.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import invariant from "invariant"; +import { CompilerError } from "../CompilerError"; export type BuiltInType = PrimitiveType | FunctionType | ObjectType; @@ -62,9 +62,10 @@ const opaqueTypeId = Symbol(); export type TypeId = number & { [opaqueTypeId]: "IdentifierId" }; export function makeTypeId(id: number): TypeId { - invariant( + CompilerError.invariant( id >= 0 && Number.isInteger(id), - "Expected instruction id to be a non-negative integer" + "Expected instruction id to be a non-negative integer", + null ); return id as TypeId; } diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/Inference/AnalyseFunctions.ts b/compiler/forget/packages/babel-plugin-react-forget/src/Inference/AnalyseFunctions.ts index c40fc5fee2..974f8053cf 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/Inference/AnalyseFunctions.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/Inference/AnalyseFunctions.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import invariant from "invariant"; +import { CompilerError } from "../CompilerError"; import { Effect, FunctionExpression, @@ -169,9 +169,10 @@ function infer( // In practice this never really matters because the Component function has no // context refs, so it will never have duplicate deps. for (const place of context) { - invariant( + CompilerError.invariant( place.identifier.name !== null, - "context refs should always have a name" + "context refs should always have a name", + place.loc ); const effect = mutations.get(place.identifier.name); diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/Inference/InferMutableLifetimes.ts b/compiler/forget/packages/babel-plugin-react-forget/src/Inference/InferMutableLifetimes.ts index 5e5884be7d..d833479423 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/Inference/InferMutableLifetimes.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/Inference/InferMutableLifetimes.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import invariant from "invariant"; +import { CompilerError } from "../CompilerError"; import { Effect, HIRFunction, @@ -108,9 +108,10 @@ export function inferMutableLifetimes( start = Math.min(start, operand.mutableRange.start); end = Math.max(end, operand.mutableRange.end); } - invariant( + CompilerError.invariant( start !== Number.MAX_SAFE_INTEGER, - "Expected phi to have a start range value" + "Expected phi to have a start range value", + null ); phi.id.mutableRange = { start: makeInstructionId(start), diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/Inference/InferReferenceEffects.ts b/compiler/forget/packages/babel-plugin-react-forget/src/Inference/InferReferenceEffects.ts index adb90428ff..944b898a0e 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/Inference/InferReferenceEffects.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/Inference/InferReferenceEffects.ts @@ -5,7 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -import invariant from "invariant"; import { CompilerError } from "../CompilerError"; import { Environment } from "../HIR"; import { @@ -192,9 +191,10 @@ class InferenceState { * (Re)initializes a @param value with its default @param kind. */ initialize(value: InstructionValue, kind: ValueKind): void { - invariant( + CompilerError.invariant( value.kind !== "LoadLocal", - "Expected all top-level identifiers to be defined as variables, not values" + "Expected all top-level identifiers to be defined as variables, not values", + value.loc ); this.#values.set(value, kind); } @@ -204,11 +204,12 @@ class InferenceState { */ kind(place: Place): ValueKind { const values = this.#variables.get(place.identifier.id); - invariant( + CompilerError.invariant( values != null, `Expected value kind to be initialized at '${printSourceLocation( place.loc - )}'` + )}'`, + place.loc ); let mergedKind: ValueKind | null = null; for (const value of values) { @@ -229,10 +230,10 @@ class InferenceState { */ alias(place: Place, value: Place): void { const values = this.#variables.get(value.identifier.id); - invariant( + CompilerError.invariant( values != null, - "Expected value for identifier `%s` to be initialized.", - value.identifier.id + `Expected value for identifier \`${value.identifier.id}\` to be initialized.`, + value.loc ); this.#variables.set(place.identifier.id, new Set(values)); } @@ -241,9 +242,10 @@ class InferenceState { * Defines (initializing or updating) a variable with a specific kind of value. */ define(place: Place, value: InstructionValue): void { - invariant( + CompilerError.invariant( this.#values.has(value), - `Expected value to be initialized at '${printSourceLocation(value.loc)}'` + `Expected value to be initialized at '${printSourceLocation(value.loc)}'`, + value.loc ); this.#variables.set(place.identifier.id, new Set([value])); } @@ -363,9 +365,10 @@ class InferenceState { break; } case Effect.Unknown: { - invariant( + CompilerError.invariant( false, - "Unexpected unknown effect, expected to infer a precise effect kind" + "Unexpected unknown effect, expected to infer a precise effect kind", + place.loc ); } default: { @@ -375,7 +378,11 @@ class InferenceState { ); } } - invariant(effect !== null, "Expected effect to be set"); + CompilerError.invariant( + effect !== null, + "Expected effect to be set", + place.loc + ); place.effect = effect; } @@ -746,9 +753,10 @@ function inferBlock( continue; } case "MethodCall": { - invariant( + CompilerError.invariant( state.isDefined(instrValue.receiver), - "[InferReferenceEffects] Internal error: receiver of PropertyCall should have been defined by corresponding PropertyLoad" + "[InferReferenceEffects] Internal error: receiver of PropertyCall should have been defined by corresponding PropertyLoad", + instrValue.loc ); state.reference(instrValue.property, Effect.Read); @@ -882,9 +890,10 @@ function inferBlock( const lvalue = instr.lvalue; lvalue.effect = Effect.ConditionallyMutate; const valueKind = state.kind(instrValue.place); - invariant( + CompilerError.invariant( valueKind === ValueKind.Mutable || valueKind === ValueKind.Context, - "[InferReferenceEffects] Context variables are always mutable." + "[InferReferenceEffects] Context variables are always mutable.", + instrValue.loc ); state.initialize(instrValue, valueKind); state.define(lvalue, instrValue); @@ -971,10 +980,10 @@ function inferBlock( } for (const operand of eachInstructionOperand(instr)) { - invariant( + CompilerError.invariant( effectKind != null, - "effectKind must be set for instruction value `%s`", - instrValue.kind + `effectKind must be set for instruction value \`${instrValue.kind}\``, + instrValue.loc ); state.reference(operand, effectKind); } diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/BuildReactiveBlocks.ts b/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/BuildReactiveBlocks.ts index 0727211d72..6296fc60f7 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/BuildReactiveBlocks.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/BuildReactiveBlocks.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import invariant from "invariant"; +import { CompilerError } from "../CompilerError"; import { BlockId, InstructionId, @@ -70,7 +70,11 @@ class Context { this.#builders.push(builder); fn(); const popped = this.#builders.pop(); - invariant(popped === builder, "Expected push/pop to be called 1:1"); + CompilerError.invariant( + popped === builder, + "Expected push/pop to be called 1:1", + null + ); return builder.complete(); } } @@ -90,7 +94,11 @@ class Builder { append(item: ReactiveStatement, label: BlockId | null): void { if (label !== null) { - invariant(item.kind === "terminal", "Only terminals may have a label"); + CompilerError.invariant( + item.kind === "terminal", + "Only terminals may have a label", + null + ); item.label = label; } this.#instructions.push(item); @@ -130,9 +138,10 @@ class Builder { // "Expected all scopes to be closed when exiting a block" // ); const first = this.#stack[0]!; - invariant( + CompilerError.invariant( first.kind === "block", - "Expected first stack item to be a basic block" + "Expected first stack item to be a basic block", + null ); return first.block; } @@ -164,9 +173,10 @@ function visitBlock(context: Context, block: ReactiveBlock): void { break; } case "scope": { - invariant( + CompilerError.invariant( false, - "Expected the function to not have scopes already assigned" + "Expected the function to not have scopes already assigned", + null ); } default: { @@ -182,10 +192,11 @@ function visitBlock(context: Context, block: ReactiveBlock): void { export function getInstructionScope( instr: ReactiveInstruction ): ReactiveScope | null { - invariant( + CompilerError.invariant( instr.lvalue !== null, "Expected lvalues to not be null when assigning scopes. " + - "Pruning lvalues too early can result in missing scope information." + "Pruning lvalues too early can result in missing scope information.", + instr.loc ); for (const operand of eachInstructionLValue(instr)) { const operandScope = getPlaceScope(instr.id, operand); diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/BuildReactiveFunction.ts b/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/BuildReactiveFunction.ts index 41cc146038..ce85b2515f 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/BuildReactiveFunction.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/BuildReactiveFunction.ts @@ -5,7 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -import invariant from "invariant"; import { CompilerError } from "../CompilerError"; import { BasicBlock, @@ -66,9 +65,10 @@ class Driver { } visitBlock(block: BasicBlock, blockValue: ReactiveBlock): void { - invariant( + CompilerError.invariant( !this.cx.emitted.has(block.id), - `Cannot emit the same block twice: bb${block.id}` + `Cannot emit the same block twice: bb${block.id}`, + null ); this.cx.emitted.add(block.id); for (const instruction of block.instructions) { @@ -252,9 +252,10 @@ class Driver { loopBody = this.traverseBlock(this.cx.ir.blocks.get(loopId)!); } else { const break_ = this.visitBreak(terminal.loop, null); - invariant( + CompilerError.invariant( break_ !== null, - "If loop body is already scheduled it must be a break" + "If loop body is already scheduled it must be a break", + null ); loopBody = [break_]; } @@ -308,9 +309,10 @@ class Driver { loopBody = this.traverseBlock(this.cx.ir.blocks.get(loopId)!); } else { const break_ = this.visitBreak(terminal.loop, null); - invariant( + CompilerError.invariant( break_ !== null, - "If loop body is already scheduled it must be a break" + "If loop body is already scheduled it must be a break", + null ); loopBody = [break_]; } @@ -392,9 +394,10 @@ class Driver { loopBody = this.traverseBlock(this.cx.ir.blocks.get(loopId)!); } else { const break_ = this.visitBreak(terminal.loop, null); - invariant( + CompilerError.invariant( break_ !== null, - "If loop body is already scheduled it must be a break" + "If loop body is already scheduled it must be a break", + null ); loopBody = [break_]; } @@ -467,9 +470,10 @@ class Driver { loopBody = this.traverseBlock(this.cx.ir.blocks.get(loopId)!); } else { const break_ = this.visitBreak(terminal.loop, null); - invariant( + CompilerError.invariant( break_ !== null, - "If loop body is already scheduled it must be a break" + "If loop body is already scheduled it must be a break", + null ); loopBody = [break_]; } @@ -626,7 +630,11 @@ class Driver { break; } case "unsupported": { - invariant(false, "Unexpected unsupported terminal"); + CompilerError.invariant( + false, + "Unexpected unsupported terminal", + terminal.loc + ); } default: { assertExhaustive(terminal, "Unexpected terminal"); @@ -654,10 +662,11 @@ class Driver { }; } else if (defaultBlock.instructions.length === 1) { const instr = defaultBlock.instructions[0]!; - invariant( + CompilerError.invariant( instr.lvalue.identifier.id === defaultBlock.terminal.test.identifier.id, - "Expected branch block to end in an instruction that sets the test value" + "Expected branch block to end in an instruction that sets the test value", + instr.lvalue.loc ); return { block: defaultBlock.id, @@ -684,9 +693,10 @@ class Driver { } else if (defaultBlock.terminal.kind === "goto") { const instructions = defaultBlock.instructions; if (instructions.length === 0) { - invariant( + CompilerError.invariant( false, - "Expected goto value block to have at least one instruction" + "Expected goto value block to have at least one instruction", + null ); } else if (defaultBlock.instructions.length === 1) { const instr = defaultBlock.instructions[0]!; @@ -782,10 +792,10 @@ class Driver { case "optional": { const test = this.visitValueBlock(terminal.test, terminal.loc); const testBlock = this.cx.ir.blocks.get(test.block)!; - invariant( + CompilerError.invariant( testBlock.terminal.kind === "branch", - "Unexpected terminal kind '%s' for optional call test block", - testBlock.terminal.kind + `Unexpected terminal kind '${testBlock.terminal.kind}' for optional call test block`, + testBlock.terminal.loc ); const consequent = this.visitValueBlock( testBlock.terminal.consequent, @@ -821,10 +831,10 @@ class Driver { case "logical": { const test = this.visitValueBlock(terminal.test, terminal.loc); const testBlock = this.cx.ir.blocks.get(test.block)!; - invariant( + CompilerError.invariant( testBlock.terminal.kind === "branch", - "Unexpected terminal kind '%s' for logical test block", - testBlock.terminal.kind + `Unexpected terminal kind '${testBlock.terminal.kind}' for logical test block`, + testBlock.terminal.loc ); const leftFinal = this.visitValueBlock( @@ -866,10 +876,10 @@ class Driver { case "ternary": { const test = this.visitValueBlock(terminal.test, terminal.loc); const testBlock = this.cx.ir.blocks.get(test.block)!; - invariant( + CompilerError.invariant( testBlock.terminal.kind === "branch", - "Unexpected terminal kind '%s' for ternary test block", - testBlock.terminal.kind + `Unexpected terminal kind '${testBlock.terminal.kind}' for ternary test block`, + testBlock.terminal.loc ); const consequent = this.visitValueBlock( testBlock.terminal.consequent, @@ -895,10 +905,10 @@ class Driver { }; } default: { - invariant( + CompilerError.invariant( false, - "Unexpected value block terminal kind '%s'", - terminal.kind + `Unexpected value block terminal kind '${terminal.kind}'`, + terminal.loc ); } } @@ -914,7 +924,7 @@ class Driver { ): ReactiveTerminalStatement { const target = this.cx.getBreakTarget(block); if (target === null) { - invariant(false, "Expected a break target"); + CompilerError.invariant(false, "Expected a break target", null); } switch (target.type) { case "implicit": { @@ -952,9 +962,10 @@ class Driver { id: InstructionId ): ReactiveTerminalStatement { const target = this.cx.getContinueTarget(block); - invariant( + CompilerError.invariant( target !== null, - `Expected continue target to be scheduled for bb${block}` + `Expected continue target to be scheduled for bb${block}`, + null ); switch (target.type) { case "implicit": { @@ -1035,9 +1046,10 @@ class Context { */ schedule(block: BlockId, type: "if" | "switch" | "case"): number { const id = this.#nextScheduleId++; - invariant( + CompilerError.invariant( !this.#scheduled.has(block), - `Break block is already scheduled: bb${block}` + `Break block is already scheduled: bb${block}`, + null ); this.#scheduled.add(block); this.#controlFlowStack.push({ block, id, type }); @@ -1052,9 +1064,10 @@ class Context { const id = this.#nextScheduleId++; const ownsBlock = !this.#scheduled.has(fallthroughBlock); this.#scheduled.add(fallthroughBlock); - invariant( + CompilerError.invariant( !this.#scheduled.has(continueBlock), - `Continue block is already scheduled: bb${continueBlock}` + `Continue block is already scheduled: bb${continueBlock}`, + null ); this.#scheduled.add(continueBlock); let ownsLoop = false; @@ -1080,9 +1093,10 @@ class Context { */ unschedule(scheduleId: number): void { const last = this.#controlFlowStack.pop(); - invariant( + CompilerError.invariant( last !== undefined && last.id === scheduleId, - "Can only unschedule the last target" + "Can only unschedule the last target", + null ); if (last.type !== "loop" || last.ownsBlock !== null) { this.#scheduled.delete(last.block); diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts b/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts index ecd9fce018..f5488e2f18 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts @@ -6,7 +6,6 @@ */ import * as t from "@babel/types"; -import invariant from "invariant"; import { pruneUnusedLValues, pruneUnusedLabels, renameVariables } from "."; import { CompilerError, ErrorSeverity } from "../CompilerError"; import { Environment } from "../HIR"; @@ -216,10 +215,10 @@ function codegenReactiveScope( firstOutputIndex = index; } - invariant( + CompilerError.invariant( identifier.name != null, - "Expected identifier '@%s' to be named", - identifier.id + `Expected identifier '@${identifier.id}' to be named`, + null ); const name = convertIdentifier(identifier); @@ -284,10 +283,10 @@ function codegenReactiveScope( null as t.Expression | null ); if (testCondition === null) { - invariant( + CompilerError.invariant( firstOutputIndex !== null, - "Expected scope '@%s' to have at least one declaration", - scope.id + `Expected scope '@${scope.id}' to have at least one declaration`, + null ); testCondition = t.binaryExpression( "===", @@ -542,7 +541,11 @@ function codegenInstructionNullable( ]); } case InstructionKind.Reassign: { - invariant(value !== null, "Expected a value for reassignment"); + CompilerError.invariant( + value !== null, + "Expected a value for reassignment", + instr.value.loc + ); const expr = t.assignmentExpression("=", codegenLValue(lvalue), value); if (instr.lvalue !== null) { if (instr.value.kind !== "StoreContext") { @@ -589,9 +592,10 @@ function codegenForInit( })) ).body; const declaration = body[0]!; - invariant( + CompilerError.invariant( declaration.type === "VariableDeclaration", - "Expected a variable declaration" + "Expected a variable declaration", + declaration.loc ?? null ); return declaration; } else { @@ -740,9 +744,10 @@ function codegenInstructionValue( switch (optionalValue.type) { case "OptionalCallExpression": case "CallExpression": { - invariant( + CompilerError.invariant( t.isExpression(optionalValue.callee), - "v8 intrinsics are validated during lowering" + "v8 intrinsics are validated during lowering", + optionalValue.callee.loc ?? null ); value = t.optionalCallExpression( optionalValue.callee, @@ -754,9 +759,10 @@ function codegenInstructionValue( case "OptionalMemberExpression": case "MemberExpression": { const property = optionalValue.property; - invariant( + CompilerError.invariant( t.isExpression(property), - "Private names are validated during lowering" + "Private names are validated during lowering", + property.loc ?? null ); value = t.optionalMemberExpression( optionalValue.object, @@ -779,19 +785,21 @@ function codegenInstructionValue( } case "MethodCall": { const memberExpr = codegenPlace(cx, instrValue.property); - invariant( + CompilerError.invariant( t.isMemberExpression(memberExpr) || t.isOptionalMemberExpression(memberExpr), "[Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression. " + - `Got a '${memberExpr.type}'` + `Got a '${memberExpr.type}'`, + memberExpr.loc ?? null ); - invariant( + CompilerError.invariant( t.isNodesEquivalent( memberExpr.object, codegenPlace(cx, instrValue.receiver) ), "[Codegen] Internal error: Forget should always generate MethodCall::property " + - "as a MemberExpression of MethodCall::receiver" + "as a MemberExpression of MethodCall::receiver", + memberExpr.loc ?? null ); const args = instrValue.args.map((arg) => codegenArgument(cx, arg)); value = createCallExpression(instrValue.loc, memberExpr, args); @@ -843,10 +851,10 @@ function codegenInstructionValue( } else if (tagValue.type === "MemberExpression") { tag = convertMemberExpressionToJsx(tagValue); } else { - invariant( + CompilerError.invariant( tagValue.type === "StringLiteral", - "Expected JSX tag to be an identifier or string, got '%s'", - tagValue.type + `Expected JSX tag to be an identifier or string, got '${tagValue.type}'`, + tagValue.loc ?? null ); if (tagValue.value.indexOf(":") >= 0) { const [namespace, name] = tagValue.value.split(":", 2); @@ -1185,17 +1193,19 @@ function codegenJsxElement( function convertMemberExpressionToJsx( expr: t.MemberExpression ): t.JSXMemberExpression { - invariant( + CompilerError.invariant( expr.property.type === "Identifier", - "Expected JSX member expression property to be a string" + "Expected JSX member expression property to be a string", + expr.loc ?? null ); const property = t.jsxIdentifier(expr.property.name); if (expr.object.type === "Identifier") { return t.jsxMemberExpression(t.jsxIdentifier(expr.object.name), property); } else { - invariant( + CompilerError.invariant( expr.object.type === "MemberExpression", - "Expected JSX member expression to be an identifier or nested member expression" + "Expected JSX member expression to be an identifier or nested member expression", + expr.object.loc ?? null ); const object = convertMemberExpressionToJsx(expr.object); return t.jsxMemberExpression(object, property); diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/DeriveMinimalDependencies.ts b/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/DeriveMinimalDependencies.ts index 61e586a65a..e3d572fccb 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/DeriveMinimalDependencies.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/DeriveMinimalDependencies.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import invariant from "invariant"; +import { CompilerError } from "../CompilerError"; import { Identifier, ReactiveScopeDependency } from "../HIR"; import { printIdentifier } from "../HIR/PrintHIR"; import { assertExhaustive } from "../Utils/utils"; @@ -122,11 +122,12 @@ export class ReactiveScopeDependencyTree { const results = new Set(); for (const [rootId, rootNode] of this.#roots.entries()) { const deps = deriveMinimalDependenciesInSubtree(rootNode); - invariant( + CompilerError.invariant( deps.every( (dep) => dep.accessType === PropertyAccessType.UnconditionalDependency ), - "[PropagateScopeDependencies] All dependencies must be reduced to unconditional dependencies." + "[PropagateScopeDependencies] All dependencies must be reduced to unconditional dependencies.", + null ); for (const dep of deps) { @@ -162,9 +163,10 @@ export class ReactiveScopeDependencyTree { promoteDepsFromExhaustiveConditionals( trees: Array ): void { - invariant( + CompilerError.invariant( trees.length > 1, - "Expected trees to be at least 2 elements long." + "Expected trees to be at least 2 elements long.", + null ); for (const [id, root] of this.#roots) { @@ -456,16 +458,18 @@ function addSubtreeIntersection( otherProperties: Array>, currProperties: Map ): void { - invariant( + CompilerError.invariant( otherProperties.length > 1, - "[DeriveMinimalDependencies] Expected otherProperties to be at least 2 elements long." + "[DeriveMinimalDependencies] Expected otherProperties to be at least 2 elements long.", + null ); otherProperties.forEach((properties) => properties.forEach((node, _) => - invariant( + CompilerError.invariant( !isUnconditional(node.accessType), - "[DeriveMinimalDependencies] Expected otherProperties to only contain unconditional nodes!" + "[DeriveMinimalDependencies] Expected otherProperties to only contain unconditional nodes!", + null ) ) ); diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/PrintReactiveFunction.ts b/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/PrintReactiveFunction.ts index d230e7905e..ad8925953d 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/PrintReactiveFunction.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/PrintReactiveFunction.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import invariant from "invariant"; +import { CompilerError } from "../CompilerError"; import { ReactiveFunction, ReactiveScopeBlock, @@ -226,7 +226,11 @@ function printTerminal(writer: Writer, terminal: ReactiveTerminal): void { writer.writeLine(`${prefix}: {`); writer.indented(() => { const block = case_.block; - invariant(block != null, "Expected case to have a block"); + CompilerError.invariant( + block != null, + "Expected case to have a block", + case_.test?.loc ?? null + ); printReactiveInstructions(writer, block); }); writer.writeLine("}"); diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/PruneNonEscapingScopes.ts b/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/PruneNonEscapingScopes.ts index c00ef919c2..be72ed0192 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/PruneNonEscapingScopes.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/PruneNonEscapingScopes.ts @@ -5,7 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -import invariant from "invariant"; import prettyFormat from "pretty-format"; import { CompilerError } from "../CompilerError"; import { @@ -244,9 +243,10 @@ class State { this.scopes.set(scope.id, node); } const identifierNode = this.identifiers.get(identifier); - invariant( + CompilerError.invariant( identifierNode !== undefined, - "Expected identifier to be initialized" + "Expected identifier to be initialized", + place.loc ); identifierNode.scopes.add(scope.id); } @@ -264,9 +264,10 @@ function computeMemoizedIdentifiers(state: State): Set { // Visit an identifier, optionally forcing it to be memoized function visit(id: IdentifierId, forceMemoize: boolean = false): boolean { const node = state.identifiers.get(id); - invariant( + CompilerError.invariant( node !== undefined, - `Expected a node for all identifiers, none found for '${id}'` + `Expected a node for all identifiers, none found for '${id}'`, + null ); if (node.seen) { return node.memoized; @@ -302,7 +303,11 @@ function computeMemoizedIdentifiers(state: State): Set { // Force all the scope's optionally-memoizeable dependencies (not "Never") to be memoized function forceMemoizeScopeDependencies(id: ScopeId): void { const node = state.scopes.get(id); - invariant(node !== undefined, "Expected a node for all scopes"); + CompilerError.invariant( + node !== undefined, + "Expected a node for all scopes", + null + ); if (node.seen) { return; } diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/RenameVariables.ts b/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/RenameVariables.ts index f0766a6bb1..c39856fdea 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/RenameVariables.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/RenameVariables.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import invariant from "invariant"; +import { CompilerError } from "../CompilerError"; import { Identifier, IdentifierId, @@ -103,6 +103,6 @@ class Scopes { this.#stack.push(next); fn(); const last = this.#stack.pop(); - invariant(last === next, "Mismatch push/pop calls"); + CompilerError.invariant(last === next, "Mismatch push/pop calls", null); } } diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/SSA/EliminateRedundantPhi.ts b/compiler/forget/packages/babel-plugin-react-forget/src/SSA/EliminateRedundantPhi.ts index fc5c969c1e..54e6557814 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/SSA/EliminateRedundantPhi.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/SSA/EliminateRedundantPhi.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import invariant from "invariant"; +import { CompilerError } from "../CompilerError"; import { BlockId, HIRFunction, Identifier, Place } from "../HIR/HIR"; import { eachInstructionLValue, @@ -83,7 +83,11 @@ export function eliminateRedundantPhi(fn: HIRFunction): void { same = operand; } } - invariant(same !== null, "Expected phis to be non-empty"); + CompilerError.invariant( + same !== null, + "Expected phis to be non-empty", + null + ); rewrites.set(phi.id, same); block.phis.delete(phi); } diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/SSA/EnterSSA.ts b/compiler/forget/packages/babel-plugin-react-forget/src/SSA/EnterSSA.ts index 3956980835..04c8225a43 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/SSA/EnterSSA.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/SSA/EnterSSA.ts @@ -5,7 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -import invariant from "invariant"; import { CompilerError } from "../CompilerError"; import { Environment } from "../HIR/Environment"; import { @@ -68,9 +67,10 @@ class SSABuilder { } state(): State { - invariant( + CompilerError.invariant( this.#current !== null, - "we need to be in a block to access state!" + "we need to be in a block to access state!", + null ); return this.#states.get(this.#current)!; } @@ -237,9 +237,10 @@ function enterSSAImpl( ): void { const visitedBlocks: Set = new Set(); for (const [blockId, block] of func.body.blocks) { - invariant( + CompilerError.invariant( !visitedBlocks.has(block), - `found a cycle! visiting bb${block.id} again` + `found a cycle! visiting bb${block.id} again`, + null ); visitedBlocks.add(block); @@ -269,9 +270,10 @@ function enterSSAImpl( ) { const loweredFunc = instr.value.loweredFunc; const entry = loweredFunc.body.blocks.get(loweredFunc.body.entry)!; - invariant( + CompilerError.invariant( entry.preds.size === 0, - "Expected function expression entry block to have zero predecessors" + "Expected function expression entry block to have zero predecessors", + null ); entry.preds.add(blockId); builder.defineFunction(loweredFunc); diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/SSA/LeaveSSA.ts b/compiler/forget/packages/babel-plugin-react-forget/src/SSA/LeaveSSA.ts index f4b81e1f06..b65a757fc0 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/SSA/LeaveSSA.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/SSA/LeaveSSA.ts @@ -5,7 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -import invariant from "invariant"; import { CompilerError } from "../CompilerError"; import { BasicBlock, @@ -220,7 +219,11 @@ export function leaveSSA(fn: HIRFunction): void { } } } - invariant(kind !== null, "Expected at least one operand"); + CompilerError.invariant( + kind !== null, + "Expected at least one operand", + null + ); value.lvalue.kind = kind; } rewritePlace(lvalue, rewrites, declarations); @@ -353,9 +356,10 @@ export function leaveSSA(fn: HIRFunction): void { // If we never saw a declaration for this phi, it may have been pruned by DCE, so synthesize // a new Let binding - invariant( + CompilerError.invariant( phi.id.name != null, - "Expected reassignment phis to have a name" + "Expected reassignment phis to have a name", + null ); const declaration = declarations.get(phi.id.name); if (declaration === undefined) { diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/TypeInference/InferTypes.ts b/compiler/forget/packages/babel-plugin-react-forget/src/TypeInference/InferTypes.ts index 978cfba043..3b53736d26 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/TypeInference/InferTypes.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/TypeInference/InferTypes.ts @@ -6,7 +6,7 @@ */ import * as t from "@babel/types"; -import invariant from "invariant"; +import { CompilerError } from "../CompilerError"; import { Environment } from "../HIR"; import { HIRFunction, @@ -342,7 +342,11 @@ class Unifier { if (type.kind === "Phi") { const operands = new Set(type.operands.map((i) => this.get(i).kind)); - invariant(operands.size > 0, "there should be at least one operand"); + CompilerError.invariant( + operands.size > 0, + "there should be at least one operand", + null + ); const kind = operands.values().next().value; // there's only one unique type and it's not a type var diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/Utils/DisjointSet.ts b/compiler/forget/packages/babel-plugin-react-forget/src/Utils/DisjointSet.ts index 00d5506de5..1da35d460b 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/Utils/DisjointSet.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/Utils/DisjointSet.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import invariant from "invariant"; +import { CompilerError } from "../CompilerError"; /** * Represents items which form disjoint sets. @@ -20,7 +20,11 @@ export default class DisjointSet { */ union(items: Array): void { const first = items.shift(); - invariant(first != null, "Expected set to be non-empty"); + CompilerError.invariant( + first != null, + "Expected set to be non-empty", + null + ); // determine an arbitrary "root" for this set: if the first // item already has a root then use that, otherwise the first item // will be the new root. diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo.destructure-assignment-to-context-var.expect.md b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo.destructure-assignment-to-context-var.expect.md index 86a7bd262a..12382c805e 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo.destructure-assignment-to-context-var.expect.md +++ b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo.destructure-assignment-to-context-var.expect.md @@ -18,7 +18,7 @@ function useFoo(props) { ## Error ``` -[InferReferenceEffects] Context variables are always mutable. +[ReactForget] Invariant: [InferReferenceEffects] Context variables are always mutable. (5:5) ``` \ No newline at end of file