[compiler] Migrate CompilerError.invariant to new CompilerDiagnostic infra (#34403)

Mechanical PR to migrate existing invariants to use the new
CompilerDiagnostic infra @josephsavona added. Will tackle the others at
a later time.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34403).
* #34409
* #34404
* __->__ #34403
This commit is contained in:
lauren 2025-09-06 12:58:08 -04:00 committed by GitHub
parent 1fef581e1a
commit 474f25842a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
84 changed files with 1974 additions and 338 deletions

View File

@ -37,7 +37,7 @@ export enum ErrorSeverity {
export type CompilerDiagnosticOptions = { export type CompilerDiagnosticOptions = {
category: ErrorCategory; category: ErrorCategory;
reason: string; reason: string;
description: string; description: string | null;
details: Array<CompilerDiagnosticDetail>; details: Array<CompilerDiagnosticDetail>;
suggestions?: Array<CompilerSuggestion> | null | undefined; suggestions?: Array<CompilerSuggestion> | null | undefined;
}; };
@ -49,7 +49,7 @@ export type CompilerDiagnosticDetail =
| { | {
kind: 'error'; kind: 'error';
loc: SourceLocation | null; loc: SourceLocation | null;
message: string; message: string | null;
} }
| { | {
kind: 'hint'; kind: 'hint';
@ -126,8 +126,8 @@ export class CompilerDiagnostic {
return this.options.category; return this.options.category;
} }
withDetail(detail: CompilerDiagnosticDetail): CompilerDiagnostic { withDetails(...details: Array<CompilerDiagnosticDetail>): CompilerDiagnostic {
this.options.details.push(detail); this.options.details.push(...details);
return this; return this;
} }
@ -155,9 +155,9 @@ export class CompilerDiagnostic {
} }
let codeFrame: string; let codeFrame: string;
try { try {
codeFrame = printCodeFrame(source, loc, detail.message); codeFrame = printCodeFrame(source, loc, detail.message ?? '');
} catch (e) { } catch (e) {
codeFrame = detail.message; codeFrame = detail.message ?? '';
} }
buffer.push('\n\n'); buffer.push('\n\n');
if (loc.filename != null) { if (loc.filename != null) {
@ -284,15 +284,16 @@ export class CompilerError extends Error {
static invariant( static invariant(
condition: unknown, condition: unknown,
options: Omit<CompilerErrorDetailOptions, 'category'>, options: Omit<CompilerDiagnosticOptions, 'category'>,
): asserts condition { ): asserts condition {
if (!condition) { if (!condition) {
const errors = new CompilerError(); const errors = new CompilerError();
errors.pushErrorDetail( errors.pushDiagnostic(
new CompilerErrorDetail({ CompilerDiagnostic.create({
...options, reason: options.reason,
description: options.description,
category: ErrorCategory.Invariant, category: ErrorCategory.Invariant,
}), }).withDetails(...options.details),
); );
throw errors; throw errors;
} }

View File

@ -51,12 +51,26 @@ function insertAdditionalFunctionDeclaration(
CompilerError.invariant(originalFnName != null && compiled.id != null, { CompilerError.invariant(originalFnName != null && compiled.id != null, {
reason: reason:
'Expected function declarations that are referenced elsewhere to have a named identifier', 'Expected function declarations that are referenced elsewhere to have a named identifier',
loc: fnPath.node.loc ?? null, description: null,
details: [
{
kind: 'error',
loc: fnPath.node.loc ?? null,
message: null,
},
],
}); });
CompilerError.invariant(originalFnParams.length === compiledParams.length, { CompilerError.invariant(originalFnParams.length === compiledParams.length, {
reason: reason:
'Expected React Compiler optimized function declarations to have the same number of parameters as source', 'Expected React Compiler optimized function declarations to have the same number of parameters as source',
loc: fnPath.node.loc ?? null, description: null,
details: [
{
kind: 'error',
loc: fnPath.node.loc ?? null,
message: null,
},
],
}); });
const gatingCondition = t.identifier( const gatingCondition = t.identifier(
@ -140,7 +154,13 @@ export function insertGatedFunctionDeclaration(
CompilerError.invariant(compiled.type === 'FunctionDeclaration', { CompilerError.invariant(compiled.type === 'FunctionDeclaration', {
reason: 'Expected compiled node type to match input type', reason: 'Expected compiled node type to match input type',
description: `Got ${compiled.type} but expected FunctionDeclaration`, description: `Got ${compiled.type} but expected FunctionDeclaration`,
loc: fnPath.node.loc ?? null, details: [
{
kind: 'error',
loc: fnPath.node.loc ?? null,
message: null,
},
],
}); });
insertAdditionalFunctionDeclaration( insertAdditionalFunctionDeclaration(
fnPath, fnPath,

View File

@ -257,7 +257,13 @@ export function addImportsToProgram(
reason: reason:
'Encountered conflicting import specifiers in generated program', 'Encountered conflicting import specifiers in generated program',
description: `Conflict from import ${loweredImport.module}:(${loweredImport.imported} as ${loweredImport.name}).`, description: `Conflict from import ${loweredImport.module}:(${loweredImport.imported} as ${loweredImport.name}).`,
loc: GeneratedSource, details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
suggestions: null, suggestions: null,
}, },
); );
@ -268,7 +274,13 @@ export function addImportsToProgram(
reason: reason:
'Found inconsistent import specifier. This is an internal bug.', 'Found inconsistent import specifier. This is an internal bug.',
description: `Expected import ${moduleName}:${specifierName} but found ${loweredImport.module}:${loweredImport.imported}`, description: `Expected import ${moduleName}:${specifierName} but found ${loweredImport.module}:${loweredImport.imported}`,
loc: GeneratedSource, details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
}, },
); );
} }

View File

@ -310,7 +310,13 @@ function insertNewOutlinedFunctionNode(
CompilerError.invariant(insertedFuncDecl.isFunctionDeclaration(), { CompilerError.invariant(insertedFuncDecl.isFunctionDeclaration(), {
reason: 'Expected inserted function declaration', reason: 'Expected inserted function declaration',
description: `Got: ${insertedFuncDecl}`, description: `Got: ${insertedFuncDecl}`,
loc: insertedFuncDecl.node?.loc ?? null, details: [
{
kind: 'error',
loc: insertedFuncDecl.node?.loc ?? null,
message: null,
},
],
}); });
return insertedFuncDecl; return insertedFuncDecl;
} }
@ -419,7 +425,14 @@ export function compileProgram(
for (const outlined of compiled.outlined) { for (const outlined of compiled.outlined) {
CompilerError.invariant(outlined.fn.outlined.length === 0, { CompilerError.invariant(outlined.fn.outlined.length === 0, {
reason: 'Unexpected nested outlined functions', reason: 'Unexpected nested outlined functions',
loc: outlined.fn.loc, description: null,
details: [
{
kind: 'error',
loc: outlined.fn.loc,
message: null,
},
],
}); });
const fn = insertNewOutlinedFunctionNode( const fn = insertNewOutlinedFunctionNode(
program, program,
@ -1407,7 +1420,13 @@ export function getReactCompilerRuntimeModule(
{ {
reason: 'Expected target to already be validated', reason: 'Expected target to already be validated',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}, },
); );

View File

@ -152,7 +152,14 @@ export function suppressionsToCompilerError(
): CompilerError { ): CompilerError {
CompilerError.invariant(suppressionRanges.length !== 0, { CompilerError.invariant(suppressionRanges.length !== 0, {
reason: `Expected at least suppression comment source range`, reason: `Expected at least suppression comment source range`,
loc: GeneratedSource, description: null,
details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
}); });
const error = new CompilerError(); const error = new CompilerError();
for (const suppressionRange of suppressionRanges) { for (const suppressionRange of suppressionRanges) {
@ -196,7 +203,7 @@ export function suppressionsToCompilerError(
op: CompilerSuggestionOperation.Remove, op: CompilerSuggestionOperation.Remove,
}, },
], ],
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: suppressionRange.disableComment.loc ?? null, loc: suppressionRange.disableComment.loc ?? null,
message: 'Found React rule suppression', message: 'Found React rule suppression',

View File

@ -217,7 +217,14 @@ function validateImportSpecifier(
const binding = local.scope.getBinding(local.node.name); const binding = local.scope.getBinding(local.node.name);
CompilerError.invariant(binding != null, { CompilerError.invariant(binding != null, {
reason: 'Expected binding to be found for import specifier', reason: 'Expected binding to be found for import specifier',
loc: local.node.loc ?? null, description: null,
details: [
{
kind: 'error',
loc: local.node.loc ?? null,
message: null,
},
],
}); });
checkFn(binding.referencePaths, state); checkFn(binding.referencePaths, state);
} }
@ -237,7 +244,14 @@ function validateNamespacedImport(
CompilerError.invariant(binding != null, { CompilerError.invariant(binding != null, {
reason: 'Expected binding to be found for import specifier', reason: 'Expected binding to be found for import specifier',
loc: local.node.loc ?? null, description: null,
details: [
{
kind: 'error',
loc: local.node.loc ?? null,
message: null,
},
],
}); });
const filteredReferences = new Map< const filteredReferences = new Map<
CheckInvalidReferenceFn, CheckInvalidReferenceFn,

View File

@ -46,7 +46,14 @@ export function raiseUnificationErrors(
if (errs.length === 0) { if (errs.length === 0) {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: 'Should not have array of zero errors', reason: 'Should not have array of zero errors',
loc, description: null,
details: [
{
kind: 'error',
loc,
message: null,
},
],
}); });
} else if (errs.length === 1) { } else if (errs.length === 1) {
CompilerError.throwInvalidJS({ CompilerError.throwInvalidJS({

View File

@ -152,7 +152,13 @@ export function makeLinearId(id: number): LinearId {
CompilerError.invariant(id >= 0 && Number.isInteger(id), { CompilerError.invariant(id >= 0 && Number.isInteger(id), {
reason: 'Expected LinearId id to be a non-negative integer', reason: 'Expected LinearId id to be a non-negative integer',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
return id as LinearId; return id as LinearId;
@ -167,7 +173,13 @@ export function makeTypeParameterId(id: number): TypeParameterId {
CompilerError.invariant(id >= 0 && Number.isInteger(id), { CompilerError.invariant(id >= 0 && Number.isInteger(id), {
reason: 'Expected TypeParameterId to be a non-negative integer', reason: 'Expected TypeParameterId to be a non-negative integer',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
return id as TypeParameterId; return id as TypeParameterId;
@ -191,7 +203,13 @@ export function makeVariableId(id: number): VariableId {
CompilerError.invariant(id >= 0 && Number.isInteger(id), { CompilerError.invariant(id >= 0 && Number.isInteger(id), {
reason: 'Expected VariableId id to be a non-negative integer', reason: 'Expected VariableId id to be a non-negative integer',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
return id as VariableId; return id as VariableId;
@ -399,7 +417,14 @@ function convertFlowType(flowType: FlowType, loc: string): ResolvedType {
} else { } else {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Unsupported property kind ${prop.kind}`, reason: `Unsupported property kind ${prop.kind}`,
loc: GeneratedSource, description: null,
details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
}); });
} }
} }
@ -468,7 +493,14 @@ function convertFlowType(flowType: FlowType, loc: string): ResolvedType {
} else { } else {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Unsupported property kind ${prop.kind}`, reason: `Unsupported property kind ${prop.kind}`,
loc: GeneratedSource, description: null,
details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
}); });
} }
} }
@ -487,7 +519,14 @@ function convertFlowType(flowType: FlowType, loc: string): ResolvedType {
} else { } else {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Unsupported property kind ${prop.kind}`, reason: `Unsupported property kind ${prop.kind}`,
loc: GeneratedSource, description: null,
details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
}); });
} }
} }
@ -500,7 +539,14 @@ function convertFlowType(flowType: FlowType, loc: string): ResolvedType {
} }
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Unsupported class instance type ${flowType.def.type.kind}`, reason: `Unsupported class instance type ${flowType.def.type.kind}`,
loc: GeneratedSource, description: null,
details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
}); });
} }
case 'Fun': case 'Fun':
@ -559,7 +605,14 @@ function convertFlowType(flowType: FlowType, loc: string): ResolvedType {
} else { } else {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Unsupported component props type ${propsType.type.kind}`, reason: `Unsupported component props type ${propsType.type.kind}`,
loc: GeneratedSource, description: null,
details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
}); });
} }
@ -712,7 +765,14 @@ export class FlowTypeEnv implements ITypeEnv {
// TODO: use flow-js only for web environments (e.g. playground) // TODO: use flow-js only for web environments (e.g. playground)
CompilerError.invariant(env.config.flowTypeProvider != null, { CompilerError.invariant(env.config.flowTypeProvider != null, {
reason: 'Expected flowDumpTypes to be defined in environment config', reason: 'Expected flowDumpTypes to be defined in environment config',
loc: GeneratedSource, description: null,
details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
}); });
let stdout: any; let stdout: any;
if (source === lastFlowSource) { if (source === lastFlowSource) {

View File

@ -38,7 +38,13 @@ export function assertConsistentIdentifiers(fn: HIRFunction): void {
CompilerError.invariant(instr.lvalue.identifier.name === null, { CompilerError.invariant(instr.lvalue.identifier.name === null, {
reason: `Expected all lvalues to be temporaries`, reason: `Expected all lvalues to be temporaries`,
description: `Found named lvalue \`${instr.lvalue.identifier.name}\``, description: `Found named lvalue \`${instr.lvalue.identifier.name}\``,
loc: instr.lvalue.loc, details: [
{
kind: 'error',
loc: instr.lvalue.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
CompilerError.invariant(!assignments.has(instr.lvalue.identifier.id), { CompilerError.invariant(!assignments.has(instr.lvalue.identifier.id), {
@ -46,7 +52,13 @@ export function assertConsistentIdentifiers(fn: HIRFunction): void {
description: `Found duplicate assignment of '${printPlace( description: `Found duplicate assignment of '${printPlace(
instr.lvalue, instr.lvalue,
)}'`, )}'`,
loc: instr.lvalue.loc, details: [
{
kind: 'error',
loc: instr.lvalue.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
assignments.add(instr.lvalue.identifier.id); assignments.add(instr.lvalue.identifier.id);
@ -77,7 +89,13 @@ function validate(
CompilerError.invariant(identifier === previous, { CompilerError.invariant(identifier === previous, {
reason: `Duplicate identifier object`, reason: `Duplicate identifier object`,
description: `Found duplicate identifier object for id ${identifier.id}`, description: `Found duplicate identifier object for id ${identifier.id}`,
loc: loc ?? GeneratedSource, details: [
{
kind: 'error',
loc: loc ?? GeneratedSource,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} }

View File

@ -18,7 +18,13 @@ export function assertTerminalSuccessorsExist(fn: HIRFunction): void {
description: `Block bb${successor} does not exist for terminal '${printTerminal( description: `Block bb${successor} does not exist for terminal '${printTerminal(
block.terminal, block.terminal,
)}'`, )}'`,
loc: (block.terminal as any).loc ?? GeneratedSource, details: [
{
kind: 'error',
loc: (block.terminal as any).loc ?? GeneratedSource,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
return successor; return successor;
@ -33,14 +39,26 @@ export function assertTerminalPredsExist(fn: HIRFunction): void {
CompilerError.invariant(predBlock != null, { CompilerError.invariant(predBlock != null, {
reason: 'Expected predecessor block to exist', reason: 'Expected predecessor block to exist',
description: `Block ${block.id} references non-existent ${pred}`, description: `Block ${block.id} references non-existent ${pred}`,
loc: GeneratedSource, details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
}); });
CompilerError.invariant( CompilerError.invariant(
[...eachTerminalSuccessor(predBlock.terminal)].includes(block.id), [...eachTerminalSuccessor(predBlock.terminal)].includes(block.id),
{ {
reason: 'Terminal successor does not reference correct predecessor', reason: 'Terminal successor does not reference correct predecessor',
description: `Block bb${block.id} has bb${predBlock.id} as a predecessor, but bb${predBlock.id}'s successors do not include bb${block.id}`, description: `Block bb${block.id} has bb${predBlock.id} as a predecessor, but bb${predBlock.id}'s successors do not include bb${block.id}`,
loc: GeneratedSource, details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
}, },
); );
} }

View File

@ -131,7 +131,13 @@ export function recursivelyTraverseItems<T, TContext>(
CompilerError.invariant(disjoint || nested, { CompilerError.invariant(disjoint || nested, {
reason: 'Invalid nesting in program blocks or scopes', reason: 'Invalid nesting in program blocks or scopes',
description: `Items overlap but are not nested: ${maybeParentRange.start}:${maybeParentRange.end}(${currRange.start}:${currRange.end})`, description: `Items overlap but are not nested: ${maybeParentRange.start}:${maybeParentRange.end}(${currRange.start}:${currRange.end})`,
loc: GeneratedSource, details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
}); });
if (disjoint) { if (disjoint) {
exit(maybeParent, context); exit(maybeParent, context);

View File

@ -57,7 +57,13 @@ function validateMutableRange(
{ {
reason: `Invalid mutable range: [${range.start}:${range.end}]`, reason: `Invalid mutable range: [${range.start}:${range.end}]`,
description: `${printPlace(place)} in ${description}`, description: `${printPlace(place)} in ${description}`,
loc: place.loc, details: [
{
kind: 'error',
loc: place.loc,
message: null,
},
],
}, },
); );
} }

View File

@ -110,7 +110,7 @@ export function lower(
category: ErrorCategory.Invariant, category: ErrorCategory.Invariant,
reason: 'Could not find binding', reason: 'Could not find binding',
description: `[BuildHIR] Could not find binding for param \`${param.node.name}\`.`, description: `[BuildHIR] Could not find binding for param \`${param.node.name}\`.`,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: param.node.loc ?? null, loc: param.node.loc ?? null,
message: 'Could not find binding', message: 'Could not find binding',
@ -174,7 +174,7 @@ export function lower(
category: ErrorCategory.Todo, category: ErrorCategory.Todo,
reason: `Handle ${param.node.type} parameters`, reason: `Handle ${param.node.type} parameters`,
description: `[BuildHIR] Add support for ${param.node.type} parameters.`, description: `[BuildHIR] Add support for ${param.node.type} parameters.`,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: param.node.loc ?? null, loc: param.node.loc ?? null,
message: 'Unsupported parameter type', message: 'Unsupported parameter type',
@ -205,7 +205,7 @@ export function lower(
category: ErrorCategory.Syntax, category: ErrorCategory.Syntax,
reason: `Unexpected function body kind`, reason: `Unexpected function body kind`,
description: `Expected function body to be an expression or a block statement, got \`${body.type}\`.`, description: `Expected function body to be an expression or a block statement, got \`${body.type}\`.`,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: body.node.loc ?? null, loc: body.node.loc ?? null,
message: 'Expected a block statement or expression', message: 'Expected a block statement or expression',
@ -439,7 +439,13 @@ function lowerStatement(
reason: 'Expected to find binding for hoisted identifier', reason: 'Expected to find binding for hoisted identifier',
description: `Could not find a binding for ${id.node.name}`, description: `Could not find a binding for ${id.node.name}`,
suggestions: null, suggestions: null,
loc: id.node.loc ?? GeneratedSource, details: [
{
kind: 'error',
loc: id.node.loc ?? GeneratedSource,
message: null,
},
],
}); });
if (builder.environment.isHoistedIdentifier(binding.identifier)) { if (builder.environment.isHoistedIdentifier(binding.identifier)) {
// Already hoisted // Already hoisted
@ -481,7 +487,14 @@ function lowerStatement(
CompilerError.invariant(identifier.kind === 'Identifier', { CompilerError.invariant(identifier.kind === 'Identifier', {
reason: reason:
'Expected hoisted binding to be a local identifier, not a global', 'Expected hoisted binding to be a local identifier, not a global',
loc: id.node.loc ?? GeneratedSource, description: null,
details: [
{
kind: 'error',
loc: id.node.loc ?? GeneratedSource,
message: null,
},
],
}); });
const place: Place = { const place: Place = {
effect: Effect.Unknown, effect: Effect.Unknown,
@ -1014,7 +1027,13 @@ function lowerStatement(
CompilerError.invariant(stmt.get('id').type === 'Identifier', { CompilerError.invariant(stmt.get('id').type === 'Identifier', {
reason: 'function declarations must have a name', reason: 'function declarations must have a name',
description: null, description: null,
loc: stmt.node.loc ?? null, details: [
{
kind: 'error',
loc: stmt.node.loc ?? null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
const id = stmt.get('id') as NodePath<t.Identifier>; const id = stmt.get('id') as NodePath<t.Identifier>;
@ -1114,7 +1133,13 @@ function lowerStatement(
CompilerError.invariant(declarations.length === 1, { CompilerError.invariant(declarations.length === 1, {
reason: `Expected only one declaration in the init of a ForOfStatement, got ${declarations.length}`, reason: `Expected only one declaration in the init of a ForOfStatement, got ${declarations.length}`,
description: null, description: null,
loc: left.node.loc ?? null, details: [
{
kind: 'error',
loc: left.node.loc ?? null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
const id = declarations[0].get('id'); const id = declarations[0].get('id');
@ -1129,8 +1154,15 @@ function lowerStatement(
test = lowerValueToTemporary(builder, assign); test = lowerValueToTemporary(builder, assign);
} else { } else {
CompilerError.invariant(left.isLVal(), { CompilerError.invariant(left.isLVal(), {
loc: leftLoc,
reason: 'Expected ForOf init to be a variable declaration or lval', reason: 'Expected ForOf init to be a variable declaration or lval',
description: null,
details: [
{
kind: 'error',
loc: leftLoc,
message: null,
},
],
}); });
const assign = lowerAssignment( const assign = lowerAssignment(
builder, builder,
@ -1207,7 +1239,13 @@ function lowerStatement(
CompilerError.invariant(declarations.length === 1, { CompilerError.invariant(declarations.length === 1, {
reason: `Expected only one declaration in the init of a ForInStatement, got ${declarations.length}`, reason: `Expected only one declaration in the init of a ForInStatement, got ${declarations.length}`,
description: null, description: null,
loc: left.node.loc ?? null, details: [
{
kind: 'error',
loc: left.node.loc ?? null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
const id = declarations[0].get('id'); const id = declarations[0].get('id');
@ -1222,8 +1260,15 @@ function lowerStatement(
test = lowerValueToTemporary(builder, assign); test = lowerValueToTemporary(builder, assign);
} else { } else {
CompilerError.invariant(left.isLVal(), { CompilerError.invariant(left.isLVal(), {
loc: leftLoc,
reason: 'Expected ForIn init to be a variable declaration or lval', reason: 'Expected ForIn init to be a variable declaration or lval',
description: null,
details: [
{
kind: 'error',
loc: leftLoc,
message: null,
},
],
}); });
const assign = lowerAssignment( const assign = lowerAssignment(
builder, builder,
@ -2202,7 +2247,13 @@ function lowerExpression(
CompilerError.invariant(namePath.isJSXNamespacedName(), { CompilerError.invariant(namePath.isJSXNamespacedName(), {
reason: 'Refinement', reason: 'Refinement',
description: null, description: null,
loc: namePath.node.loc ?? null, details: [
{
kind: 'error',
loc: namePath.node.loc ?? null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
const namespace = namePath.node.namespace.name; const namespace = namePath.node.namespace.name;
@ -2256,8 +2307,14 @@ function lowerExpression(
// This is already checked in builder.resolveIdentifier // This is already checked in builder.resolveIdentifier
CompilerError.invariant(tagIdentifier.kind !== 'Identifier', { CompilerError.invariant(tagIdentifier.kind !== 'Identifier', {
reason: `<${tagName}> tags should be module-level imports`, reason: `<${tagName}> tags should be module-level imports`,
loc: openingIdentifier.node.loc ?? GeneratedSource,
description: null, description: null,
details: [
{
kind: 'error',
loc: openingIdentifier.node.loc ?? GeneratedSource,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} }
@ -2361,7 +2418,13 @@ function lowerExpression(
reason: reason:
"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",
description: null, description: null,
loc: expr.node.loc ?? null, details: [
{
kind: 'error',
loc: expr.node.loc ?? null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
const value = expr.get('quasi').get('quasis').at(0)!.node.value; const value = expr.get('quasi').get('quasis').at(0)!.node.value;
@ -2759,7 +2822,13 @@ function lowerOptionalMemberExpression(
CompilerError.invariant(object !== null, { CompilerError.invariant(object !== null, {
reason: 'Satisfy type checker', reason: 'Satisfy type checker',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
@ -3327,7 +3396,13 @@ function lowerJsxMemberExpression(
CompilerError.invariant(object.isJSXIdentifier(), { CompilerError.invariant(object.isJSXIdentifier(), {
reason: `TypeScript refinement fail: expected 'JsxIdentifier', got \`${object.node.type}\``, reason: `TypeScript refinement fail: expected 'JsxIdentifier', got \`${object.node.type}\``,
description: null, description: null,
loc: object.node.loc ?? null, details: [
{
kind: 'error',
loc: object.node.loc ?? null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
@ -3369,7 +3444,13 @@ function lowerJsxElement(
CompilerError.invariant(expression.isExpression(), { CompilerError.invariant(expression.isExpression(), {
reason: `(BuildHIR::lowerJsxElement) Expected Expression but found ${expression.type}!`, reason: `(BuildHIR::lowerJsxElement) Expected Expression but found ${expression.type}!`,
description: null, description: null,
loc: expression.node.loc ?? null, details: [
{
kind: 'error',
loc: expression.node.loc ?? null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
return lowerExpressionToTemporary(builder, expression); return lowerExpressionToTemporary(builder, expression);
@ -3770,7 +3851,13 @@ function lowerAssignment(
CompilerError.invariant(kind === InstructionKind.Reassign, { CompilerError.invariant(kind === InstructionKind.Reassign, {
reason: 'MemberExpression may only appear in an assignment expression', reason: 'MemberExpression may only appear in an assignment expression',
description: null, description: null,
loc: lvaluePath.node.loc ?? null, details: [
{
kind: 'error',
loc: lvaluePath.node.loc ?? null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
const lvalue = lvaluePath as NodePath<t.MemberExpression>; const lvalue = lvaluePath as NodePath<t.MemberExpression>;

View File

@ -234,7 +234,14 @@ function pushEndScopeTerminal(
const fallthroughId = context.fallthroughs.get(scope.id); const fallthroughId = context.fallthroughs.get(scope.id);
CompilerError.invariant(fallthroughId != null, { CompilerError.invariant(fallthroughId != null, {
reason: 'Expected scope to exist', reason: 'Expected scope to exist',
loc: GeneratedSource, description: null,
details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
}); });
context.rewrites.push({ context.rewrites.push({
kind: 'EndScope', kind: 'EndScope',

View File

@ -269,7 +269,14 @@ class PropertyPathRegistry {
CompilerError.invariant(reactive === rootNode.fullPath.reactive, { CompilerError.invariant(reactive === rootNode.fullPath.reactive, {
reason: reason:
'[HoistablePropertyLoads] Found inconsistencies in `reactive` flag when deduping identifier reads within the same scope', '[HoistablePropertyLoads] Found inconsistencies in `reactive` flag when deduping identifier reads within the same scope',
loc: identifier.loc, description: null,
details: [
{
kind: 'error',
loc: identifier.loc,
message: null,
},
],
}); });
} }
return rootNode; return rootNode;
@ -498,7 +505,14 @@ function propagateNonNull(
if (node == null) { if (node == null) {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Bad node ${nodeId}, kind: ${direction}`, reason: `Bad node ${nodeId}, kind: ${direction}`,
loc: GeneratedSource, description: null,
details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
}); });
} }
const neighbors = Array.from( const neighbors = Array.from(
@ -570,7 +584,14 @@ function propagateNonNull(
CompilerError.invariant(i++ < 100, { CompilerError.invariant(i++ < 100, {
reason: reason:
'[CollectHoistablePropertyLoads] fixed point iteration did not terminate after 100 loops', '[CollectHoistablePropertyLoads] fixed point iteration did not terminate after 100 loops',
loc: GeneratedSource, description: null,
details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
}); });
changed = false; changed = false;
@ -602,7 +623,13 @@ export function assertNonNull<T extends NonNullable<U>, U>(
CompilerError.invariant(value != null, { CompilerError.invariant(value != null, {
reason: 'Unexpected null', reason: 'Unexpected null',
description: source != null ? `(from ${source})` : null, description: source != null ? `(from ${source})` : null,
loc: GeneratedSource, details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
}); });
return value; return value;
} }

View File

@ -186,7 +186,13 @@ function matchOptionalTestBlock(
reason: reason:
'[OptionalChainDeps] Inconsistent optional chaining property load', '[OptionalChainDeps] Inconsistent optional chaining property load',
description: `Test=${printIdentifier(terminal.test.identifier)} PropertyLoad base=${printIdentifier(propertyLoad.value.object.identifier)}`, description: `Test=${printIdentifier(terminal.test.identifier)} PropertyLoad base=${printIdentifier(propertyLoad.value.object.identifier)}`,
loc: propertyLoad.loc, details: [
{
kind: 'error',
loc: propertyLoad.loc,
message: null,
},
],
}, },
); );
@ -194,7 +200,14 @@ function matchOptionalTestBlock(
storeLocal.value.identifier.id === propertyLoad.lvalue.identifier.id, storeLocal.value.identifier.id === propertyLoad.lvalue.identifier.id,
{ {
reason: '[OptionalChainDeps] Unexpected storeLocal', reason: '[OptionalChainDeps] Unexpected storeLocal',
loc: propertyLoad.loc, description: null,
details: [
{
kind: 'error',
loc: propertyLoad.loc,
message: null,
},
],
}, },
); );
if ( if (
@ -211,7 +224,14 @@ function matchOptionalTestBlock(
alternate.instructions[1].value.kind === 'StoreLocal', alternate.instructions[1].value.kind === 'StoreLocal',
{ {
reason: 'Unexpected alternate structure', reason: 'Unexpected alternate structure',
loc: terminal.loc, description: null,
details: [
{
kind: 'error',
loc: terminal.loc,
message: null,
},
],
}, },
); );
@ -247,7 +267,14 @@ function traverseOptionalBlock(
if (maybeTest.terminal.kind === 'branch') { if (maybeTest.terminal.kind === 'branch') {
CompilerError.invariant(optional.terminal.optional, { CompilerError.invariant(optional.terminal.optional, {
reason: '[OptionalChainDeps] Expect base case to be always optional', reason: '[OptionalChainDeps] Expect base case to be always optional',
loc: optional.terminal.loc, description: null,
details: [
{
kind: 'error',
loc: optional.terminal.loc,
message: null,
},
],
}); });
/** /**
* Optional base expressions are currently within value blocks which cannot * Optional base expressions are currently within value blocks which cannot
@ -285,7 +312,14 @@ function traverseOptionalBlock(
maybeTest.instructions.at(-1)!.lvalue.identifier.id, maybeTest.instructions.at(-1)!.lvalue.identifier.id,
{ {
reason: '[OptionalChainDeps] Unexpected test expression', reason: '[OptionalChainDeps] Unexpected test expression',
loc: maybeTest.terminal.loc, description: null,
details: [
{
kind: 'error',
loc: maybeTest.terminal.loc,
message: null,
},
],
}, },
); );
baseObject = { baseObject = {
@ -374,7 +408,14 @@ function traverseOptionalBlock(
reason: reason:
'[OptionalChainDeps] Unexpected instructions an inner optional block. ' + '[OptionalChainDeps] Unexpected instructions an inner optional block. ' +
'This indicates that the compiler may be incorrectly concatenating two unrelated optional chains', 'This indicates that the compiler may be incorrectly concatenating two unrelated optional chains',
loc: optional.terminal.loc, description: null,
details: [
{
kind: 'error',
loc: optional.terminal.loc,
message: null,
},
],
}); });
} }
const matchConsequentResult = matchOptionalTestBlock(test, context.blocks); const matchConsequentResult = matchOptionalTestBlock(test, context.blocks);
@ -387,7 +428,13 @@ function traverseOptionalBlock(
{ {
reason: '[OptionalChainDeps] Unexpected optional goto-fallthrough', reason: '[OptionalChainDeps] Unexpected optional goto-fallthrough',
description: `${matchConsequentResult.consequentGoto} != ${optional.terminal.fallthrough}`, description: `${matchConsequentResult.consequentGoto} != ${optional.terminal.fallthrough}`,
loc: optional.terminal.loc, details: [
{
kind: 'error',
loc: optional.terminal.loc,
message: null,
},
],
}, },
); );
const load = { const load = {

View File

@ -24,7 +24,14 @@ export function computeUnconditionalBlocks(fn: HIRFunction): Set<BlockId> {
CompilerError.invariant(!unconditionalBlocks.has(current), { CompilerError.invariant(!unconditionalBlocks.has(current), {
reason: reason:
'Internal error: non-terminating loop in ComputeUnconditionalBlocks', 'Internal error: non-terminating loop in ComputeUnconditionalBlocks',
loc: null, description: null,
details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
unconditionalBlocks.add(current); unconditionalBlocks.add(current);

View File

@ -54,7 +54,14 @@ export class ReactiveScopeDependencyTreeHIR {
prevAccessType == null || prevAccessType === accessType, prevAccessType == null || prevAccessType === accessType,
{ {
reason: 'Conflicting access types', reason: 'Conflicting access types',
loc: GeneratedSource, description: null,
details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
}, },
); );
let nextNode = currNode.properties.get(path[i].property); let nextNode = currNode.properties.get(path[i].property);
@ -90,7 +97,13 @@ export class ReactiveScopeDependencyTreeHIR {
CompilerError.invariant(reactive === rootNode.reactive, { CompilerError.invariant(reactive === rootNode.reactive, {
reason: '[DeriveMinimalDependenciesHIR] Conflicting reactive root flag', reason: '[DeriveMinimalDependenciesHIR] Conflicting reactive root flag',
description: `Identifier ${printIdentifier(identifier)}`, description: `Identifier ${printIdentifier(identifier)}`,
loc: GeneratedSource, details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
}); });
} }
return rootNode; return rootNode;

View File

@ -89,7 +89,13 @@ export class Dominator<T> {
CompilerError.invariant(dominator !== undefined, { CompilerError.invariant(dominator !== undefined, {
reason: 'Unknown node', reason: 'Unknown node',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
return dominator === id ? null : dominator; return dominator === id ? null : dominator;
@ -130,7 +136,13 @@ export class PostDominator<T> {
CompilerError.invariant(dominator !== undefined, { CompilerError.invariant(dominator !== undefined, {
reason: 'Unknown node', reason: 'Unknown node',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
return dominator === id ? null : dominator; return dominator === id ? null : dominator;
@ -175,7 +187,13 @@ function computeImmediateDominators<T>(graph: Graph<T>): Map<T, T> {
CompilerError.invariant(newIdom !== null, { CompilerError.invariant(newIdom !== null, {
reason: `At least one predecessor must have been visited for block ${id}`, reason: `At least one predecessor must have been visited for block ${id}`,
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });

View File

@ -750,7 +750,13 @@ export class Environment {
CompilerError.invariant(!this.#globals.has(hookName), { CompilerError.invariant(!this.#globals.has(hookName), {
reason: `[Globals] Found existing definition in global registry for custom hook ${hookName}`, reason: `[Globals] Found existing definition in global registry for custom hook ${hookName}`,
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
this.#globals.set( this.#globals.set(
@ -783,7 +789,14 @@ export class Environment {
CompilerError.invariant(code != null, { CompilerError.invariant(code != null, {
reason: reason:
'Expected Environment to be initialized with source code when a Flow type provider is specified', 'Expected Environment to be initialized with source code when a Flow type provider is specified',
loc: null, description: null,
details: [
{
kind: 'error',
loc: null,
message: null,
},
],
}); });
this.#flowTypeEnvironment.init(this, code); this.#flowTypeEnvironment.init(this, code);
} else { } else {
@ -794,7 +807,14 @@ export class Environment {
get typeContext(): FlowTypeEnv { get typeContext(): FlowTypeEnv {
CompilerError.invariant(this.#flowTypeEnvironment != null, { CompilerError.invariant(this.#flowTypeEnvironment != null, {
reason: 'Flow type environment not initialized', reason: 'Flow type environment not initialized',
loc: null, description: null,
details: [
{
kind: 'error',
loc: null,
message: null,
},
],
}); });
return this.#flowTypeEnvironment; return this.#flowTypeEnvironment;
} }
@ -1044,7 +1064,13 @@ export class Environment {
CompilerError.invariant(shape !== undefined, { CompilerError.invariant(shape !== undefined, {
reason: `[HIR] Forget internal error: cannot resolve shape ${shapeId}`, reason: `[HIR] Forget internal error: cannot resolve shape ${shapeId}`,
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
return shape.properties.get('*') ?? null; return shape.properties.get('*') ?? null;
@ -1069,7 +1095,13 @@ export class Environment {
CompilerError.invariant(shape !== undefined, { CompilerError.invariant(shape !== undefined, {
reason: `[HIR] Forget internal error: cannot resolve shape ${shapeId}`, reason: `[HIR] Forget internal error: cannot resolve shape ${shapeId}`,
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
if (typeof property === 'string') { if (typeof property === 'string') {
@ -1094,7 +1126,13 @@ export class Environment {
CompilerError.invariant(shape !== undefined, { CompilerError.invariant(shape !== undefined, {
reason: `[HIR] Forget internal error: cannot resolve shape ${shapeId}`, reason: `[HIR] Forget internal error: cannot resolve shape ${shapeId}`,
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
return shape.functionType; return shape.functionType;

View File

@ -184,7 +184,13 @@ function handleAssignment(
CompilerError.invariant(valuePath.isLVal(), { CompilerError.invariant(valuePath.isLVal(), {
reason: `[FindContextIdentifiers] Expected object property value to be an LVal, got: ${valuePath.type}`, reason: `[FindContextIdentifiers] Expected object property value to be an LVal, got: ${valuePath.type}`,
description: null, description: null,
loc: valuePath.node.loc ?? GeneratedSource, details: [
{
kind: 'error',
loc: valuePath.node.loc ?? GeneratedSource,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
handleAssignment(currentFn, identifiers, valuePath); handleAssignment(currentFn, identifiers, valuePath);
@ -192,7 +198,13 @@ function handleAssignment(
CompilerError.invariant(property.isRestElement(), { CompilerError.invariant(property.isRestElement(), {
reason: `[FindContextIdentifiers] Invalid assumptions for babel types.`, reason: `[FindContextIdentifiers] Invalid assumptions for babel types.`,
description: null, description: null,
loc: property.node.loc ?? GeneratedSource, details: [
{
kind: 'error',
loc: property.node.loc ?? GeneratedSource,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
handleAssignment(currentFn, identifiers, property); handleAssignment(currentFn, identifiers, property);

View File

@ -1314,8 +1314,14 @@ export function makeIdentifierName(name: string): ValidatedIdentifier {
} else { } else {
CompilerError.invariant(t.isValidIdentifier(name), { CompilerError.invariant(t.isValidIdentifier(name), {
reason: `Expected a valid identifier name`, reason: `Expected a valid identifier name`,
loc: GeneratedSource,
description: `\`${name}\` is not a valid JavaScript identifier`, description: `\`${name}\` is not a valid JavaScript identifier`,
details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} }
@ -1334,8 +1340,14 @@ export function makeIdentifierName(name: string): ValidatedIdentifier {
export function promoteTemporary(identifier: Identifier): void { export function promoteTemporary(identifier: Identifier): void {
CompilerError.invariant(identifier.name === null, { CompilerError.invariant(identifier.name === null, {
reason: `Expected a temporary (unnamed) identifier`, reason: `Expected a temporary (unnamed) identifier`,
loc: GeneratedSource,
description: `Identifier already has a name, \`${identifier.name}\``, description: `Identifier already has a name, \`${identifier.name}\``,
details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
identifier.name = { identifier.name = {
@ -1358,8 +1370,14 @@ export function isPromotedTemporary(name: string): boolean {
export function promoteTemporaryJsxTag(identifier: Identifier): void { export function promoteTemporaryJsxTag(identifier: Identifier): void {
CompilerError.invariant(identifier.name === null, { CompilerError.invariant(identifier.name === null, {
reason: `Expected a temporary (unnamed) identifier`, reason: `Expected a temporary (unnamed) identifier`,
loc: GeneratedSource,
description: `Identifier already has a name, \`${identifier.name}\``, description: `Identifier already has a name, \`${identifier.name}\``,
details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
identifier.name = { identifier.name = {
@ -1527,7 +1545,13 @@ export function isMutableEffect(
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: 'Unexpected unknown effect', reason: 'Unexpected unknown effect',
description: null, description: null,
loc: location, details: [
{
kind: 'error',
loc: location,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} }
@ -1660,7 +1684,13 @@ export function makeBlockId(id: number): BlockId {
CompilerError.invariant(id >= 0 && Number.isInteger(id), { CompilerError.invariant(id >= 0 && Number.isInteger(id), {
reason: 'Expected block id to be a non-negative integer', reason: 'Expected block id to be a non-negative integer',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
return id as BlockId; return id as BlockId;
@ -1677,7 +1707,13 @@ export function makeScopeId(id: number): ScopeId {
CompilerError.invariant(id >= 0 && Number.isInteger(id), { CompilerError.invariant(id >= 0 && Number.isInteger(id), {
reason: 'Expected block id to be a non-negative integer', reason: 'Expected block id to be a non-negative integer',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
return id as ScopeId; return id as ScopeId;
@ -1694,7 +1730,13 @@ export function makeIdentifierId(id: number): IdentifierId {
CompilerError.invariant(id >= 0 && Number.isInteger(id), { CompilerError.invariant(id >= 0 && Number.isInteger(id), {
reason: 'Expected identifier id to be a non-negative integer', reason: 'Expected identifier id to be a non-negative integer',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
return id as IdentifierId; return id as IdentifierId;
@ -1711,7 +1753,13 @@ export function makeDeclarationId(id: number): DeclarationId {
CompilerError.invariant(id >= 0 && Number.isInteger(id), { CompilerError.invariant(id >= 0 && Number.isInteger(id), {
reason: 'Expected declaration id to be a non-negative integer', reason: 'Expected declaration id to be a non-negative integer',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
return id as DeclarationId; return id as DeclarationId;
@ -1728,7 +1776,13 @@ export function makeInstructionId(id: number): InstructionId {
CompilerError.invariant(id >= 0 && Number.isInteger(id), { CompilerError.invariant(id >= 0 && Number.isInteger(id), {
reason: 'Expected instruction id to be a non-negative integer', reason: 'Expected instruction id to be a non-negative integer',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
return id as InstructionId; return id as InstructionId;

View File

@ -507,7 +507,13 @@ export default class HIRBuilder {
{ {
reason: 'Mismatched label', reason: 'Mismatched label',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}, },
); );
@ -530,7 +536,13 @@ export default class HIRBuilder {
{ {
reason: 'Mismatched label', reason: 'Mismatched label',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}, },
); );
@ -566,7 +578,13 @@ export default class HIRBuilder {
{ {
reason: 'Mismatched loops', reason: 'Mismatched loops',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}, },
); );
@ -591,7 +609,13 @@ export default class HIRBuilder {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: 'Expected a loop or switch to be in scope', reason: 'Expected a loop or switch to be in scope',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} }
@ -612,7 +636,13 @@ export default class HIRBuilder {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: 'Continue may only refer to a labeled loop', reason: 'Continue may only refer to a labeled loop',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} }
@ -620,7 +650,13 @@ export default class HIRBuilder {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: 'Expected a loop to be in scope', reason: 'Expected a loop to be in scope',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} }
@ -643,7 +679,13 @@ function _shrink(func: HIR): void {
CompilerError.invariant(block != null, { CompilerError.invariant(block != null, {
reason: `expected block ${blockId} to exist`, reason: `expected block ${blockId} to exist`,
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
target = getTargetIfIndirection(block); target = getTargetIfIndirection(block);
@ -775,7 +817,13 @@ function getReversePostorderedBlocks(func: HIR): HIR['blocks'] {
CompilerError.invariant(block != null, { CompilerError.invariant(block != null, {
reason: '[HIRBuilder] Unexpected null block', reason: '[HIRBuilder] Unexpected null block',
description: `expected block ${blockId} to exist`, description: `expected block ${blockId} to exist`,
loc: GeneratedSource, details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
}); });
const successors = [...eachTerminalSuccessor(block.terminal)].reverse(); const successors = [...eachTerminalSuccessor(block.terminal)].reverse();
const fallthrough = terminalFallthrough(block.terminal); const fallthrough = terminalFallthrough(block.terminal);
@ -831,7 +879,13 @@ export function markInstructionIds(func: HIR): void {
CompilerError.invariant(!visited.has(instr), { CompilerError.invariant(!visited.has(instr), {
reason: `${printInstruction(instr)} already visited!`, reason: `${printInstruction(instr)} already visited!`,
description: null, description: null,
loc: instr.loc, details: [
{
kind: 'error',
loc: instr.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
visited.add(instr); visited.add(instr);
@ -854,7 +908,13 @@ export function markPredecessors(func: HIR): void {
CompilerError.invariant(block != null, { CompilerError.invariant(block != null, {
reason: 'unexpected missing block', reason: 'unexpected missing block',
description: `block ${blockId}`, description: `block ${blockId}`,
loc: GeneratedSource, details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
}); });
if (prevBlock) { if (prevBlock) {
block.preds.add(prevBlock.id); block.preds.add(prevBlock.id);

View File

@ -61,7 +61,13 @@ export function mergeConsecutiveBlocks(fn: HIRFunction): void {
CompilerError.invariant(predecessor !== undefined, { CompilerError.invariant(predecessor !== undefined, {
reason: `Expected predecessor ${predecessorId} to exist`, reason: `Expected predecessor ${predecessorId} to exist`,
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
if (predecessor.terminal.kind !== 'goto' || predecessor.kind !== 'block') { if (predecessor.terminal.kind !== 'goto' || predecessor.kind !== 'block') {
@ -77,7 +83,13 @@ export function mergeConsecutiveBlocks(fn: HIRFunction): void {
CompilerError.invariant(phi.operands.size === 1, { CompilerError.invariant(phi.operands.size === 1, {
reason: `Found a block with a single predecessor but where a phi has multiple (${phi.operands.size}) operands`, reason: `Found a block with a single predecessor but where a phi has multiple (${phi.operands.size}) operands`,
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
const operand = Array.from(phi.operands.values())[0]!; const operand = Array.from(phi.operands.values())[0]!;

View File

@ -119,7 +119,13 @@ function parseAliasingSignatureConfig(
CompilerError.invariant(!lifetimes.has(temp), { CompilerError.invariant(!lifetimes.has(temp), {
reason: `Invalid type configuration for module`, reason: `Invalid type configuration for module`,
description: `Expected aliasing signature to have unique names for receiver, params, rest, returns, and temporaries in module '${moduleName}'`, description: `Expected aliasing signature to have unique names for receiver, params, rest, returns, and temporaries in module '${moduleName}'`,
loc, details: [
{
kind: 'error',
loc,
message: null,
},
],
}); });
const place = signatureArgument(lifetimes.size); const place = signatureArgument(lifetimes.size);
lifetimes.set(temp, place); lifetimes.set(temp, place);
@ -130,7 +136,13 @@ function parseAliasingSignatureConfig(
CompilerError.invariant(place != null, { CompilerError.invariant(place != null, {
reason: `Invalid type configuration for module`, reason: `Invalid type configuration for module`,
description: `Expected aliasing signature effects to reference known names from receiver/params/rest/returns/temporaries, but '${temp}' is not a known name in '${moduleName}'`, description: `Expected aliasing signature effects to reference known names from receiver/params/rest/returns/temporaries, but '${temp}' is not a known name in '${moduleName}'`,
loc, details: [
{
kind: 'error',
loc,
message: null,
},
],
}); });
return place; return place;
} }
@ -265,7 +277,13 @@ function addShape(
CompilerError.invariant(!registry.has(id), { CompilerError.invariant(!registry.has(id), {
reason: `[ObjectShape] Could not add shape to registry: name ${id} already exists.`, reason: `[ObjectShape] Could not add shape to registry: name ${id} already exists.`,
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
registry.set(id, shape); registry.set(id, shape);

View File

@ -596,7 +596,13 @@ export function printInstructionValue(instrValue: ReactiveValue): string {
{ {
reason: 'Bad assumption about quasi length.', reason: 'Bad assumption about quasi length.',
description: null, description: null,
loc: instrValue.loc, details: [
{
kind: 'error',
loc: instrValue.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}, },
); );
@ -865,8 +871,15 @@ export function printManualMemoDependency(
} else { } else {
CompilerError.invariant(val.root.value.identifier.name?.kind === 'named', { CompilerError.invariant(val.root.value.identifier.name?.kind === 'named', {
reason: 'DepsValidation: expected named local variable in depslist', reason: 'DepsValidation: expected named local variable in depslist',
description: null,
suggestions: null, suggestions: null,
loc: val.root.value.loc, details: [
{
kind: 'error',
loc: val.root.value.loc,
message: null,
},
],
}); });
rootStr = nameOnly rootStr = nameOnly
? val.root.value.identifier.name.value ? val.root.value.identifier.name.value

View File

@ -86,7 +86,14 @@ export function propagateScopeDependenciesHIR(fn: HIRFunction): void {
const hoistables = hoistablePropertyLoads.get(scope.id); const hoistables = hoistablePropertyLoads.get(scope.id);
CompilerError.invariant(hoistables != null, { CompilerError.invariant(hoistables != null, {
reason: '[PropagateScopeDependencies] Scope not found in tracked blocks', reason: '[PropagateScopeDependencies] Scope not found in tracked blocks',
loc: GeneratedSource, description: null,
details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
}); });
/** /**
* Step 2: Calculate hoistable dependencies. * Step 2: Calculate hoistable dependencies.
@ -428,7 +435,14 @@ export class DependencyCollectionContext {
const scopedDependencies = this.#dependencies.value; const scopedDependencies = this.#dependencies.value;
CompilerError.invariant(scopedDependencies != null, { CompilerError.invariant(scopedDependencies != null, {
reason: '[PropagateScopeDeps]: Unexpected scope mismatch', reason: '[PropagateScopeDeps]: Unexpected scope mismatch',
loc: scope.loc, description: null,
details: [
{
kind: 'error',
loc: scope.loc,
message: null,
},
],
}); });
// Restore context of previous scope // Restore context of previous scope

View File

@ -53,7 +53,14 @@ export function pruneUnusedLabelsHIR(fn: HIRFunction): void {
next.phis.size === 0 && fallthrough.phis.size === 0, next.phis.size === 0 && fallthrough.phis.size === 0,
{ {
reason: 'Unexpected phis when merging label blocks', reason: 'Unexpected phis when merging label blocks',
loc: label.terminal.loc, description: null,
details: [
{
kind: 'error',
loc: label.terminal.loc,
message: null,
},
],
}, },
); );
@ -64,7 +71,14 @@ export function pruneUnusedLabelsHIR(fn: HIRFunction): void {
fallthrough.preds.has(nextId), fallthrough.preds.has(nextId),
{ {
reason: 'Unexpected block predecessors when merging label blocks', reason: 'Unexpected block predecessors when merging label blocks',
loc: label.terminal.loc, description: null,
details: [
{
kind: 'error',
loc: label.terminal.loc,
message: null,
},
],
}, },
); );

View File

@ -202,8 +202,14 @@ function writeOptionalDependency(
CompilerError.invariant(firstOptional !== -1, { CompilerError.invariant(firstOptional !== -1, {
reason: reason:
'[ScopeDependencyUtils] Internal invariant broken: expected optional path', '[ScopeDependencyUtils] Internal invariant broken: expected optional path',
loc: dep.identifier.loc,
description: null, description: null,
details: [
{
kind: 'error',
loc: dep.identifier.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
if (firstOptional === dep.path.length - 1) { if (firstOptional === dep.path.length - 1) {
@ -239,7 +245,13 @@ function writeOptionalDependency(
CompilerError.invariant(testIdentifier !== null, { CompilerError.invariant(testIdentifier !== null, {
reason: 'Satisfy type checker', reason: 'Satisfy type checker',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });

View File

@ -87,7 +87,13 @@ export function makeTypeId(id: number): TypeId {
CompilerError.invariant(id >= 0 && Number.isInteger(id), { CompilerError.invariant(id >= 0 && Number.isInteger(id), {
reason: 'Expected instruction id to be a non-negative integer', reason: 'Expected instruction id to be a non-negative integer',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
return id as TypeId; return id as TypeId;

View File

@ -1233,7 +1233,14 @@ export class ScopeBlockTraversal {
CompilerError.invariant(blockInfo.scope.id === top, { CompilerError.invariant(blockInfo.scope.id === top, {
reason: reason:
'Expected traversed block fallthrough to match top-most active scope', 'Expected traversed block fallthrough to match top-most active scope',
loc: block.instructions[0]?.loc ?? block.terminal.id, description: null,
details: [
{
kind: 'error',
loc: block.instructions[0]?.loc ?? block.terminal.id,
message: null,
},
],
}); });
this.#activeScopes.pop(); this.#activeScopes.pop();
} }
@ -1247,7 +1254,14 @@ export class ScopeBlockTraversal {
!this.blockInfos.has(block.terminal.fallthrough), !this.blockInfos.has(block.terminal.fallthrough),
{ {
reason: 'Expected unique scope blocks and fallthroughs', reason: 'Expected unique scope blocks and fallthroughs',
loc: block.terminal.loc, description: null,
details: [
{
kind: 'error',
loc: block.terminal.loc,
message: null,
},
],
}, },
); );
this.blockInfos.set(block.terminal.block, { this.blockInfos.set(block.terminal.block, {

View File

@ -78,7 +78,14 @@ function lowerWithMutationAliasing(fn: HIRFunction): void {
case 'Apply': { case 'Apply': {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `[AnalyzeFunctions] Expected Apply effects to be replaced with more precise effects`, reason: `[AnalyzeFunctions] Expected Apply effects to be replaced with more precise effects`,
loc: effect.function.loc, description: null,
details: [
{
kind: 'error',
loc: effect.function.loc,
message: null,
},
],
}); });
} }
case 'Mutate': case 'Mutate':

View File

@ -300,7 +300,7 @@ function extractManualMemoizationArgs(
reason: `Expected a callback function to be passed to ${kind}`, reason: `Expected a callback function to be passed to ${kind}`,
description: `Expected a callback function to be passed to ${kind}`, description: `Expected a callback function to be passed to ${kind}`,
suggestions: null, suggestions: null,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: instr.value.loc, loc: instr.value.loc,
message: `Expected a callback function to be passed to ${kind}`, message: `Expected a callback function to be passed to ${kind}`,
@ -315,7 +315,7 @@ function extractManualMemoizationArgs(
reason: `Unexpected spread argument to ${kind}`, reason: `Unexpected spread argument to ${kind}`,
description: `Unexpected spread argument to ${kind}`, description: `Unexpected spread argument to ${kind}`,
suggestions: null, suggestions: null,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: instr.value.loc, loc: instr.value.loc,
message: `Unexpected spread argument to ${kind}`, message: `Unexpected spread argument to ${kind}`,
@ -335,7 +335,7 @@ function extractManualMemoizationArgs(
reason: `Expected the dependency list for ${kind} to be an array literal`, reason: `Expected the dependency list for ${kind} to be an array literal`,
description: `Expected the dependency list for ${kind} to be an array literal`, description: `Expected the dependency list for ${kind} to be an array literal`,
suggestions: null, suggestions: null,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: depsListPlace.loc, loc: depsListPlace.loc,
message: `Expected the dependency list for ${kind} to be an array literal`, message: `Expected the dependency list for ${kind} to be an array literal`,
@ -353,7 +353,7 @@ function extractManualMemoizationArgs(
reason: `Expected the dependency list to be an array of simple expressions (e.g. \`x\`, \`x.y.z\`, \`x?.y?.z\`)`, reason: `Expected the dependency list to be an array of simple expressions (e.g. \`x\`, \`x.y.z\`, \`x?.y?.z\`)`,
description: `Expected the dependency list to be an array of simple expressions (e.g. \`x\`, \`x.y.z\`, \`x?.y?.z\`)`, description: `Expected the dependency list to be an array of simple expressions (e.g. \`x\`, \`x.y.z\`, \`x?.y?.z\`)`,
suggestions: null, suggestions: null,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: dep.loc, loc: dep.loc,
message: `Expected the dependency list to be an array of simple expressions (e.g. \`x\`, \`x.y.z\`, \`x?.y?.z\`)`, message: `Expected the dependency list to be an array of simple expressions (e.g. \`x\`, \`x.y.z\`, \`x?.y?.z\`)`,
@ -462,7 +462,7 @@ export function dropManualMemoization(
: 'useMemo' : 'useMemo'
} callback doesn't return a value. useMemo is for computing and caching values, not for arbitrary side effects.`, } callback doesn't return a value. useMemo is for computing and caching values, not for arbitrary side effects.`,
suggestions: null, suggestions: null,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: instr.value.loc, loc: instr.value.loc,
message: 'useMemo() callbacks must return a value', message: 'useMemo() callbacks must return a value',
@ -498,7 +498,7 @@ export function dropManualMemoization(
reason: `Expected the first argument to be an inline function expression`, reason: `Expected the first argument to be an inline function expression`,
description: `Expected the first argument to be an inline function expression`, description: `Expected the first argument to be an inline function expression`,
suggestions: [], suggestions: [],
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: fnPlace.loc, loc: fnPlace.loc,
message: `Expected the first argument to be an inline function expression`, message: `Expected the first argument to be an inline function expression`,
@ -613,7 +613,14 @@ function findOptionalPlaces(fn: HIRFunction): Set<IdentifierId> {
default: { default: {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Unexpected terminal in optional`, reason: `Unexpected terminal in optional`,
loc: terminal.loc, description: null,
details: [
{
kind: 'error',
loc: terminal.loc,
message: `Unexpected ${terminal.kind} in optional`,
},
],
}); });
} }
} }

View File

@ -438,7 +438,14 @@ function rewriteSplices(
{ {
reason: reason:
'[InferEffectDependencies] Internal invariant broken: expected block instructions to be sorted', '[InferEffectDependencies] Internal invariant broken: expected block instructions to be sorted',
loc: originalInstrs[cursor].loc, description: null,
details: [
{
kind: 'error',
loc: originalInstrs[cursor].loc,
message: null,
},
],
}, },
); );
currBlock.instructions.push(originalInstrs[cursor]); currBlock.instructions.push(originalInstrs[cursor]);
@ -447,7 +454,14 @@ function rewriteSplices(
CompilerError.invariant(originalInstrs[cursor].id === rewrite.location, { CompilerError.invariant(originalInstrs[cursor].id === rewrite.location, {
reason: reason:
'[InferEffectDependencies] Internal invariant broken: splice location not found', '[InferEffectDependencies] Internal invariant broken: splice location not found',
loc: originalInstrs[cursor].loc, description: null,
details: [
{
kind: 'error',
loc: originalInstrs[cursor].loc,
message: null,
},
],
}); });
if (rewrite.kind === 'instr') { if (rewrite.kind === 'instr') {
@ -467,7 +481,14 @@ function rewriteSplices(
{ {
reason: reason:
'[InferEffectDependencies] Internal invariant broken: expected entry block to have a fallthrough', '[InferEffectDependencies] Internal invariant broken: expected entry block to have a fallthrough',
loc: entryBlock.terminal.loc, description: null,
details: [
{
kind: 'error',
loc: entryBlock.terminal.loc,
message: null,
},
],
}, },
); );
const originalTerminal = currBlock.terminal; const originalTerminal = currBlock.terminal;
@ -566,7 +587,14 @@ function inferMinimalDependencies(
CompilerError.invariant(hoistableToFnEntry != null, { CompilerError.invariant(hoistableToFnEntry != null, {
reason: reason:
'[InferEffectDependencies] Internal invariant broken: missing entry block', '[InferEffectDependencies] Internal invariant broken: missing entry block',
loc: fnInstr.loc, description: null,
details: [
{
kind: 'error',
loc: fnInstr.loc,
message: null,
},
],
}); });
const dependencies = inferDependencies( const dependencies = inferDependencies(
@ -622,7 +650,14 @@ function inferDependencies(
CompilerError.invariant(resultUnfiltered != null, { CompilerError.invariant(resultUnfiltered != null, {
reason: reason:
'[InferEffectDependencies] Internal invariant broken: missing scope dependencies', '[InferEffectDependencies] Internal invariant broken: missing scope dependencies',
loc: fn.loc, description: null,
details: [
{
kind: 'error',
loc: fn.loc,
message: null,
},
],
}); });
const fnContext = new Set(fn.context.map(dep => dep.identifier.id)); const fnContext = new Set(fn.context.map(dep => dep.identifier.id));

View File

@ -58,7 +58,6 @@ import {
printInstruction, printInstruction,
printInstructionValue, printInstructionValue,
printPlace, printPlace,
printSourceLocation,
} from '../HIR/PrintHIR'; } from '../HIR/PrintHIR';
import {FunctionSignature} from '../HIR/ObjectShape'; import {FunctionSignature} from '../HIR/ObjectShape';
import prettyFormat from 'pretty-format'; import prettyFormat from 'pretty-format';
@ -135,7 +134,13 @@ export function inferMutationAliasingEffects(
reason: reason:
'Expected React component to have not more than two parameters: one for props and for ref', 'Expected React component to have not more than two parameters: one for props and for ref',
description: null, description: null,
loc: fn.loc, details: [
{
kind: 'error',
loc: fn.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
const [props, ref] = fn.params; const [props, ref] = fn.params;
@ -202,7 +207,13 @@ export function inferMutationAliasingEffects(
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `[InferMutationAliasingEffects] Potential infinite loop`, reason: `[InferMutationAliasingEffects] Potential infinite loop`,
description: `A value, temporary place, or effect was not cached properly`, description: `A value, temporary place, or effect was not cached properly`,
loc: fn.loc, details: [
{
kind: 'error',
loc: fn.loc,
message: null,
},
],
}); });
} }
for (const [blockId, block] of fn.body.blocks) { for (const [blockId, block] of fn.body.blocks) {
@ -357,7 +368,14 @@ function inferBlock(
CompilerError.invariant(state.kind(handlerParam) != null, { CompilerError.invariant(state.kind(handlerParam) != null, {
reason: reason:
'Expected catch binding to be intialized with a DeclareLocal Catch instruction', 'Expected catch binding to be intialized with a DeclareLocal Catch instruction',
loc: terminal.loc, description: null,
details: [
{
kind: 'error',
loc: terminal.loc,
message: null,
},
],
}); });
const effects: Array<AliasingEffect> = []; const effects: Array<AliasingEffect> = [];
for (const instr of block.instructions) { for (const instr of block.instructions) {
@ -456,7 +474,7 @@ function applySignature(
category: ErrorCategory.Immutability, category: ErrorCategory.Immutability,
reason: 'This value cannot be modified', reason: 'This value cannot be modified',
description: `${reason}.`, description: `${reason}.`,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: effect.value.loc, loc: effect.value.loc,
message: `${variable} cannot be modified`, message: `${variable} cannot be modified`,
@ -465,7 +483,7 @@ function applySignature(
effect.kind === 'Mutate' && effect.kind === 'Mutate' &&
effect.reason?.kind === 'AssignCurrentProperty' effect.reason?.kind === 'AssignCurrentProperty'
) { ) {
diagnostic.withDetail({ diagnostic.withDetails({
kind: 'hint', kind: 'hint',
message: `Hint: If this value is a Ref (value returned by \`useRef()\`), rename the variable to end in "Ref".`, message: `Hint: If this value is a Ref (value returned by \`useRef()\`), rename the variable to end in "Ref".`,
}); });
@ -507,7 +525,14 @@ function applySignature(
) { ) {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Expected instruction lvalue to be initialized`, reason: `Expected instruction lvalue to be initialized`,
loc: instruction.loc, description: null,
details: [
{
kind: 'error',
loc: instruction.loc,
message: null,
},
],
}); });
} }
return effects.length !== 0 ? effects : null; return effects.length !== 0 ? effects : null;
@ -536,7 +561,13 @@ function applyEffect(
CompilerError.invariant(!initialized.has(effect.into.identifier.id), { CompilerError.invariant(!initialized.has(effect.into.identifier.id), {
reason: `Cannot re-initialize variable within an instruction`, reason: `Cannot re-initialize variable within an instruction`,
description: `Re-initialized ${printPlace(effect.into)} in ${printAliasingEffect(effect)}`, description: `Re-initialized ${printPlace(effect.into)} in ${printAliasingEffect(effect)}`,
loc: effect.into.loc, details: [
{
kind: 'error',
loc: effect.into.loc,
message: null,
},
],
}); });
initialized.add(effect.into.identifier.id); initialized.add(effect.into.identifier.id);
@ -575,7 +606,13 @@ function applyEffect(
CompilerError.invariant(!initialized.has(effect.into.identifier.id), { CompilerError.invariant(!initialized.has(effect.into.identifier.id), {
reason: `Cannot re-initialize variable within an instruction`, reason: `Cannot re-initialize variable within an instruction`,
description: `Re-initialized ${printPlace(effect.into)} in ${printAliasingEffect(effect)}`, description: `Re-initialized ${printPlace(effect.into)} in ${printAliasingEffect(effect)}`,
loc: effect.into.loc, details: [
{
kind: 'error',
loc: effect.into.loc,
message: null,
},
],
}); });
initialized.add(effect.into.identifier.id); initialized.add(effect.into.identifier.id);
@ -635,7 +672,13 @@ function applyEffect(
CompilerError.invariant(!initialized.has(effect.into.identifier.id), { CompilerError.invariant(!initialized.has(effect.into.identifier.id), {
reason: `Cannot re-initialize variable within an instruction`, reason: `Cannot re-initialize variable within an instruction`,
description: `Re-initialized ${printPlace(effect.into)} in ${printAliasingEffect(effect)}`, description: `Re-initialized ${printPlace(effect.into)} in ${printAliasingEffect(effect)}`,
loc: effect.into.loc, details: [
{
kind: 'error',
loc: effect.into.loc,
message: null,
},
],
}); });
initialized.add(effect.into.identifier.id); initialized.add(effect.into.identifier.id);
@ -709,7 +752,13 @@ function applyEffect(
{ {
reason: `Expected destination value to already be initialized within this instruction for Alias effect`, reason: `Expected destination value to already be initialized within this instruction for Alias effect`,
description: `Destination ${printPlace(effect.into)} is not initialized in this instruction`, description: `Destination ${printPlace(effect.into)} is not initialized in this instruction`,
loc: effect.into.loc, details: [
{
kind: 'error',
loc: effect.into.loc,
message: null,
},
],
}, },
); );
/* /*
@ -768,7 +817,13 @@ function applyEffect(
CompilerError.invariant(!initialized.has(effect.into.identifier.id), { CompilerError.invariant(!initialized.has(effect.into.identifier.id), {
reason: `Cannot re-initialize variable within an instruction`, reason: `Cannot re-initialize variable within an instruction`,
description: `Re-initialized ${printPlace(effect.into)} in ${printAliasingEffect(effect)}`, description: `Re-initialized ${printPlace(effect.into)} in ${printAliasingEffect(effect)}`,
loc: effect.into.loc, details: [
{
kind: 'error',
loc: effect.into.loc,
message: null,
},
],
}); });
initialized.add(effect.into.identifier.id); initialized.add(effect.into.identifier.id);
@ -1042,13 +1097,13 @@ function applyEffect(
description: `${variable ?? 'This variable'} is accessed before it is declared, which prevents the earlier access from updating when this value changes over time.`, description: `${variable ?? 'This variable'} is accessed before it is declared, which prevents the earlier access from updating when this value changes over time.`,
}); });
if (hoistedAccess != null && hoistedAccess.loc != effect.value.loc) { if (hoistedAccess != null && hoistedAccess.loc != effect.value.loc) {
diagnostic.withDetail({ diagnostic.withDetails({
kind: 'error', kind: 'error',
loc: hoistedAccess.loc, loc: hoistedAccess.loc,
message: `${variable ?? 'variable'} accessed before it is declared`, message: `${variable ?? 'variable'} accessed before it is declared`,
}); });
} }
diagnostic.withDetail({ diagnostic.withDetails({
kind: 'error', kind: 'error',
loc: effect.value.loc, loc: effect.value.loc,
message: `${variable ?? 'variable'} is declared here`, message: `${variable ?? 'variable'} is declared here`,
@ -1079,7 +1134,7 @@ function applyEffect(
category: ErrorCategory.Immutability, category: ErrorCategory.Immutability,
reason: 'This value cannot be modified', reason: 'This value cannot be modified',
description: `${reason}.`, description: `${reason}.`,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: effect.value.loc, loc: effect.value.loc,
message: `${variable} cannot be modified`, message: `${variable} cannot be modified`,
@ -1088,7 +1143,7 @@ function applyEffect(
effect.kind === 'Mutate' && effect.kind === 'Mutate' &&
effect.reason?.kind === 'AssignCurrentProperty' effect.reason?.kind === 'AssignCurrentProperty'
) { ) {
diagnostic.withDetail({ diagnostic.withDetails({
kind: 'hint', kind: 'hint',
message: `Hint: If this value is a Ref (value returned by \`useRef()\`), rename the variable to end in "Ref".`, message: `Hint: If this value is a Ref (value returned by \`useRef()\`), rename the variable to end in "Ref".`,
}); });
@ -1169,7 +1224,13 @@ class InferenceState {
reason: reason:
'[InferMutationAliasingEffects] Expected all top-level identifiers to be defined as variables, not values', '[InferMutationAliasingEffects] Expected all top-level identifiers to be defined as variables, not values',
description: null, description: null,
loc: value.loc, details: [
{
kind: 'error',
loc: value.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
this.#values.set(value, kind); this.#values.set(value, kind);
@ -1180,7 +1241,13 @@ class InferenceState {
CompilerError.invariant(values != null, { CompilerError.invariant(values != null, {
reason: `[InferMutationAliasingEffects] Expected value kind to be initialized`, reason: `[InferMutationAliasingEffects] Expected value kind to be initialized`,
description: `${printPlace(place)}`, description: `${printPlace(place)}`,
loc: place.loc, details: [
{
kind: 'error',
loc: place.loc,
message: 'this is uninitialized',
},
],
suggestions: null, suggestions: null,
}); });
return Array.from(values); return Array.from(values);
@ -1192,7 +1259,13 @@ class InferenceState {
CompilerError.invariant(values != null, { CompilerError.invariant(values != null, {
reason: `[InferMutationAliasingEffects] Expected value kind to be initialized`, reason: `[InferMutationAliasingEffects] Expected value kind to be initialized`,
description: `${printPlace(place)}`, description: `${printPlace(place)}`,
loc: place.loc, details: [
{
kind: 'error',
loc: place.loc,
message: 'this is uninitialized',
},
],
suggestions: null, suggestions: null,
}); });
let mergedKind: AbstractValue | null = null; let mergedKind: AbstractValue | null = null;
@ -1204,7 +1277,13 @@ class InferenceState {
CompilerError.invariant(mergedKind !== null, { CompilerError.invariant(mergedKind !== null, {
reason: `[InferMutationAliasingEffects] Expected at least one value`, reason: `[InferMutationAliasingEffects] Expected at least one value`,
description: `No value found at \`${printPlace(place)}\``, description: `No value found at \`${printPlace(place)}\``,
loc: place.loc, details: [
{
kind: 'error',
loc: place.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
return mergedKind; return mergedKind;
@ -1216,7 +1295,13 @@ class InferenceState {
CompilerError.invariant(values != null, { CompilerError.invariant(values != null, {
reason: `[InferMutationAliasingEffects] Expected value for identifier to be initialized`, reason: `[InferMutationAliasingEffects] Expected value for identifier to be initialized`,
description: `${printIdentifier(value.identifier)}`, description: `${printIdentifier(value.identifier)}`,
loc: value.loc, details: [
{
kind: 'error',
loc: value.loc,
message: 'Expected value for identifier to be initialized',
},
],
suggestions: null, suggestions: null,
}); });
this.#variables.set(place.identifier.id, new Set(values)); this.#variables.set(place.identifier.id, new Set(values));
@ -1227,7 +1312,13 @@ class InferenceState {
CompilerError.invariant(values != null, { CompilerError.invariant(values != null, {
reason: `[InferMutationAliasingEffects] Expected value for identifier to be initialized`, reason: `[InferMutationAliasingEffects] Expected value for identifier to be initialized`,
description: `${printIdentifier(value.identifier)}`, description: `${printIdentifier(value.identifier)}`,
loc: value.loc, details: [
{
kind: 'error',
loc: value.loc,
message: 'Expected value for identifier to be initialized',
},
],
suggestions: null, suggestions: null,
}); });
const prevValues = this.values(place); const prevValues = this.values(place);
@ -1240,11 +1331,15 @@ class InferenceState {
// Defines (initializing or updating) a variable with a specific kind of value. // Defines (initializing or updating) a variable with a specific kind of value.
define(place: Place, value: InstructionValue): void { define(place: Place, value: InstructionValue): void {
CompilerError.invariant(this.#values.has(value), { CompilerError.invariant(this.#values.has(value), {
reason: `[InferMutationAliasingEffects] Expected value to be initialized at '${printSourceLocation( reason: `[InferMutationAliasingEffects] Expected value to be initialized`,
value.loc,
)}'`,
description: printInstructionValue(value), description: printInstructionValue(value),
loc: value.loc, details: [
{
kind: 'error',
loc: value.loc,
message: 'Expected value for identifier to be initialized',
},
],
suggestions: null, suggestions: null,
}); });
this.#variables.set(place.identifier.id, new Set([value])); this.#variables.set(place.identifier.id, new Set([value]));
@ -2055,7 +2150,7 @@ function computeSignatureForInstruction(
reason: reason:
'Cannot reassign variables declared outside of the component/hook', 'Cannot reassign variables declared outside of the component/hook',
description: `Variable ${variable} is declared outside of the component/hook. Reassigning this value during render is a form of side effect, which can cause unpredictable behavior depending on when the component happens to re-render. If this variable is used in rendering, use useState instead. Otherwise, consider updating it in an effect. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)`, description: `Variable ${variable} is declared outside of the component/hook. Reassigning this value during render is a form of side effect, which can cause unpredictable behavior depending on when the component happens to re-render. If this variable is used in rendering, use useState instead. Otherwise, consider updating it in an effect. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)`,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: instr.loc, loc: instr.loc,
message: `${variable} cannot be reassigned`, message: `${variable} cannot be reassigned`,
@ -2157,7 +2252,7 @@ function computeEffectsForLegacySignature(
? `\`${signature.canonicalName}\` is an impure function. ` ? `\`${signature.canonicalName}\` is an impure function. `
: '') + : '') +
'Calling an impure function can produce unstable results that update unpredictably when the component happens to re-render. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)', 'Calling an impure function can produce unstable results that update unpredictably when the component happens to re-render. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)',
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc, loc,
message: 'Cannot call impure function', message: 'Cannot call impure function',
@ -2176,7 +2271,7 @@ function computeEffectsForLegacySignature(
'However, you may see issues if values from this API are passed to other components/hooks that are ' + 'However, you may see issues if values from this API are passed to other components/hooks that are ' +
'memoized.', 'memoized.',
].join(''), ].join(''),
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: receiver.loc, loc: receiver.loc,
message: signature.knownIncompatible, message: signature.knownIncompatible,
@ -2676,7 +2771,13 @@ export function isKnownMutableEffect(effect: Effect): boolean {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: 'Unexpected unknown effect', reason: 'Unexpected unknown effect',
description: null, description: null,
loc: GeneratedSource, details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} }
@ -2785,7 +2886,13 @@ function mergeValueKinds(a: ValueKind, b: ValueKind): ValueKind {
{ {
reason: `Unexpected value kind in mergeValues()`, reason: `Unexpected value kind in mergeValues()`,
description: `Found kinds ${a} and ${b}`, description: `Found kinds ${a} and ${b}`,
loc: GeneratedSource, details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
}, },
); );
return ValueKind.Primitive; return ValueKind.Primitive;

View File

@ -229,7 +229,14 @@ export function inferMutationAliasingRanges(
} else { } else {
CompilerError.invariant(effect.kind === 'Freeze', { CompilerError.invariant(effect.kind === 'Freeze', {
reason: `Unexpected '${effect.kind}' effect for MaybeThrow terminal`, reason: `Unexpected '${effect.kind}' effect for MaybeThrow terminal`,
loc: block.terminal.loc, description: null,
details: [
{
kind: 'error',
loc: block.terminal.loc,
message: null,
},
],
}); });
} }
} }
@ -378,7 +385,14 @@ export function inferMutationAliasingRanges(
case 'Apply': { case 'Apply': {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `[AnalyzeFunctions] Expected Apply effects to be replaced with more precise effects`, reason: `[AnalyzeFunctions] Expected Apply effects to be replaced with more precise effects`,
loc: effect.function.loc, description: null,
details: [
{
kind: 'error',
loc: effect.function.loc,
message: null,
},
],
}); });
} }
case 'MutateTransitive': case 'MutateTransitive':
@ -525,7 +539,14 @@ export function inferMutationAliasingRanges(
const fromNode = state.nodes.get(from.identifier); const fromNode = state.nodes.get(from.identifier);
CompilerError.invariant(fromNode != null, { CompilerError.invariant(fromNode != null, {
reason: `Expected a node to exist for all parameters and context variables`, reason: `Expected a node to exist for all parameters and context variables`,
loc: into.loc, description: null,
details: [
{
kind: 'error',
loc: into.loc,
message: null,
},
],
}); });
if (fromNode.lastMutated === mutationIndex) { if (fromNode.lastMutated === mutationIndex) {
if (into.identifier.id === fn.returns.identifier.id) { if (into.identifier.id === fn.returns.identifier.id) {

View File

@ -349,7 +349,13 @@ export function inferReactivePlaces(fn: HIRFunction): void {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: 'Unexpected unknown effect', reason: 'Unexpected unknown effect',
description: null, description: null,
loc: operand.loc, details: [
{
kind: 'error',
loc: operand.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} }

View File

@ -191,7 +191,14 @@ function evaluatePhi(phi: Phi, constants: Constants): Constant | null {
case 'Primitive': { case 'Primitive': {
CompilerError.invariant(value.kind === 'Primitive', { CompilerError.invariant(value.kind === 'Primitive', {
reason: 'value kind expected to be Primitive', reason: 'value kind expected to be Primitive',
loc: null, description: null,
details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
@ -204,7 +211,14 @@ function evaluatePhi(phi: Phi, constants: Constants): Constant | null {
case 'LoadGlobal': { case 'LoadGlobal': {
CompilerError.invariant(value.kind === 'LoadGlobal', { CompilerError.invariant(value.kind === 'LoadGlobal', {
reason: 'value kind expected to be LoadGlobal', reason: 'value kind expected to be LoadGlobal',
loc: null, description: null,
details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });

View File

@ -709,7 +709,14 @@ function createPropsProperties(
const spreadProp = jsxSpreadAttributes[0]; const spreadProp = jsxSpreadAttributes[0];
CompilerError.invariant(spreadProp.kind === 'JsxSpreadAttribute', { CompilerError.invariant(spreadProp.kind === 'JsxSpreadAttribute', {
reason: 'Spread prop attribute must be of kind JSXSpreadAttribute', reason: 'Spread prop attribute must be of kind JSXSpreadAttribute',
loc: instr.loc, description: null,
details: [
{
kind: 'error',
loc: instr.loc,
message: null,
},
],
}); });
propsProperty = { propsProperty = {
kind: 'ObjectProperty', kind: 'ObjectProperty',

View File

@ -78,10 +78,17 @@ export function instructionReordering(fn: HIRFunction): void {
} }
CompilerError.invariant(shared.size === 0, { CompilerError.invariant(shared.size === 0, {
reason: `InstructionReordering: expected all reorderable nodes to have been emitted`, reason: `InstructionReordering: expected all reorderable nodes to have been emitted`,
loc: description: null,
[...shared.values()] details: [
.map(node => node.instruction?.loc) {
.filter(loc => loc != null)[0] ?? GeneratedSource, kind: 'error',
loc:
[...shared.values()]
.map(node => node.instruction?.loc)
.filter(loc => loc != null)[0] ?? GeneratedSource,
message: null,
},
],
}); });
markInstructionIds(fn.body); markInstructionIds(fn.body);
} }
@ -302,7 +309,13 @@ function reorderBlock(
node.reorderability === Reorderability.Reorderable, node.reorderability === Reorderability.Reorderable,
{ {
reason: `Expected all remaining instructions to be reorderable`, reason: `Expected all remaining instructions to be reorderable`,
loc: node.instruction?.loc ?? block.terminal.loc, details: [
{
kind: 'error',
loc: node.instruction?.loc ?? block.terminal.loc,
message: null,
},
],
description: description:
node.instruction != null node.instruction != null
? `Instruction [${node.instruction.id}] was not emitted yet but is not reorderable` ? `Instruction [${node.instruction.id}] was not emitted yet but is not reorderable`

View File

@ -52,7 +52,13 @@ export function pruneMaybeThrows(fn: HIRFunction): void {
const mappedTerminal = terminalMapping.get(predecessor); const mappedTerminal = terminalMapping.get(predecessor);
CompilerError.invariant(mappedTerminal != null, { CompilerError.invariant(mappedTerminal != null, {
reason: `Expected non-existing phi operand's predecessor to have been mapped to a new terminal`, reason: `Expected non-existing phi operand's predecessor to have been mapped to a new terminal`,
loc: GeneratedSource, details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
description: `Could not find mapping for predecessor bb${predecessor} in block bb${ description: `Could not find mapping for predecessor bb${predecessor} in block bb${
block.id block.id
} for phi ${printPlace(phi.place)}`, } for phi ${printPlace(phi.place)}`,

View File

@ -41,8 +41,15 @@ function findScopesToMerge(fn: HIRFunction): DisjointSet<ReactiveScope> {
{ {
reason: reason:
'Internal error: Expected all ObjectExpressions and ObjectMethods to have non-null scope.', 'Internal error: Expected all ObjectExpressions and ObjectMethods to have non-null scope.',
description: null,
suggestions: null, suggestions: null,
loc: GeneratedSource, details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
}, },
); );
mergeScopesBuilder.union([operandScope, lvalueScope]); mergeScopesBuilder.union([operandScope, lvalueScope]);

View File

@ -170,7 +170,14 @@ export function alignReactiveScopesToBlockScopesHIR(fn: HIRFunction): void {
CompilerError.invariant(!valueBlockNodes.has(fallthrough), { CompilerError.invariant(!valueBlockNodes.has(fallthrough), {
reason: 'Expect hir blocks to have unique fallthroughs', reason: 'Expect hir blocks to have unique fallthroughs',
loc: terminal.loc, description: null,
details: [
{
kind: 'error',
loc: terminal.loc,
message: null,
},
],
}); });
if (node != null) { if (node != null) {
valueBlockNodes.set(fallthrough, node); valueBlockNodes.set(fallthrough, node);
@ -252,7 +259,14 @@ export function alignReactiveScopesToBlockScopesHIR(fn: HIRFunction): void {
// Transition from block->value block, derive the outer block range // Transition from block->value block, derive the outer block range
CompilerError.invariant(fallthrough !== null, { CompilerError.invariant(fallthrough !== null, {
reason: `Expected a fallthrough for value block`, reason: `Expected a fallthrough for value block`,
loc: terminal.loc, description: null,
details: [
{
kind: 'error',
loc: terminal.loc,
message: null,
},
],
}); });
const fallthroughBlock = fn.body.blocks.get(fallthrough)!; const fallthroughBlock = fn.body.blocks.get(fallthrough)!;
const nextId = const nextId =

View File

@ -81,10 +81,16 @@ class CheckInstructionsAgainstScopesVisitor extends ReactiveFunctionVisitor<
!this.activeScopes.has(scope.id) !this.activeScopes.has(scope.id)
) { ) {
CompilerError.invariant(false, { CompilerError.invariant(false, {
description: `Instruction [${id}] is part of scope @${scope.id}, but that scope has already completed.`,
loc: place.loc,
reason: reason:
'Encountered an instruction that should be part of a scope, but where that scope has already completed', 'Encountered an instruction that should be part of a scope, but where that scope has already completed',
description: `Instruction [${id}] is part of scope @${scope.id}, but that scope has already completed.`,
details: [
{
kind: 'error',
loc: place.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} }

View File

@ -28,7 +28,14 @@ class Visitor extends ReactiveFunctionVisitor<Set<BlockId>> {
if (terminal.kind === 'break' || terminal.kind === 'continue') { if (terminal.kind === 'break' || terminal.kind === 'continue') {
CompilerError.invariant(seenLabels.has(terminal.target), { CompilerError.invariant(seenLabels.has(terminal.target), {
reason: 'Unexpected break to invalid label', reason: 'Unexpected break to invalid label',
loc: stmt.terminal.loc, description: null,
details: [
{
kind: 'error',
loc: stmt.terminal.loc,
message: null,
},
],
}); });
} }
} }

View File

@ -70,7 +70,13 @@ class Driver {
CompilerError.invariant(!this.cx.emitted.has(block.id), { CompilerError.invariant(!this.cx.emitted.has(block.id), {
reason: `Cannot emit the same block twice: bb${block.id}`, reason: `Cannot emit the same block twice: bb${block.id}`,
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
this.cx.emitted.add(block.id); this.cx.emitted.add(block.id);
@ -130,7 +136,14 @@ class Driver {
if (this.cx.isScheduled(terminal.consequent)) { if (this.cx.isScheduled(terminal.consequent)) {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Unexpected 'if' where the consequent is already scheduled`, reason: `Unexpected 'if' where the consequent is already scheduled`,
loc: terminal.loc, description: null,
details: [
{
kind: 'error',
loc: terminal.loc,
message: null,
},
],
}); });
} else { } else {
consequent = this.traverseBlock( consequent = this.traverseBlock(
@ -143,7 +156,14 @@ class Driver {
if (this.cx.isScheduled(alternateId)) { if (this.cx.isScheduled(alternateId)) {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Unexpected 'if' where the alternate is already scheduled`, reason: `Unexpected 'if' where the alternate is already scheduled`,
loc: terminal.loc, description: null,
details: [
{
kind: 'error',
loc: terminal.loc,
message: null,
},
],
}); });
} else { } else {
alternate = this.traverseBlock(this.cx.ir.blocks.get(alternateId)!); alternate = this.traverseBlock(this.cx.ir.blocks.get(alternateId)!);
@ -196,7 +216,14 @@ class Driver {
if (this.cx.isScheduled(case_.block)) { if (this.cx.isScheduled(case_.block)) {
CompilerError.invariant(case_.block === terminal.fallthrough, { CompilerError.invariant(case_.block === terminal.fallthrough, {
reason: `Unexpected 'switch' where a case is already scheduled and block is not the fallthrough`, reason: `Unexpected 'switch' where a case is already scheduled and block is not the fallthrough`,
loc: terminal.loc, description: null,
details: [
{
kind: 'error',
loc: terminal.loc,
message: null,
},
],
}); });
return; return;
} else { } else {
@ -255,7 +282,14 @@ class Driver {
} else { } else {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Unexpected 'do-while' where the loop is already scheduled`, reason: `Unexpected 'do-while' where the loop is already scheduled`,
loc: terminal.loc, description: null,
details: [
{
kind: 'error',
loc: terminal.loc,
message: null,
},
],
}); });
} }
@ -316,7 +350,14 @@ class Driver {
} else { } else {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Unexpected 'while' where the loop is already scheduled`, reason: `Unexpected 'while' where the loop is already scheduled`,
loc: terminal.loc, description: null,
details: [
{
kind: 'error',
loc: terminal.loc,
message: null,
},
],
}); });
} }
@ -402,7 +443,14 @@ class Driver {
} else { } else {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Unexpected 'for' where the loop is already scheduled`, reason: `Unexpected 'for' where the loop is already scheduled`,
loc: terminal.loc, description: null,
details: [
{
kind: 'error',
loc: terminal.loc,
message: null,
},
],
}); });
} }
@ -500,7 +548,14 @@ class Driver {
} else { } else {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Unexpected 'for-of' where the loop is already scheduled`, reason: `Unexpected 'for-of' where the loop is already scheduled`,
loc: terminal.loc, description: null,
details: [
{
kind: 'error',
loc: terminal.loc,
message: null,
},
],
}); });
} }
@ -572,7 +627,14 @@ class Driver {
} else { } else {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Unexpected 'for-in' where the loop is already scheduled`, reason: `Unexpected 'for-in' where the loop is already scheduled`,
loc: terminal.loc, description: null,
details: [
{
kind: 'error',
loc: terminal.loc,
message: null,
},
],
}); });
} }
@ -615,7 +677,14 @@ class Driver {
if (this.cx.isScheduled(terminal.alternate)) { if (this.cx.isScheduled(terminal.alternate)) {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Unexpected 'branch' where the alternate is already scheduled`, reason: `Unexpected 'branch' where the alternate is already scheduled`,
loc: terminal.loc, description: null,
details: [
{
kind: 'error',
loc: terminal.loc,
message: null,
},
],
}); });
} else { } else {
alternate = this.traverseBlock( alternate = this.traverseBlock(
@ -653,7 +722,14 @@ class Driver {
if (this.cx.isScheduled(terminal.block)) { if (this.cx.isScheduled(terminal.block)) {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Unexpected 'label' where the block is already scheduled`, reason: `Unexpected 'label' where the block is already scheduled`,
loc: terminal.loc, description: null,
details: [
{
kind: 'error',
loc: terminal.loc,
message: null,
},
],
}); });
} else { } else {
block = this.traverseBlock(this.cx.ir.blocks.get(terminal.block)!); block = this.traverseBlock(this.cx.ir.blocks.get(terminal.block)!);
@ -811,7 +887,14 @@ class Driver {
if (this.cx.isScheduled(terminal.block)) { if (this.cx.isScheduled(terminal.block)) {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Unexpected 'scope' where the block is already scheduled`, reason: `Unexpected 'scope' where the block is already scheduled`,
loc: terminal.loc, description: null,
details: [
{
kind: 'error',
loc: terminal.loc,
message: null,
},
],
}); });
} else { } else {
block = this.traverseBlock(this.cx.ir.blocks.get(terminal.block)!); block = this.traverseBlock(this.cx.ir.blocks.get(terminal.block)!);
@ -837,7 +920,13 @@ class Driver {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: 'Unexpected unsupported terminal', reason: 'Unexpected unsupported terminal',
description: null, description: null,
loc: terminal.loc, details: [
{
kind: 'error',
loc: terminal.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} }
@ -874,7 +963,13 @@ class Driver {
reason: reason:
'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',
description: null, description: null,
loc: instr.lvalue.loc, details: [
{
kind: 'error',
loc: instr.lvalue.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}, },
); );
@ -906,7 +1001,13 @@ class Driver {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: 'Expected goto value block to have at least one instruction', reason: 'Expected goto value block to have at least one instruction',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} else if (defaultBlock.instructions.length === 1) { } else if (defaultBlock.instructions.length === 1) {
@ -1191,14 +1292,27 @@ class Driver {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: 'Expected a break target', reason: 'Expected a break target',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} }
if (this.cx.scopeFallthroughs.has(target.block)) { if (this.cx.scopeFallthroughs.has(target.block)) {
CompilerError.invariant(target.type === 'implicit', { CompilerError.invariant(target.type === 'implicit', {
reason: 'Expected reactive scope to implicitly break to fallthrough', reason: 'Expected reactive scope to implicitly break to fallthrough',
loc, description: null,
details: [
{
kind: 'error',
loc,
message: null,
},
],
}); });
return null; return null;
} }
@ -1224,7 +1338,13 @@ class Driver {
CompilerError.invariant(target !== null, { CompilerError.invariant(target !== null, {
reason: `Expected continue target to be scheduled for bb${block}`, reason: `Expected continue target to be scheduled for bb${block}`,
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
@ -1299,7 +1419,13 @@ class Context {
CompilerError.invariant(!this.#scheduled.has(block), { CompilerError.invariant(!this.#scheduled.has(block), {
reason: `Break block is already scheduled: bb${block}`, reason: `Break block is already scheduled: bb${block}`,
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
this.#scheduled.add(block); this.#scheduled.add(block);
@ -1318,7 +1444,13 @@ class Context {
CompilerError.invariant(!this.#scheduled.has(continueBlock), { CompilerError.invariant(!this.#scheduled.has(continueBlock), {
reason: `Continue block is already scheduled: bb${continueBlock}`, reason: `Continue block is already scheduled: bb${continueBlock}`,
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
this.#scheduled.add(continueBlock); this.#scheduled.add(continueBlock);
@ -1346,7 +1478,13 @@ class Context {
CompilerError.invariant(last !== undefined && last.id === scheduleId, { CompilerError.invariant(last !== undefined && last.id === scheduleId, {
reason: 'Can only unschedule the last target', reason: 'Can only unschedule the last target',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
if (last.type !== 'loop' || last.ownsBlock !== null) { if (last.type !== 'loop' || last.ownsBlock !== null) {
@ -1421,7 +1559,13 @@ class Context {
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: 'Expected a break target', reason: 'Expected a break target',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} }

View File

@ -296,7 +296,14 @@ export function codegenFunction(
CompilerError.invariant(globalGating != null, { CompilerError.invariant(globalGating != null, {
reason: reason:
'Bad config not caught! Expected at least one of gating or globalGating', 'Bad config not caught! Expected at least one of gating or globalGating',
loc: null, description: null,
details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
ifTest = globalGating; ifTest = globalGating;
@ -499,10 +506,16 @@ function codegenBlock(cx: Context, block: ReactiveBlock): t.BlockStatement {
continue; continue;
} }
CompilerError.invariant(temp.get(key)! === value, { CompilerError.invariant(temp.get(key)! === value, {
loc: null,
reason: 'Expected temporary value to be unchanged', reason: 'Expected temporary value to be unchanged',
description: null, description: null,
suggestions: null, suggestions: null,
details: [
{
kind: 'error',
loc: null,
message: null,
},
],
}); });
} }
cx.temp = temp; cx.temp = temp;
@ -670,7 +683,13 @@ function codegenReactiveScope(
description: `Declaration \`${printIdentifier( description: `Declaration \`${printIdentifier(
identifier, identifier,
)}\` is unnamed in scope @${scope.id}`, )}\` is unnamed in scope @${scope.id}`,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
@ -707,7 +726,13 @@ function codegenReactiveScope(
CompilerError.invariant(firstOutputIndex !== null, { CompilerError.invariant(firstOutputIndex !== null, {
reason: `Expected scope to have at least one declaration`, reason: `Expected scope to have at least one declaration`,
description: `Scope '@${scope.id}' has no declarations`, description: `Scope '@${scope.id}' has no declarations`,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
testCondition = t.binaryExpression( testCondition = t.binaryExpression(
@ -730,7 +755,13 @@ function codegenReactiveScope(
{ {
reason: `Expected to not have both change detection enabled and memoization disabled`, reason: `Expected to not have both change detection enabled and memoization disabled`,
description: `Incompatible config options`, description: `Incompatible config options`,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
}, },
); );
testCondition = t.logicalExpression( testCondition = t.logicalExpression(
@ -914,8 +945,14 @@ function codegenReactiveScope(
earlyReturnValue.value.name.kind === 'named', earlyReturnValue.value.name.kind === 'named',
{ {
reason: `Expected early return value to be promoted to a named variable`, reason: `Expected early return value to be promoted to a named variable`,
loc: earlyReturnValue.loc,
description: null, description: null,
details: [
{
kind: 'error',
loc: earlyReturnValue.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}, },
); );
@ -975,7 +1012,13 @@ function codegenTerminal(
CompilerError.invariant(terminal.init.kind === 'SequenceExpression', { CompilerError.invariant(terminal.init.kind === 'SequenceExpression', {
reason: `Expected a sequence expression init for for..in`, reason: `Expected a sequence expression init for for..in`,
description: `Got \`${terminal.init.kind}\` expression instead`, description: `Got \`${terminal.init.kind}\` expression instead`,
loc: terminal.init.loc, details: [
{
kind: 'error',
loc: terminal.init.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
if (terminal.init.instructions.length !== 2) { if (terminal.init.instructions.length !== 2) {
@ -1010,7 +1053,13 @@ function codegenTerminal(
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Expected a StoreLocal or Destructure to be assigned to the collection`, reason: `Expected a StoreLocal or Destructure to be assigned to the collection`,
description: `Found ${iterableItem.value.kind}`, description: `Found ${iterableItem.value.kind}`,
loc: iterableItem.value.loc, details: [
{
kind: 'error',
loc: iterableItem.value.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} }
@ -1027,7 +1076,13 @@ function codegenTerminal(
reason: reason:
'Destructure should never be Reassign as it would be an Object/ArrayPattern', 'Destructure should never be Reassign as it would be an Object/ArrayPattern',
description: null, description: null,
loc: iterableItem.loc, details: [
{
kind: 'error',
loc: iterableItem.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
case InstructionKind.Catch: case InstructionKind.Catch:
@ -1038,7 +1093,13 @@ function codegenTerminal(
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Unexpected ${iterableItem.value.lvalue.kind} variable in for..in collection`, reason: `Unexpected ${iterableItem.value.lvalue.kind} variable in for..in collection`,
description: null, description: null,
loc: iterableItem.loc, details: [
{
kind: 'error',
loc: iterableItem.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
default: default:
@ -1067,7 +1128,13 @@ function codegenTerminal(
{ {
reason: `Expected a single-expression sequence expression init for for..of`, reason: `Expected a single-expression sequence expression init for for..of`,
description: `Got \`${terminal.init.kind}\` expression instead`, description: `Got \`${terminal.init.kind}\` expression instead`,
loc: terminal.init.loc, details: [
{
kind: 'error',
loc: terminal.init.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}, },
); );
@ -1076,7 +1143,13 @@ function codegenTerminal(
CompilerError.invariant(terminal.test.kind === 'SequenceExpression', { CompilerError.invariant(terminal.test.kind === 'SequenceExpression', {
reason: `Expected a sequence expression test for for..of`, reason: `Expected a sequence expression test for for..of`,
description: `Got \`${terminal.init.kind}\` expression instead`, description: `Got \`${terminal.init.kind}\` expression instead`,
loc: terminal.test.loc, details: [
{
kind: 'error',
loc: terminal.test.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
if (terminal.test.instructions.length !== 2) { if (terminal.test.instructions.length !== 2) {
@ -1110,7 +1183,13 @@ function codegenTerminal(
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Expected a StoreLocal or Destructure to be assigned to the collection`, reason: `Expected a StoreLocal or Destructure to be assigned to the collection`,
description: `Found ${iterableItem.value.kind}`, description: `Found ${iterableItem.value.kind}`,
loc: iterableItem.value.loc, details: [
{
kind: 'error',
loc: iterableItem.value.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} }
@ -1131,7 +1210,13 @@ function codegenTerminal(
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Unexpected ${iterableItem.value.lvalue.kind} variable in for..of collection`, reason: `Unexpected ${iterableItem.value.lvalue.kind} variable in for..of collection`,
description: null, description: null,
loc: iterableItem.loc, details: [
{
kind: 'error',
loc: iterableItem.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
default: default:
@ -1272,7 +1357,13 @@ function codegenInstructionNullable(
reason: reason:
'Encountered a destructuring operation where some identifiers are already declared (reassignments) but others are not (declarations)', 'Encountered a destructuring operation where some identifiers are already declared (reassignments) but others are not (declarations)',
description: null, description: null,
loc: instr.loc, details: [
{
kind: 'error',
loc: instr.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} else if (hasReassign) { } else if (hasReassign) {
@ -1285,7 +1376,13 @@ function codegenInstructionNullable(
CompilerError.invariant(instr.lvalue === null, { CompilerError.invariant(instr.lvalue === null, {
reason: `Const declaration cannot be referenced as an expression`, reason: `Const declaration cannot be referenced as an expression`,
description: null, description: null,
loc: instr.value.loc, details: [
{
kind: 'error',
loc: instr.value.loc,
message: `this is ${kind}`,
},
],
suggestions: null, suggestions: null,
}); });
return createVariableDeclaration(instr.loc, 'const', [ return createVariableDeclaration(instr.loc, 'const', [
@ -1296,20 +1393,38 @@ function codegenInstructionNullable(
CompilerError.invariant(instr.lvalue === null, { CompilerError.invariant(instr.lvalue === null, {
reason: `Function declaration cannot be referenced as an expression`, reason: `Function declaration cannot be referenced as an expression`,
description: null, description: null,
loc: instr.value.loc, details: [
{
kind: 'error',
loc: instr.value.loc,
message: `this is ${kind}`,
},
],
suggestions: null, suggestions: null,
}); });
const genLvalue = codegenLValue(cx, lvalue); const genLvalue = codegenLValue(cx, lvalue);
CompilerError.invariant(genLvalue.type === 'Identifier', { CompilerError.invariant(genLvalue.type === 'Identifier', {
reason: 'Expected an identifier as a function declaration lvalue', reason: 'Expected an identifier as a function declaration lvalue',
description: null, description: null,
loc: instr.value.loc, details: [
{
kind: 'error',
loc: instr.value.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
CompilerError.invariant(value?.type === 'FunctionExpression', { CompilerError.invariant(value?.type === 'FunctionExpression', {
reason: 'Expected a function as a function declaration value', reason: 'Expected a function as a function declaration value',
description: `Got ${value == null ? String(value) : value.type} at ${printInstruction(instr)}`, description: `Got ${value == null ? String(value) : value.type} at ${printInstruction(instr)}`,
loc: instr.value.loc, details: [
{
kind: 'error',
loc: instr.value.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
return createFunctionDeclaration( return createFunctionDeclaration(
@ -1325,7 +1440,13 @@ function codegenInstructionNullable(
CompilerError.invariant(instr.lvalue === null, { CompilerError.invariant(instr.lvalue === null, {
reason: `Const declaration cannot be referenced as an expression`, reason: `Const declaration cannot be referenced as an expression`,
description: null, description: null,
loc: instr.value.loc, details: [
{
kind: 'error',
loc: instr.value.loc,
message: 'this is const',
},
],
suggestions: null, suggestions: null,
}); });
return createVariableDeclaration(instr.loc, 'let', [ return createVariableDeclaration(instr.loc, 'let', [
@ -1336,7 +1457,13 @@ function codegenInstructionNullable(
CompilerError.invariant(value !== null, { CompilerError.invariant(value !== null, {
reason: 'Expected a value for reassignment', reason: 'Expected a value for reassignment',
description: null, description: null,
loc: instr.value.loc, details: [
{
kind: 'error',
loc: instr.value.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
const expr = t.assignmentExpression( const expr = t.assignmentExpression(
@ -1369,7 +1496,13 @@ function codegenInstructionNullable(
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Expected ${kind} to have been pruned in PruneHoistedContexts`, reason: `Expected ${kind} to have been pruned in PruneHoistedContexts`,
description: null, description: null,
loc: instr.loc, details: [
{
kind: 'error',
loc: instr.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} }
@ -1387,7 +1520,14 @@ function codegenInstructionNullable(
} else if (instr.value.kind === 'ObjectMethod') { } else if (instr.value.kind === 'ObjectMethod') {
CompilerError.invariant(instr.lvalue, { CompilerError.invariant(instr.lvalue, {
reason: 'Expected object methods to have a temp lvalue', reason: 'Expected object methods to have a temp lvalue',
loc: null, description: null,
details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
cx.objectMethods.set(instr.lvalue.identifier.id, instr.value); cx.objectMethods.set(instr.lvalue.identifier.id, instr.value);
@ -1434,7 +1574,13 @@ function codegenForInit(
(instr.kind === 'let' || instr.kind === 'const'), (instr.kind === 'let' || instr.kind === 'const'),
{ {
reason: 'Expected a variable declaration', reason: 'Expected a variable declaration',
loc: init.loc, details: [
{
kind: 'error',
loc: init.loc,
message: null,
},
],
description: `Got ${instr.type}`, description: `Got ${instr.type}`,
suggestions: null, suggestions: null,
}, },
@ -1447,7 +1593,13 @@ function codegenForInit(
}); });
CompilerError.invariant(declarators.length > 0, { CompilerError.invariant(declarators.length > 0, {
reason: 'Expected a variable declaration', reason: 'Expected a variable declaration',
loc: init.loc, details: [
{
kind: 'error',
loc: init.loc,
message: null,
},
],
description: null, description: null,
suggestions: null, suggestions: null,
}); });
@ -1768,7 +1920,13 @@ function codegenInstructionValue(
CompilerError.invariant(t.isExpression(optionalValue.callee), { CompilerError.invariant(t.isExpression(optionalValue.callee), {
reason: 'v8 intrinsics are validated during lowering', reason: 'v8 intrinsics are validated during lowering',
description: null, description: null,
loc: optionalValue.callee.loc ?? null, details: [
{
kind: 'error',
loc: optionalValue.callee.loc ?? null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
value = t.optionalCallExpression( value = t.optionalCallExpression(
@ -1784,7 +1942,13 @@ function codegenInstructionValue(
CompilerError.invariant(t.isExpression(property), { CompilerError.invariant(t.isExpression(property), {
reason: 'Private names are validated during lowering', reason: 'Private names are validated during lowering',
description: null, description: null,
loc: property.loc ?? null, details: [
{
kind: 'error',
loc: property.loc ?? null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
value = t.optionalMemberExpression( value = t.optionalMemberExpression(
@ -1800,7 +1964,13 @@ function codegenInstructionValue(
reason: reason:
'Expected an optional value to resolve to a call expression or member expression', 'Expected an optional value to resolve to a call expression or member expression',
description: `Got a \`${optionalValue.type}\``, description: `Got a \`${optionalValue.type}\``,
loc: instrValue.loc, details: [
{
kind: 'error',
loc: instrValue.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} }
@ -1816,10 +1986,15 @@ function codegenInstructionValue(
t.isOptionalMemberExpression(memberExpr), t.isOptionalMemberExpression(memberExpr),
{ {
reason: reason:
'[Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression. ' + '[Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression',
`Got a \`${memberExpr.type}\``,
description: null, description: null,
loc: memberExpr.loc ?? null, details: [
{
kind: 'error',
loc: memberExpr.loc ?? null,
message: `Got: '${memberExpr.type}'`,
},
],
suggestions: null, suggestions: null,
}, },
); );
@ -1833,7 +2008,13 @@ function codegenInstructionValue(
'[Codegen] Internal error: Forget should always generate MethodCall::property ' + '[Codegen] Internal error: Forget should always generate MethodCall::property ' +
'as a MemberExpression of MethodCall::receiver', 'as a MemberExpression of MethodCall::receiver',
description: null, description: null,
loc: memberExpr.loc ?? null, details: [
{
kind: 'error',
loc: memberExpr.loc ?? null,
message: null,
},
],
suggestions: null, suggestions: null,
}, },
); );
@ -1878,7 +2059,14 @@ function codegenInstructionValue(
const method = cx.objectMethods.get(property.place.identifier.id); const method = cx.objectMethods.get(property.place.identifier.id);
CompilerError.invariant(method, { CompilerError.invariant(method, {
reason: 'Expected ObjectMethod instruction', reason: 'Expected ObjectMethod instruction',
loc: null, description: null,
details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
const loweredFunc = method.loweredFunc; const loweredFunc = method.loweredFunc;
@ -1949,7 +2137,13 @@ function codegenInstructionValue(
CompilerError.invariant(tagValue.type === 'StringLiteral', { CompilerError.invariant(tagValue.type === 'StringLiteral', {
reason: `Expected JSX tag to be an identifier or string, got \`${tagValue.type}\``, reason: `Expected JSX tag to be an identifier or string, got \`${tagValue.type}\``,
description: null, description: null,
loc: tagValue.loc ?? null, details: [
{
kind: 'error',
loc: tagValue.loc ?? null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
if (tagValue.value.indexOf(':') >= 0) { if (tagValue.value.indexOf(':') >= 0) {
@ -1969,7 +2163,13 @@ function codegenInstructionValue(
SINGLE_CHILD_FBT_TAGS.has(tagValue.value) SINGLE_CHILD_FBT_TAGS.has(tagValue.value)
) { ) {
CompilerError.invariant(instrValue.children != null, { CompilerError.invariant(instrValue.children != null, {
loc: instrValue.loc, details: [
{
kind: 'error',
loc: instrValue.loc,
message: null,
},
],
reason: 'Expected fbt element to have children', reason: 'Expected fbt element to have children',
suggestions: null, suggestions: null,
description: null, description: null,
@ -2271,7 +2471,13 @@ function codegenInstructionValue(
{ {
reason: `Unexpected StoreLocal in codegenInstructionValue`, reason: `Unexpected StoreLocal in codegenInstructionValue`,
description: null, description: null,
loc: instrValue.loc, details: [
{
kind: 'error',
loc: instrValue.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}, },
); );
@ -2301,7 +2507,13 @@ function codegenInstructionValue(
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Unexpected ${instrValue.kind} in codegenInstructionValue`, reason: `Unexpected ${instrValue.kind} in codegenInstructionValue`,
description: null, description: null,
loc: instrValue.loc, details: [
{
kind: 'error',
loc: instrValue.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} }
@ -2447,7 +2659,13 @@ function convertMemberExpressionToJsx(
CompilerError.invariant(expr.property.type === 'Identifier', { CompilerError.invariant(expr.property.type === 'Identifier', {
reason: 'Expected JSX member expression property to be a string', reason: 'Expected JSX member expression property to be a string',
description: null, description: null,
loc: expr.loc ?? null, details: [
{
kind: 'error',
loc: expr.loc ?? null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
const property = t.jsxIdentifier(expr.property.name); const property = t.jsxIdentifier(expr.property.name);
@ -2458,7 +2676,13 @@ function convertMemberExpressionToJsx(
reason: reason:
'Expected JSX member expression to be an identifier or nested member expression', 'Expected JSX member expression to be an identifier or nested member expression',
description: null, description: null,
loc: expr.object.loc ?? null, details: [
{
kind: 'error',
loc: expr.object.loc ?? null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
const object = convertMemberExpressionToJsx(expr.object); const object = convertMemberExpressionToJsx(expr.object);
@ -2482,7 +2706,13 @@ function codegenObjectPropertyKey(
CompilerError.invariant(t.isExpression(expr), { CompilerError.invariant(t.isExpression(expr), {
reason: 'Expected object property key to be an expression', reason: 'Expected object property key to be an expression',
description: null, description: null,
loc: key.name.loc, details: [
{
kind: 'error',
loc: key.name.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
return expr; return expr;
@ -2629,7 +2859,13 @@ function codegenPlace(cx: Context, place: Place): t.Expression | t.JSXText {
description: `Value for '${printPlace( description: `Value for '${printPlace(
place, place,
)}' was not set in the codegen context`, )}' was not set in the codegen context`,
loc: place.loc, details: [
{
kind: 'error',
loc: place.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
const identifier = convertIdentifier(place.identifier); const identifier = convertIdentifier(place.identifier);
@ -2642,7 +2878,13 @@ function convertIdentifier(identifier: Identifier): t.Identifier {
identifier.name !== null && identifier.name.kind === 'named', identifier.name !== null && identifier.name.kind === 'named',
{ {
reason: `Expected temporaries to be promoted to named identifiers in an earlier pass`, reason: `Expected temporaries to be promoted to named identifiers in an earlier pass`,
loc: GeneratedSource, details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
description: `identifier ${identifier.id} is unnamed`, description: `identifier ${identifier.id} is unnamed`,
suggestions: null, suggestions: null,
}, },
@ -2658,7 +2900,14 @@ function compareScopeDependency(
a.identifier.name?.kind === 'named' && b.identifier.name?.kind === 'named', a.identifier.name?.kind === 'named' && b.identifier.name?.kind === 'named',
{ {
reason: '[Codegen] Expected named identifier for dependency', reason: '[Codegen] Expected named identifier for dependency',
loc: a.identifier.loc, description: null,
details: [
{
kind: 'error',
loc: a.identifier.loc,
message: null,
},
],
}, },
); );
const aName = [ const aName = [
@ -2682,7 +2931,14 @@ function compareScopeDeclaration(
a.identifier.name?.kind === 'named' && b.identifier.name?.kind === 'named', a.identifier.name?.kind === 'named' && b.identifier.name?.kind === 'named',
{ {
reason: '[Codegen] Expected named identifier for declaration', reason: '[Codegen] Expected named identifier for declaration',
loc: a.identifier.loc, description: null,
details: [
{
kind: 'error',
loc: a.identifier.loc,
message: null,
},
],
}, },
); );
const aName = a.identifier.name.value; const aName = a.identifier.name.value;

View File

@ -75,7 +75,13 @@ export function flattenScopesWithHooksOrUseHIR(fn: HIRFunction): void {
CompilerError.invariant(terminal.kind === 'scope', { CompilerError.invariant(terminal.kind === 'scope', {
reason: `Expected block to have a scope terminal`, reason: `Expected block to have a scope terminal`,
description: `Expected block bb${block.id} to end in a scope terminal`, description: `Expected block bb${block.id} to end in a scope terminal`,
loc: terminal.loc, details: [
{
kind: 'error',
loc: terminal.loc,
message: null,
},
],
}); });
const body = fn.body.blocks.get(terminal.block)!; const body = fn.body.blocks.get(terminal.block)!;
if ( if (

View File

@ -162,7 +162,13 @@ export function inferReactiveScopeVariables(fn: HIRFunction): void {
}); });
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Invalid mutable range for scope`, reason: `Invalid mutable range for scope`,
loc: GeneratedSource, details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
description: `Scope @${scope.id} has range [${scope.range.start}:${ description: `Scope @${scope.id} has range [${scope.range.start}:${
scope.range.end scope.range.end
}] but the valid range is [1:${maxInstruction + 1}]`, }] but the valid range is [1:${maxInstruction + 1}]`,

View File

@ -159,11 +159,17 @@ class Transform extends ReactiveFunctionTransform<ReactiveScopeDependencies | nu
const merged: Array<MergedScope> = []; const merged: Array<MergedScope> = [];
function reset(): void { function reset(): void {
CompilerError.invariant(current !== null, { CompilerError.invariant(current !== null, {
loc: null,
reason: reason:
'MergeConsecutiveScopes: expected current scope to be non-null if reset()', 'MergeConsecutiveScopes: expected current scope to be non-null if reset()',
suggestions: null,
description: null, description: null,
details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null,
}); });
if (current.to > current.from + 1) { if (current.to > current.from + 1) {
merged.push(current); merged.push(current);
@ -375,10 +381,16 @@ class Transform extends ReactiveFunctionTransform<ReactiveScopeDependencies | nu
} }
const mergedScope = block[entry.from]!; const mergedScope = block[entry.from]!;
CompilerError.invariant(mergedScope.kind === 'scope', { CompilerError.invariant(mergedScope.kind === 'scope', {
loc: null,
reason: reason:
'MergeConsecutiveScopes: Expected scope starting index to be a scope', 'MergeConsecutiveScopes: Expected scope starting index to be a scope',
description: null, description: null,
details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
nextInstructions.push(mergedScope); nextInstructions.push(mergedScope);

View File

@ -323,7 +323,13 @@ function writeTerminal(writer: Writer, terminal: ReactiveTerminal): void {
CompilerError.invariant(block != null, { CompilerError.invariant(block != null, {
reason: 'Expected case to have a block', reason: 'Expected case to have a block',
description: null, description: null,
loc: case_.test?.loc ?? null, details: [
{
kind: 'error',
loc: case_.test?.loc ?? null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
writeReactiveInstructions(writer, block); writeReactiveInstructions(writer, block);

View File

@ -290,7 +290,14 @@ class PromoteInterposedTemporaries extends ReactiveFunctionVisitor<InterState> {
CompilerError.invariant(lval.identifier.name != null, { CompilerError.invariant(lval.identifier.name != null, {
reason: reason:
'PromoteInterposedTemporaries: Assignment targets not expected to be temporaries', 'PromoteInterposedTemporaries: Assignment targets not expected to be temporaries',
loc: instruction.loc, description: null,
details: [
{
kind: 'error',
loc: instruction.loc,
message: null,
},
],
}); });
} }
@ -454,7 +461,13 @@ function promoteIdentifier(identifier: Identifier, state: State): void {
reason: reason:
'promoteTemporary: Expected to be called only for temporary variables', 'promoteTemporary: Expected to be called only for temporary variables',
description: null, description: null,
loc: GeneratedSource, details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
if (state.tags.has(identifier.declarationId)) { if (state.tags.has(identifier.declarationId)) {

View File

@ -145,7 +145,14 @@ class Visitor extends ReactiveFunctionTransform<VisitorState> {
if (maybeHoistedFn != null) { if (maybeHoistedFn != null) {
CompilerError.invariant(maybeHoistedFn.kind === 'func', { CompilerError.invariant(maybeHoistedFn.kind === 'func', {
reason: '[PruneHoistedContexts] Unexpected hoisted function', reason: '[PruneHoistedContexts] Unexpected hoisted function',
loc: instruction.loc, description: null,
details: [
{
kind: 'error',
loc: instruction.loc,
message: null,
},
],
}); });
maybeHoistedFn.definition = instruction.value.lvalue.place; maybeHoistedFn.definition = instruction.value.lvalue.place;
/** /**

View File

@ -196,7 +196,14 @@ class Visitor extends ReactiveFunctionVisitor<CreateUpdate> {
): void { ): void {
CompilerError.invariant(state !== 'Create', { CompilerError.invariant(state !== 'Create', {
reason: "Visiting a terminal statement with state 'Create'", reason: "Visiting a terminal statement with state 'Create'",
loc: stmt.terminal.loc, description: null,
details: [
{
kind: 'error',
loc: stmt.terminal.loc,
message: null,
},
],
}); });
super.visitTerminal(stmt, state); super.visitTerminal(stmt, state);
} }

View File

@ -264,7 +264,13 @@ class State {
CompilerError.invariant(identifierNode !== undefined, { CompilerError.invariant(identifierNode !== undefined, {
reason: 'Expected identifier to be initialized', reason: 'Expected identifier to be initialized',
description: `[${id}] operand=${printPlace(place)} for identifier declaration ${identifier}`, description: `[${id}] operand=${printPlace(place)} for identifier declaration ${identifier}`,
loc: place.loc, details: [
{
kind: 'error',
loc: place.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
identifierNode.scopes.add(scope.id); identifierNode.scopes.add(scope.id);
@ -286,7 +292,13 @@ function computeMemoizedIdentifiers(state: State): Set<DeclarationId> {
CompilerError.invariant(node !== undefined, { CompilerError.invariant(node !== undefined, {
reason: `Expected a node for all identifiers, none found for \`${id}\``, reason: `Expected a node for all identifiers, none found for \`${id}\``,
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
if (node.seen) { if (node.seen) {
@ -328,7 +340,13 @@ function computeMemoizedIdentifiers(state: State): Set<DeclarationId> {
CompilerError.invariant(node !== undefined, { CompilerError.invariant(node !== undefined, {
reason: 'Expected a node for all scopes', reason: 'Expected a node for all scopes',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
if (node.seen) { if (node.seen) {
@ -977,7 +995,13 @@ class CollectDependenciesVisitor extends ReactiveFunctionVisitor<
CompilerError.invariant(identifierNode !== undefined, { CompilerError.invariant(identifierNode !== undefined, {
reason: 'Expected identifier to be initialized', reason: 'Expected identifier to be initialized',
description: null, description: null,
loc: stmt.terminal.loc, details: [
{
kind: 'error',
loc: stmt.terminal.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
for (const scope of scopes) { for (const scope of scopes) {
@ -1002,7 +1026,13 @@ class CollectDependenciesVisitor extends ReactiveFunctionVisitor<
CompilerError.invariant(identifierNode !== undefined, { CompilerError.invariant(identifierNode !== undefined, {
reason: 'Expected identifier to be initialized', reason: 'Expected identifier to be initialized',
description: null, description: null,
loc: reassignment.loc, details: [
{
kind: 'error',
loc: reassignment.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
for (const scope of scopes) { for (const scope of scopes) {

View File

@ -186,7 +186,13 @@ class Scopes {
CompilerError.invariant(last === next, { CompilerError.invariant(last === next, {
reason: 'Mismatch push/pop calls', reason: 'Mismatch push/pop calls',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} }

View File

@ -97,7 +97,13 @@ export function eliminateRedundantPhi(
CompilerError.invariant(same !== null, { CompilerError.invariant(same !== null, {
reason: 'Expected phis to be non-empty', reason: 'Expected phis to be non-empty',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
rewrites.set(phi.place.identifier, same); rewrites.set(phi.place.identifier, same);
@ -149,12 +155,26 @@ export function eliminateRedundantPhi(
for (const phi of block.phis) { for (const phi of block.phis) {
CompilerError.invariant(!rewrites.has(phi.place.identifier), { CompilerError.invariant(!rewrites.has(phi.place.identifier), {
reason: '[EliminateRedundantPhis]: rewrite not complete', reason: '[EliminateRedundantPhis]: rewrite not complete',
loc: phi.place.loc, description: null,
details: [
{
kind: 'error',
loc: phi.place.loc,
message: null,
},
],
}); });
for (const [, operand] of phi.operands) { for (const [, operand] of phi.operands) {
CompilerError.invariant(!rewrites.has(operand.identifier), { CompilerError.invariant(!rewrites.has(operand.identifier), {
reason: '[EliminateRedundantPhis]: rewrite not complete', reason: '[EliminateRedundantPhis]: rewrite not complete',
loc: phi.place.loc, description: null,
details: [
{
kind: 'error',
loc: phi.place.loc,
message: null,
},
],
}); });
} }
} }

View File

@ -70,7 +70,13 @@ class SSABuilder {
CompilerError.invariant(this.#current !== null, { CompilerError.invariant(this.#current !== null, {
reason: 'we need to be in a block to access state!', reason: 'we need to be in a block to access state!',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
return this.#states.get(this.#current)!; return this.#states.get(this.#current)!;
@ -253,7 +259,13 @@ function enterSSAImpl(
CompilerError.invariant(!visitedBlocks.has(block), { CompilerError.invariant(!visitedBlocks.has(block), {
reason: `found a cycle! visiting bb${block.id} again`, reason: `found a cycle! visiting bb${block.id} again`,
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
@ -266,7 +278,13 @@ function enterSSAImpl(
CompilerError.invariant(func.context.length === 0, { CompilerError.invariant(func.context.length === 0, {
reason: `Expected function context to be empty for outer function declarations`, reason: `Expected function context to be empty for outer function declarations`,
description: null, description: null,
loc: func.loc, details: [
{
kind: 'error',
loc: func.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
func.params = func.params.map(param => { func.params = func.params.map(param => {
@ -295,7 +313,13 @@ function enterSSAImpl(
reason: reason:
'Expected function expression entry block to have zero predecessors', 'Expected function expression entry block to have zero predecessors',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
entry.preds.add(blockId); entry.preds.add(blockId);

View File

@ -59,7 +59,13 @@ export function rewriteInstructionKindsBasedOnReassignment(
{ {
reason: `Expected variable not to be defined prior to declaration`, reason: `Expected variable not to be defined prior to declaration`,
description: `${printPlace(lvalue.place)} was already defined`, description: `${printPlace(lvalue.place)} was already defined`,
loc: lvalue.place.loc, details: [
{
kind: 'error',
loc: lvalue.place.loc,
message: null,
},
],
}, },
); );
declarations.set(lvalue.place.identifier.declarationId, lvalue); declarations.set(lvalue.place.identifier.declarationId, lvalue);
@ -77,7 +83,13 @@ export function rewriteInstructionKindsBasedOnReassignment(
{ {
reason: `Expected variable not to be defined prior to declaration`, reason: `Expected variable not to be defined prior to declaration`,
description: `${printPlace(lvalue.place)} was already defined`, description: `${printPlace(lvalue.place)} was already defined`,
loc: lvalue.place.loc, details: [
{
kind: 'error',
loc: lvalue.place.loc,
message: null,
},
],
}, },
); );
declarations.set(lvalue.place.identifier.declarationId, lvalue); declarations.set(lvalue.place.identifier.declarationId, lvalue);
@ -101,7 +113,13 @@ export function rewriteInstructionKindsBasedOnReassignment(
description: `other places were \`${kind}\` but '${printPlace( description: `other places were \`${kind}\` but '${printPlace(
place, place,
)}' is const`, )}' is const`,
loc: place.loc, details: [
{
kind: 'error',
loc: place.loc,
message: 'Expected consistent kind for destructuring',
},
],
suggestions: null, suggestions: null,
}, },
); );
@ -114,7 +132,13 @@ export function rewriteInstructionKindsBasedOnReassignment(
CompilerError.invariant(block.kind !== 'value', { CompilerError.invariant(block.kind !== 'value', {
reason: `TODO: Handle reassignment in a value block where the original declaration was removed by dead code elimination (DCE)`, reason: `TODO: Handle reassignment in a value block where the original declaration was removed by dead code elimination (DCE)`,
description: null, description: null,
loc: place.loc, details: [
{
kind: 'error',
loc: place.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
declarations.set(place.identifier.declarationId, lvalue); declarations.set(place.identifier.declarationId, lvalue);
@ -125,7 +149,13 @@ export function rewriteInstructionKindsBasedOnReassignment(
description: `Other places were \`${kind}\` but '${printPlace( description: `Other places were \`${kind}\` but '${printPlace(
place, place,
)}' is const`, )}' is const`,
loc: place.loc, details: [
{
kind: 'error',
loc: place.loc,
message: 'Expected consistent kind for destructuring',
},
],
suggestions: null, suggestions: null,
}, },
); );
@ -138,7 +168,13 @@ export function rewriteInstructionKindsBasedOnReassignment(
description: `Other places were \`${kind}\` but '${printPlace( description: `Other places were \`${kind}\` but '${printPlace(
place, place,
)}' is reassigned`, )}' is reassigned`,
loc: place.loc, details: [
{
kind: 'error',
loc: place.loc,
message: 'Expected consistent kind for destructuring',
},
],
suggestions: null, suggestions: null,
}, },
); );
@ -150,7 +186,13 @@ export function rewriteInstructionKindsBasedOnReassignment(
CompilerError.invariant(kind !== null, { CompilerError.invariant(kind !== null, {
reason: 'Expected at least one operand', reason: 'Expected at least one operand',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
lvalue.kind = kind; lvalue.kind = kind;
@ -163,7 +205,13 @@ export function rewriteInstructionKindsBasedOnReassignment(
CompilerError.invariant(declaration !== undefined, { CompilerError.invariant(declaration !== undefined, {
reason: `Expected variable to have been defined`, reason: `Expected variable to have been defined`,
description: `No declaration for ${printPlace(lvalue)}`, description: `No declaration for ${printPlace(lvalue)}`,
loc: lvalue.loc, details: [
{
kind: 'error',
loc: lvalue.loc,
message: null,
},
],
}); });
declaration.kind = InstructionKind.Let; declaration.kind = InstructionKind.Let;
break; break;

View File

@ -616,7 +616,13 @@ class Unifier {
CompilerError.invariant(type.operands.length > 0, { CompilerError.invariant(type.operands.length > 0, {
reason: 'there should be at least one operand', reason: 'there should be at least one operand',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });

View File

@ -21,7 +21,13 @@ export default class DisjointSet<T> {
CompilerError.invariant(first != null, { CompilerError.invariant(first != null, {
reason: 'Expected set to be non-empty', reason: 'Expected set to be non-empty',
description: null, description: null,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
/* /*

View File

@ -164,7 +164,13 @@ function parseConfigPragmaEnvironmentForTest(
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: 'Internal error, could not parse config from pragma string', reason: 'Internal error, could not parse config from pragma string',
description: `${fromZodError(config.error)}`, description: `${fromZodError(config.error)}`,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} }
@ -248,7 +254,13 @@ function parseConfigStringAsJS(
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: 'Failed to parse config pragma as JavaScript object', reason: 'Failed to parse config pragma as JavaScript object',
description: `Could not parse: ${configString}. Error: ${error}`, description: `Could not parse: ${configString}. Error: ${error}`,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} }
@ -279,7 +291,13 @@ function parseConfigStringAsJS(
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: 'Invalid environment configuration in config pragma', reason: 'Invalid environment configuration in config pragma',
description: `${fromZodError(validatedEnvironment.error)}`, description: `${fromZodError(validatedEnvironment.error)}`,
loc: null, details: [
{
kind: 'error',
loc: null,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
} }

View File

@ -106,12 +106,19 @@ function visit(
} }
CompilerError.invariant(false, { CompilerError.invariant(false, {
reason: `Expected all references to a variable to be consistently local or context references`, reason:
loc: place.loc, 'Expected all references to a variable to be consistently local or context references',
description: `Identifier ${printPlace( description: `Identifier ${printPlace(
place, place,
)} is referenced as a ${kind} variable, but was previously referenced as a ${prev} variable`, )} is referenced as a ${kind} variable, but was previously referenced as a ${prev.kind} variable`,
suggestions: null, suggestions: null,
details: [
{
kind: 'error',
loc: place.loc,
message: `this is ${prev.kind}`,
},
],
}); });
} }
} }

View File

@ -40,7 +40,7 @@ export function validateLocalsNotReassignedAfterRender(fn: HIRFunction): void {
category: ErrorCategory.Immutability, category: ErrorCategory.Immutability,
reason: 'Cannot reassign variable after render completes', reason: 'Cannot reassign variable after render completes',
description: `Reassigning ${variable} after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead.`, description: `Reassigning ${variable} after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead.`,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: reassignment.loc, loc: reassignment.loc,
message: `Cannot reassign ${variable} after render completes`, message: `Cannot reassign ${variable} after render completes`,
@ -96,7 +96,7 @@ function getContextReassignment(
reason: 'Cannot reassign variable in async function', reason: 'Cannot reassign variable in async function',
description: description:
'Reassigning a variable in an async function can cause inconsistent behavior on subsequent renders. Consider using state instead', 'Reassigning a variable in an async function can cause inconsistent behavior on subsequent renders. Consider using state instead',
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: reassignment.loc, loc: reassignment.loc,
message: `Cannot reassign ${variable}`, message: `Cannot reassign ${variable}`,
@ -191,7 +191,14 @@ function getContextReassignment(
for (const operand of operands) { for (const operand of operands) {
CompilerError.invariant(operand.effect !== Effect.Unknown, { CompilerError.invariant(operand.effect !== Effect.Unknown, {
reason: `Expected effects to be inferred prior to ValidateLocalsNotReassignedAfterRender`, reason: `Expected effects to be inferred prior to ValidateLocalsNotReassignedAfterRender`,
loc: operand.loc, description: null,
details: [
{
kind: 'error',
loc: operand.loc,
message: '',
},
],
}); });
const reassignment = reassigningFunctions.get( const reassignment = reassigningFunctions.get(
operand.identifier.id, operand.identifier.id,

View File

@ -83,7 +83,14 @@ export function validateNoDerivedComputationsInEffects(fn: HIRFunction): void {
const dependencies: Array<IdentifierId> = deps.elements.map(dep => { const dependencies: Array<IdentifierId> = deps.elements.map(dep => {
CompilerError.invariant(dep.kind === 'Identifier', { CompilerError.invariant(dep.kind === 'Identifier', {
reason: `Dependency is checked as a place above`, reason: `Dependency is checked as a place above`,
loc: value.loc, description: null,
details: [
{
kind: 'error',
loc: value.loc,
message: 'this is checked as a place above',
},
],
}); });
return locals.get(dep.identifier.id) ?? dep.identifier.id; return locals.get(dep.identifier.id) ?? dep.identifier.id;
}); });

View File

@ -69,12 +69,12 @@ export function validateNoFreezingKnownMutableFunctions(
reason: 'Cannot modify local variables after render completes', reason: 'Cannot modify local variables after render completes',
description: `This argument is a function which may reassign or mutate ${variable} after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead.`, description: `This argument is a function which may reassign or mutate ${variable} after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead.`,
}) })
.withDetail({ .withDetails({
kind: 'error', kind: 'error',
loc: operand.loc, loc: operand.loc,
message: `This function may (indirectly) reassign or modify ${variable} after render`, message: `This function may (indirectly) reassign or modify ${variable} after render`,
}) })
.withDetail({ .withDetails({
kind: 'error', kind: 'error',
loc: effect.value.loc, loc: effect.value.loc,
message: `This modifies ${variable}`, message: `This modifies ${variable}`,

View File

@ -45,7 +45,7 @@ export function validateNoImpureFunctionsInRender(
: '') + : '') +
'Calling an impure function can produce unstable results that update unpredictably when the component happens to re-render. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)', 'Calling an impure function can produce unstable results that update unpredictably when the component happens to re-render. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)',
suggestions: null, suggestions: null,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: callee.loc, loc: callee.loc,
message: 'Cannot call impure function', message: 'Cannot call impure function',

View File

@ -40,7 +40,7 @@ export function validateNoJSXInTryStatement(
category: ErrorCategory.ErrorBoundaries, category: ErrorCategory.ErrorBoundaries,
reason: 'Avoid constructing JSX within try/catch', reason: 'Avoid constructing JSX within try/catch',
description: `React does not immediately render components when JSX is rendered, so any errors from this component will not be caught by the try/catch. To catch errors in rendering a given component, wrap that component in an error boundary. (https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary)`, description: `React does not immediately render components when JSX is rendered, so any errors from this component will not be caught by the try/catch. To catch errors in rendering a given component, wrap that component in an error boundary. (https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary)`,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: value.loc, loc: value.loc,
message: 'Avoid constructing JSX within try/catch', message: 'Avoid constructing JSX within try/catch',

View File

@ -57,8 +57,14 @@ function makeRefId(id: number): RefId {
CompilerError.invariant(id >= 0 && Number.isInteger(id), { CompilerError.invariant(id >= 0 && Number.isInteger(id), {
reason: 'Expected identifier id to be a non-negative integer', reason: 'Expected identifier id to be a non-negative integer',
description: null, description: null,
loc: null,
suggestions: null, suggestions: null,
details: [
{
kind: 'error',
loc: null,
message: null,
},
],
}); });
return id as RefId; return id as RefId;
} }
@ -191,19 +197,40 @@ function tyEqual(a: RefAccessType, b: RefAccessType): boolean {
case 'Guard': case 'Guard':
CompilerError.invariant(b.kind === 'Guard', { CompilerError.invariant(b.kind === 'Guard', {
reason: 'Expected ref value', reason: 'Expected ref value',
loc: null, description: null,
details: [
{
kind: 'error',
loc: null,
message: null,
},
],
}); });
return a.refId === b.refId; return a.refId === b.refId;
case 'RefValue': case 'RefValue':
CompilerError.invariant(b.kind === 'RefValue', { CompilerError.invariant(b.kind === 'RefValue', {
reason: 'Expected ref value', reason: 'Expected ref value',
loc: null, description: null,
details: [
{
kind: 'error',
loc: null,
message: null,
},
],
}); });
return a.loc == b.loc; return a.loc == b.loc;
case 'Structure': { case 'Structure': {
CompilerError.invariant(b.kind === 'Structure', { CompilerError.invariant(b.kind === 'Structure', {
reason: 'Expected structure', reason: 'Expected structure',
loc: null, description: null,
details: [
{
kind: 'error',
loc: null,
message: null,
},
],
}); });
const fnTypesEqual = const fnTypesEqual =
(a.fn === null && b.fn === null) || (a.fn === null && b.fn === null) ||
@ -242,7 +269,14 @@ function joinRefAccessTypes(...types: Array<RefAccessType>): RefAccessType {
a.kind === 'Structure' && b.kind === 'Structure', a.kind === 'Structure' && b.kind === 'Structure',
{ {
reason: 'Expected structure', reason: 'Expected structure',
loc: null, description: null,
details: [
{
kind: 'error',
loc: null,
message: null,
},
],
}, },
); );
const fn = const fn =
@ -471,7 +505,7 @@ function validateNoRefAccessInRenderImpl(
category: ErrorCategory.Refs, category: ErrorCategory.Refs,
reason: 'Cannot access refs during render', reason: 'Cannot access refs during render',
description: ERROR_DESCRIPTION, description: ERROR_DESCRIPTION,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: callee.loc, loc: callee.loc,
message: `This function accesses a ref value`, message: `This function accesses a ref value`,
@ -708,7 +742,14 @@ function validateNoRefAccessInRenderImpl(
CompilerError.invariant(!env.hasChanged(), { CompilerError.invariant(!env.hasChanged(), {
reason: 'Ref type environment did not converge', reason: 'Ref type environment did not converge',
loc: null, description: null,
details: [
{
kind: 'error',
loc: null,
message: null,
},
],
}); });
return Ok( return Ok(
@ -734,7 +775,7 @@ function guardCheck(errors: CompilerError, operand: Place, env: Env): void {
category: ErrorCategory.Refs, category: ErrorCategory.Refs,
reason: 'Cannot access refs during render', reason: 'Cannot access refs during render',
description: ERROR_DESCRIPTION, description: ERROR_DESCRIPTION,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: operand.loc, loc: operand.loc,
message: `Cannot access ref value during render`, message: `Cannot access ref value during render`,
@ -758,7 +799,7 @@ function validateNoRefValueAccess(
category: ErrorCategory.Refs, category: ErrorCategory.Refs,
reason: 'Cannot access refs during render', reason: 'Cannot access refs during render',
description: ERROR_DESCRIPTION, description: ERROR_DESCRIPTION,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: (type.kind === 'RefValue' && type.loc) || operand.loc, loc: (type.kind === 'RefValue' && type.loc) || operand.loc,
message: `Cannot access ref value during render`, message: `Cannot access ref value during render`,
@ -784,7 +825,7 @@ function validateNoRefPassedToFunction(
category: ErrorCategory.Refs, category: ErrorCategory.Refs,
reason: 'Cannot access refs during render', reason: 'Cannot access refs during render',
description: ERROR_DESCRIPTION, description: ERROR_DESCRIPTION,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: (type.kind === 'RefValue' && type.loc) || loc, loc: (type.kind === 'RefValue' && type.loc) || loc,
message: `Passing a ref to a function may read its value during render`, message: `Passing a ref to a function may read its value during render`,
@ -806,7 +847,7 @@ function validateNoRefUpdate(
category: ErrorCategory.Refs, category: ErrorCategory.Refs,
reason: 'Cannot access refs during render', reason: 'Cannot access refs during render',
description: ERROR_DESCRIPTION, description: ERROR_DESCRIPTION,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: (type.kind === 'RefValue' && type.loc) || loc, loc: (type.kind === 'RefValue' && type.loc) || loc,
message: `Cannot update ref during render`, message: `Cannot update ref during render`,
@ -827,7 +868,7 @@ function validateNoDirectRefValueAccess(
category: ErrorCategory.Refs, category: ErrorCategory.Refs,
reason: 'Cannot access refs during render', reason: 'Cannot access refs during render',
description: ERROR_DESCRIPTION, description: ERROR_DESCRIPTION,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: type.loc ?? operand.loc, loc: type.loc ?? operand.loc,
message: `Cannot access ref value during render`, message: `Cannot access ref value during render`,

View File

@ -107,7 +107,7 @@ export function validateNoSetStateInEffects(
'Calling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. ' + 'Calling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. ' +
'(https://react.dev/learn/you-might-not-need-an-effect)', '(https://react.dev/learn/you-might-not-need-an-effect)',
suggestions: null, suggestions: null,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: setState.loc, loc: setState.loc,
message: message:

View File

@ -102,7 +102,14 @@ function validateNoSetStateInRenderImpl(
case 'StartMemoize': { case 'StartMemoize': {
CompilerError.invariant(activeManualMemoId === null, { CompilerError.invariant(activeManualMemoId === null, {
reason: 'Unexpected nested StartMemoize instructions', reason: 'Unexpected nested StartMemoize instructions',
loc: instr.value.loc, description: null,
details: [
{
kind: 'error',
loc: instr.value.loc,
message: null,
},
],
}); });
activeManualMemoId = instr.value.manualMemoId; activeManualMemoId = instr.value.manualMemoId;
break; break;
@ -113,7 +120,14 @@ function validateNoSetStateInRenderImpl(
{ {
reason: reason:
'Expected FinishMemoize to align with previous StartMemoize instruction', 'Expected FinishMemoize to align with previous StartMemoize instruction',
loc: instr.value.loc, description: null,
details: [
{
kind: 'error',
loc: instr.value.loc,
message: null,
},
],
}, },
); );
activeManualMemoId = null; activeManualMemoId = null;
@ -134,7 +148,7 @@ function validateNoSetStateInRenderImpl(
description: description:
'Each time the memo callback is evaluated it will change state. This can cause a memoization dependency to change, running the memo function again and causing an infinite loop. Instead of setting state in useMemo(), prefer deriving the value during render. (https://react.dev/reference/react/useState)', 'Each time the memo callback is evaluated it will change state. This can cause a memoization dependency to change, running the memo function again and causing an infinite loop. Instead of setting state in useMemo(), prefer deriving the value during render. (https://react.dev/reference/react/useState)',
suggestions: null, suggestions: null,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: callee.loc, loc: callee.loc,
message: 'Found setState() within useMemo()', message: 'Found setState() within useMemo()',
@ -149,7 +163,7 @@ function validateNoSetStateInRenderImpl(
description: description:
'Calling setState during render will trigger another render, and can lead to infinite loops. (https://react.dev/reference/react/useState)', 'Calling setState during render will trigger another render, and can lead to infinite loops. (https://react.dev/reference/react/useState)',
suggestions: null, suggestions: null,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: callee.loc, loc: callee.loc,
message: 'Found setState() in render', message: 'Found setState() in render',

View File

@ -245,7 +245,14 @@ function validateInferredDep(
CompilerError.invariant(dep.identifier.name?.kind === 'named', { CompilerError.invariant(dep.identifier.name?.kind === 'named', {
reason: reason:
'ValidatePreservedManualMemoization: expected scope dependency to be named', 'ValidatePreservedManualMemoization: expected scope dependency to be named',
loc: GeneratedSource, description: null,
details: [
{
kind: 'error',
loc: GeneratedSource,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
normalizedDep = { normalizedDep = {
@ -303,7 +310,7 @@ function validateInferredDep(
.join('') .join('')
.trim(), .trim(),
suggestions: null, suggestions: null,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: memoLocation, loc: memoLocation,
message: 'Could not preserve existing manual memoization', message: 'Could not preserve existing manual memoization',
@ -495,7 +502,13 @@ class Visitor extends ReactiveFunctionVisitor<VisitorState> {
CompilerError.invariant(state.manualMemoState == null, { CompilerError.invariant(state.manualMemoState == null, {
reason: 'Unexpected nested StartMemoize instructions', reason: 'Unexpected nested StartMemoize instructions',
description: `Bad manual memoization ids: ${state.manualMemoState?.manualMemoId}, ${value.manualMemoId}`, description: `Bad manual memoization ids: ${state.manualMemoState?.manualMemoId}, ${value.manualMemoId}`,
loc: value.loc, details: [
{
kind: 'error',
loc: value.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}); });
@ -540,7 +553,7 @@ class Visitor extends ReactiveFunctionVisitor<VisitorState> {
'React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. ', 'React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. ',
'This dependency may be mutated later, which could cause the value to change unexpectedly.', 'This dependency may be mutated later, which could cause the value to change unexpectedly.',
].join(''), ].join(''),
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc, loc,
message: 'This dependency may be modified later', message: 'This dependency may be modified later',
@ -556,7 +569,13 @@ class Visitor extends ReactiveFunctionVisitor<VisitorState> {
{ {
reason: 'Unexpected mismatch between StartMemoize and FinishMemoize', reason: 'Unexpected mismatch between StartMemoize and FinishMemoize',
description: `Encountered StartMemoize id=${state.manualMemoState?.manualMemoId} followed by FinishMemoize id=${value.manualMemoId}`, description: `Encountered StartMemoize id=${state.manualMemoState?.manualMemoId} followed by FinishMemoize id=${value.manualMemoId}`,
loc: value.loc, details: [
{
kind: 'error',
loc: value.loc,
message: null,
},
],
suggestions: null, suggestions: null,
}, },
); );
@ -591,7 +610,7 @@ class Visitor extends ReactiveFunctionVisitor<VisitorState> {
] ]
.join('') .join('')
.trim(), .trim(),
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc, loc,
message: 'Could not preserve existing memoization', message: 'Could not preserve existing memoization',

View File

@ -69,12 +69,12 @@ export function validateStaticComponents(
reason: 'Cannot create components during render', reason: 'Cannot create components during render',
description: `Components created during render will reset their state each time they are created. Declare components outside of render. `, description: `Components created during render will reset their state each time they are created. Declare components outside of render. `,
}) })
.withDetail({ .withDetails({
kind: 'error', kind: 'error',
loc: value.tag.loc, loc: value.tag.loc,
message: 'This component is created during render', message: 'This component is created during render',
}) })
.withDetail({ .withDetails({
kind: 'error', kind: 'error',
loc: location, loc: location,
message: 'The component is created during render here', message: 'The component is created during render here',

View File

@ -79,7 +79,7 @@ export function validateUseMemo(fn: HIRFunction): Result<void, CompilerError> {
description: description:
'useMemo() callbacks are called by React to cache calculations across re-renders. They should not take parameters. Instead, directly reference the props, state, or local variables needed for the computation.', 'useMemo() callbacks are called by React to cache calculations across re-renders. They should not take parameters. Instead, directly reference the props, state, or local variables needed for the computation.',
suggestions: null, suggestions: null,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc, loc,
message: 'Callbacks with parameters are not supported', message: 'Callbacks with parameters are not supported',
@ -96,7 +96,7 @@ export function validateUseMemo(fn: HIRFunction): Result<void, CompilerError> {
description: description:
'useMemo() callbacks are called once and must synchronously return a value.', 'useMemo() callbacks are called once and must synchronously return a value.',
suggestions: null, suggestions: null,
}).withDetail({ }).withDetails({
kind: 'error', kind: 'error',
loc: body.loc, loc: body.loc,
message: 'Async and generator functions are not supported', message: 'Async and generator functions are not supported',

View File

@ -31,13 +31,13 @@ Found 1 error:
Invariant: [InferMutationAliasingEffects] Expected value kind to be initialized Invariant: [InferMutationAliasingEffects] Expected value kind to be initialized
<unknown> thunk$14. <unknown> thunk$14
error.bug-infer-mutation-aliasing-effects.ts:10:22 error.bug-infer-mutation-aliasing-effects.ts:10:22
8 | function thunk(action) { 8 | function thunk(action) {
9 | if (typeof action === 'function') { 9 | if (typeof action === 'function') {
> 10 | return action(thunk, () => stateRef.current, extraArg); > 10 | return action(thunk, () => stateRef.current, extraArg);
| ^^^^^ [InferMutationAliasingEffects] Expected value kind to be initialized | ^^^^^ this is uninitialized
11 | } else { 11 | } else {
12 | dispatch(action); 12 | dispatch(action);
13 | return undefined; 13 | return undefined;

View File

@ -16,13 +16,15 @@ const YearsAndMonthsSince = () => {
``` ```
Found 1 error: Found 1 error:
Invariant: [Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression. Got a `Identifier` Invariant: [Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression
error.bug-invariant-codegen-methodcall.ts:3:17 error.bug-invariant-codegen-methodcall.ts:3:17
1 | const YearsAndMonthsSince = () => { 1 | const YearsAndMonthsSince = () => {
2 | const diff = foo(); 2 | const diff = foo();
> 3 | const months = Math.floor(diff.bar()); > 3 | const months = Math.floor(diff.bar());
| ^^^^^^^^^^ [Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression. Got a `Identifier` | ^^^^^^^^^^ Got: 'Identifier'
4 | return <>{months}</>; 4 | return <>{months}</>;
5 | }; 5 | };
6 | 6 |

View File

@ -29,7 +29,7 @@ Found 1 error:
Invariant: Expected consistent kind for destructuring Invariant: Expected consistent kind for destructuring
Other places were `Reassign` but 'mutate? #t8$46[7:9]{reactive}' is const. Other places were `Reassign` but 'mutate? #t8$46[7:9]{reactive}' is const
error.bug-invariant-expected-consistent-destructuring.ts:9:9 error.bug-invariant-expected-consistent-destructuring.ts:9:9
7 | 7 |

View File

@ -31,13 +31,13 @@ Found 1 error:
Invariant: Expected all references to a variable to be consistently local or context references Invariant: Expected all references to a variable to be consistently local or context references
Identifier <unknown> err$7 is referenced as a context variable, but was previously referenced as a [object Object] variable. Identifier <unknown> err$7 is referenced as a context variable, but was previously referenced as a local variable
error.bug-invariant-local-or-context-references.ts:15:13 error.bug-invariant-local-or-context-references.ts:15:13
13 | setState(_prevState => ({ 13 | setState(_prevState => ({
14 | loading: false, 14 | loading: false,
> 15 | error: err, > 15 | error: err,
| ^^^ Expected all references to a variable to be consistently local or context references | ^^^ this is local
16 | })); 16 | }));
17 | } 17 | }
18 | }; 18 | };

View File

@ -21,11 +21,13 @@ Found 1 error:
Invariant: Unexpected terminal in optional Invariant: Unexpected terminal in optional
error.bug-invariant-unexpected-terminal-in-optional.ts:3:16 error.bug-invariant-unexpected-terminal-in-optional.ts:3:16
1 | const Foo = ({json}) => { 1 | const Foo = ({json}) => {
2 | try { 2 | try {
> 3 | const foo = JSON.parse(json)?.foo; > 3 | const foo = JSON.parse(json)?.foo;
| ^^^^ Unexpected terminal in optional | ^^^^ Unexpected maybe-throw in optional
4 | return <span>{foo}</span>; 4 | return <span>{foo}</span>;
5 | } catch { 5 | } catch {
6 | return null; 6 | return null;

View File

@ -24,7 +24,7 @@ Found 1 error:
Invariant: Expected temporaries to be promoted to named identifiers in an earlier pass Invariant: Expected temporaries to be promoted to named identifiers in an earlier pass
identifier 15 is unnamed. identifier 15 is unnamed
``` ```

View File

@ -18,11 +18,13 @@ Found 1 error:
Invariant: Const declaration cannot be referenced as an expression Invariant: Const declaration cannot be referenced as an expression
error.call-args-destructuring-asignment-complex.ts:3:9 error.call-args-destructuring-asignment-complex.ts:3:9
1 | function Component(props) { 1 | function Component(props) {
2 | let x = makeObject(); 2 | let x = makeObject();
> 3 | x.foo(([[x]] = makeObject())); > 3 | x.foo(([[x]] = makeObject()));
| ^^^^^ Const declaration cannot be referenced as an expression | ^^^^^ this is Const
4 | return x; 4 | return x;
5 | } 5 | }
6 | 6 |

View File

@ -24,13 +24,15 @@ export const FIXTURE_ENTRYPOINT = {
``` ```
Found 1 error: Found 1 error:
Invariant: [Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression. Got a `Identifier` Invariant: [Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression
error.todo-nested-method-calls-lower-property-load-into-temporary.ts:6:14 error.todo-nested-method-calls-lower-property-load-into-temporary.ts:6:14
4 | function Component({}) { 4 | function Component({}) {
5 | const items = makeArray(0, 1, 2, null, 4, false, 6); 5 | const items = makeArray(0, 1, 2, null, 4, false, 6);
> 6 | const max = Math.max(2, items.push(5), ...other); > 6 | const max = Math.max(2, items.push(5), ...other);
| ^^^^^^^^ [Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression. Got a `Identifier` | ^^^^^^^^ Got: 'Identifier'
7 | return max; 7 | return max;
8 | } 8 | }
9 | 9 |

View File

@ -23,13 +23,13 @@ Found 1 error:
Invariant: [InferMutationAliasingEffects] Expected value kind to be initialized Invariant: [InferMutationAliasingEffects] Expected value kind to be initialized
<unknown> hasErrors_0$15:TFunction. <unknown> hasErrors_0$15:TFunction
error.todo-repro-named-function-with-shadowed-local-same-name.ts:9:9 error.todo-repro-named-function-with-shadowed-local-same-name.ts:9:9
7 | return hasErrors; 7 | return hasErrors;
8 | } 8 | }
> 9 | return hasErrors(); > 9 | return hasErrors();
| ^^^^^^^^^ [InferMutationAliasingEffects] Expected value kind to be initialized | ^^^^^^^^^ this is uninitialized
10 | } 10 | }
11 | 11 |
``` ```

View File

@ -24,13 +24,13 @@ Found 1 error:
Invariant: [InferMutationAliasingEffects] Expected value kind to be initialized Invariant: [InferMutationAliasingEffects] Expected value kind to be initialized
<unknown> hasErrors_0$15:TFunction. <unknown> hasErrors_0$15:TFunction
error.todo-repro-named-function-with-shadowed-local-same-name.ts:10:9 error.todo-repro-named-function-with-shadowed-local-same-name.ts:10:9
8 | return hasErrors; 8 | return hasErrors;
9 | } 9 | }
> 10 | return hasErrors(); > 10 | return hasErrors();
| ^^^^^^^^^ [InferMutationAliasingEffects] Expected value kind to be initialized | ^^^^^^^^^ this is uninitialized
11 | } 11 | }
12 | 12 |
``` ```