Skip to content

Fix parsing of call with type arguments after left shift (<<) - #64854

Open
Lanz Skyler B. Busa (ArchiTecCTT) wants to merge 1 commit into
microsoft:mainfrom
ArchiTecCTT:fix-37760-left-shift-type-args
Open

Lanz Skyler B. Busa (ArchiTecCTT) wants to merge 1 commit into
microsoft:mainfrom
ArchiTecCTT:fix-37760-left-shift-type-args

Conversation

@ArchiTecCTT

Copy link
Copy Markdown

Fixes #37760

Problem

1 << alignof<T[]>() was misparsed, while the same code with >> parsed correctly:

function alignof<T>(): number { return 1; }
function bar<T>(): number { return 1 << alignof<T[]>(); }
// error TS2349: This expression is not callable. Type 'Number' has no call signatures.
// error TS1005: ',' expected.  (x2)
// emitted JS: function bar() { return 1(); }

When an expression is followed by <<, tryParseTypeArgumentsInExpression rescans it as < so that a generic function type can be the first type argument (f<<T>(x: T) => T>(g)). Here the speculative parse of <alignof<T[]> as a type argument list reports errors, but it still ends at > followed by (. So it was accepted, and the expression became the call 1<...>().

Implementation

In tryParseTypeArgumentsInExpression, if the speculative type argument list was started from a rescanned << and parsing it produced any diagnostics, rewind and return nil, so << is parsed as a left shift operator. A plain < keeps its existing behavior, and a valid f<<T>(x: T) => T>(...) still parses as type arguments.

Tests

Added tests/cases/compiler/leftShiftBeforeTypeArgumentCall.ts, covering <<, >>, >>>, <<=, >>=, >>>=, <, a parenthesized right operand, and a g<<U>(x: U) => U>(...) call that must still parse as type arguments. Before this change it produced 12 errors and emitted 1(); now it has no errors and emits 1 << alignof(). No other baselines changed. hereby test, test:all, lint, check:format, and generate (with a clean git diff) pass locally.

This change was written with the help of Claude Code; I have reviewed it and will handle review feedback myself.

🤖 Generated with Claude Code

When an expression is followed by `<<`, the parser splits it into two `<`
tokens and speculatively parses a type argument list, so that a generic
function type can be the first type argument, as in `f<<T>(x: T) => T>(g)`.
For `1 << alignof<T[]>()` that speculative parse reports errors but still
ends at `>` followed by `(`, so it was accepted and the expression was
misparsed as the call `1<...>()`.

Reject the type argument interpretation when it started from a split `<<`
and parsing the list reported errors, so `<<` is parsed as a left shift.

Fixes microsoft#37760
Copilot AI balanced review requested due to automatic review settings October 18, 2026 05:57
@typescript-automation typescript-automation Bot added the For Backlog Bug PRs that fix a backlog bug label Oct 18, 2026
@github-project-automation github-project-automation Bot moved this to Not started in PR Backlog Oct 18, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The narrow rollback and regression baselines support the intended fix with no unresolved findings; tests were not run during this review.

No open issues 🎉

What changed in this PR

Fixes #37760 by rejecting erroneous speculative type arguments after <<, allowing the native compiler to parse the intended left shift.

Changes:

  • Rewinds failed << speculation while preserving valid generic calls.
  • Adds regression coverage and JavaScript, type, and symbol baselines.
File Description
tsc/​internal/​parser/​parser.go Adds diagnostic-based rollback for << speculation.
tsc/​testdata/​tests/​cases/​compiler/​leftShiftBeforeTypeArgumentCall.ts Covers shifts, comparisons, and valid generic calls.
tsc/​testdata/​baselines/​reference/​compiler/​leftShiftBeforeTypeArgumentCall.js Records correct emitted operators and calls.
tsc/​testdata/​baselines/​reference/​compiler/​leftShiftBeforeTypeArgumentCall.types Records expected inferred types.
tsc/​testdata/​baselines/​reference/​compiler/​leftShiftBeforeTypeArgumentCall.symbols Records expected symbol bindings.

Review effort: Balanced

@ArchiTecCTT

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

This branch has not been deployed

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

Labels

For Backlog Bug PRs that fix a backlog bug

Projects

Status: Not started

Development

Successfully merging this pull request may close these issues.

Parsing issue for call expression with type arguments following left-shift

2 participants