Skip to content

[Compiler] Fix overloads causing wrong function export with gating#691

Open
everettbu wants to merge 1 commit intomainfrom
fix/overloads-gating-export
Open

[Compiler] Fix overloads causing wrong function export with gating#691
everettbu wants to merge 1 commit intomainfrom
fix/overloads-gating-export

Conversation

@everettbu
Copy link
Copy Markdown

Mirror of facebook/react#36013
Original author: GokhanKabar


TypeScript overload signatures (TSDeclareFunction nodes) were causing getFunctionReferencedBeforeDeclarationAtTopLevel to falsely detect functions as referenced before their declaration. This triggered the hoisting code path which placed the export on the unoptimized variant instead of the dispatcher function.

Fix: Skip TSDeclareFunction nodes in the reference-before-declaration traversal, consistent with how other type-only nodes (TypeAnnotation, TSTypeAnnotation, TypeAlias, TSTypeAliasDeclaration) are already skipped.

Fixes #35991

TypeScript overload signatures (TSDeclareFunction nodes) were causing
getFunctionReferencedBeforeDeclarationAtTopLevel to falsely detect
functions as referenced before their declaration. This triggered the
hoisting code path which placed the export on the unoptimized variant
instead of the dispatcher function.

Fix: Skip TSDeclareFunction nodes in the reference-before-declaration
traversal, consistent with how other type-only nodes (TypeAnnotation,
TSTypeAnnotation, TypeAlias, TSTypeAliasDeclaration) are already skipped.

Fixes #35991
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Mar 11, 2026

Greptile Summary

This PR fixes a bug in the React Compiler where TypeScript overload signatures (TSDeclareFunction nodes) were incorrectly causing getFunctionReferencedBeforeDeclarationAtTopLevel to treat a function as referenced before its declaration. The false positive triggered the hoisting code path, which placed the gating export on the unoptimized fallback variant instead of the dispatcher function.

  • Fix (Program.ts): Adds a TSDeclareFunction visitor that calls path.skip(), preventing traversal into TypeScript overload signatures. This is consistent with how TypeAnnotation, TSTypeAnnotation, TypeAlias, and TSTypeAliasDeclaration are already handled in the same traversal.
  • Test fixture (gating-test-export-function-with-overloads.tsx): Adds a new fixture with a hook that has two overload signatures and a single implementation, annotated with // @gating, reproducing the exact bug scenario.
  • Snapshot (gating-test-export-function-with-overloads.expect.md): Confirms the expected output — the overload signatures are preserved, and the implementation is correctly emitted as export const useSession = isForgetEnabled_Fixtures() ? optimizedFn : fallbackFn.

Confidence Score: 5/5

  • This PR is safe to merge — it's a minimal, targeted fix with a clear root cause and a covering test.
  • The change is a single 3-line addition that mirrors an already-established pattern (skipping type-only nodes) and is validated by a new snapshot test demonstrating correct gating output. There is no risk of regressions outside the TypeScript overload edge case being addressed.
  • No files require special attention.

Important Files Changed

Filename Overview
compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts Adds TSDeclareFunction to the list of skipped nodes in the reference-before-declaration traversal, consistent with existing handling of other type-only nodes. Fix is minimal and correctly targets the root cause.
compiler/packages/babel-plugin-react-compiler/src/tests/fixtures/compiler/gating/gating-test-export-function-with-overloads.tsx New test fixture that exercises the gating path with TypeScript overload signatures on an exported hook, covering the exact bug scenario from the issue.
compiler/packages/babel-plugin-react-compiler/src/tests/fixtures/compiler/gating/gating-test-export-function-with-overloads.expect.md Snapshot for the new test fixture. The optimized path correctly produces export const useSession = isForgetEnabled_Fixtures() ? optimizedFn : originalFn. Minor note: the fallback function references the unbound type parameter T in its signature (line 52), which may produce a TypeScript type error, but this appears to be pre-existing compiler behavior rather than a regression introduced by this PR.

Last reviewed commit: 76d881b

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants