Skip to content

Fix panic in printer when type-only export is body of an if statement#3928

Open
Copilot wants to merge 4 commits into
mainfrom
copilot/fix-if-statement-panic
Open

Fix panic in printer when type-only export is body of an if statement#3928
Copilot wants to merge 4 commits into
mainfrom
copilot/fix-if-statement-panic

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 16, 2026

if (true) export type {}; panics because the type-only export is elided during emit, leaving a nil ThenStatement. The printer's emitEmbeddedStatement dereferences it unconditionally.

  • Fixed EmitContext.VisitEmbeddedStatement to create an EmptyStatement when the visitor returns nil for a non-nil embedded statement node, consistent with the existing NotEmittedStatement handling in the same function
  • Added compiler test case typeOnlyExportAsIfBody.ts

Output after fix:

if (true)
    ;

When a type-only export (e.g., `export type {}`) is used as the body
of an if statement, the transformer elides it during emit, resulting
in a nil node being passed to emitEmbeddedStatement. Add a nil check
to emit a semicolon (empty statement) instead of panicking.

Fixes #1434

Agent-Logs-Url: https://github.com/microsoft/typescript-go/sessions/e1fda50b-565f-4581-b127-a3a85ead111f

Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix tsgo panic when type-only export is in if statement Fix panic in printer when type-only export is body of an if statement May 16, 2026
Copilot AI requested a review from jakebailey May 16, 2026 20:13
Comment thread internal/printer/printer.go Outdated
Comment on lines +4095 to +4101
if node == nil {
p.writeLine()
p.increaseIndent()
p.writePunctuation(";")
p.decreaseIndent()
return
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot The original emitEmbeddedStatement in the old compiler did not need to nil check. Probably the bug is elsewhere

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right — the fix belongs upstream. Moved it to EmitContext.VisitEmbeddedStatement in 806c52e. When a visitor returns nil for a non-nil embedded statement (e.g., type-only export elided by the type eraser), it now creates an EmptyStatement instead of propagating nil. This matches the existing NotEmittedStatementEmptyStatement conversion in the same function. The printer is reverted to its original state.

Copilot AI and others added 2 commits May 16, 2026 20:53
Instead of nil-guarding in the printer's emitEmbeddedStatement, fix the
upstream issue in EmitContext.VisitEmbeddedStatement. When a visitor
returns nil for an embedded statement (e.g., type-only export elided by
the type eraser), create an EmptyStatement instead of propagating nil.
This matches the existing handling of NotEmittedStatement nodes.

Fixes #1434

Agent-Logs-Url: https://github.com/microsoft/typescript-go/sessions/d30d9b60-0d66-4539-b25a-e9d521e0c8d4

Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
@jakebailey jakebailey marked this pull request as ready for review May 16, 2026 20:55
Copilot AI review requested due to automatic review settings May 16, 2026 20:55
Copilot AI requested a review from jakebailey May 16, 2026 20:55
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a printer panic when an embedded statement is elided during emit, such as a type-only export used as the body of an if statement.

Changes:

  • Treat non-nil embedded statements that visit to nil as empty statements.
  • Add a compiler regression test and accepted baselines for the invalid-but-emitted type-only export case.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
internal/printer/emitcontext.go Converts elided embedded statements into empty statements before printing.
testdata/tests/cases/compiler/typeOnlyExportAsIfBody.ts Adds the regression test case.
testdata/baselines/reference/compiler/typeOnlyExportAsIfBody.js Adds emitted JS baseline.
testdata/baselines/reference/compiler/typeOnlyExportAsIfBody.errors.txt Adds diagnostic baseline.
testdata/baselines/reference/compiler/typeOnlyExportAsIfBody.symbols Adds symbol baseline.
testdata/baselines/reference/compiler/typeOnlyExportAsIfBody.types Adds type baseline.

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.

tsgo panics when a type-only export is the body of an if statement

3 participants