Skip to content

Fix stack overflow on circular reference after satisfies#3807

Draft
Copilot wants to merge 2 commits into
mainfrom
copilot/fix-circular-reference-panic
Draft

Fix stack overflow on circular reference after satisfies#3807
Copilot wants to merge 2 commits into
mainfrom
copilot/fix-circular-reference-panic

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 12, 2026

const f = () => 42 satisfies typeof f causes a stack overflow due to infinite recursion between checkSatisfiesExpression → error reporting → typeToStringserializeReturnTypeForSignaturepseudoTypeToTypegetRegularTypeOfExpressioncheckExpressionExcheckSatisfiesExpression.

The satisfies check fails (number vs () => any), triggers error reporting, which serializes the function type, which re-evaluates the satisfies expression, which fails again, ad infinitum.

  • Pass checkMode through to checkSatisfiesExpression and skip the assignability check when CheckModeTypeOnly is set (the mode used by getTypeOfExpression in the serialization path). The check is purely diagnostic—exprType is always returned regardless of the result.

Now correctly produces the expected errors:

TS7023: 'f' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
TS1360: Type 'number' does not satisfy the expected type '() => any'.

When checkSatisfiesExpression is re-entered via getTypeOfExpression
(with CheckModeTypeOnly), skip the type assignability check that
triggers error reporting. Error reporting during type serialization
would re-evaluate the satisfies expression, causing infinite recursion.

The assignability check only produces errors and doesn't affect the
return type (always exprType), so skipping it when CheckModeTypeOnly
is set is safe.

Fixes #3805

Agent-Logs-Url: https://github.com/microsoft/typescript-go/sessions/f221297f-bd44-447e-965b-fc7b35362b61

Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix panic if there's a circular reference after satisfies Fix stack overflow on circular reference after satisfies May 12, 2026
Copilot AI requested a review from jakebailey May 12, 2026 05:52
@jakebailey
Copy link
Copy Markdown
Member

@copilot is this a porting bug? If not why doesn't Strada hit this?

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 12, 2026

@copilot is this a porting bug? If not why doesn't Strada hit this?

Yes, this is a porting bug. Strada doesn't hit this because it doesn't have the pseudochecker path.

The cycle is: serializeReturnTypeForSignaturepseudoTypeEquivalentToTypepseudoTypeToType (for PseudoTypeKindInferred) → getRegularTypeOfExpressioncheckExpressionExcheckSatisfiesExpression → error reporting → typeToStringserializeReturnTypeForSignature → ∞

In Strada, serializeReturnTypeForSignature uses canReuseTypeNodeAnnotation/typeNodeIsEquivalentToType which don't call getRegularTypeOfExpression during return type serialization. The Go port replaces this with the pseudochecker approach where pseudoTypeToType for inferred types calls getRegularTypeOfExpression, creating the re-entrant path that doesn't exist in Strada.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Panic if there's a circular reference after satisfies

2 participants