Skip to content

Type a shift as its left operand [patch] - #460

Open
matt-edmondson wants to merge 1 commit into
mainfrom
fix/362-shift-static-type
Open

matt-edmondson wants to merge 1 commit into
mainfrom
fix/362-shift-static-type

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #362

What changed

StandardLanguageGenerator.StaticType typed every non-comparison BinaryExpression as Promoted(left, right), and that included << and >>. In every target, a shift has the type of its left operand. That rule is already followed by JavaScriptGenerator.IntegerWidthOf and by the binary and assignment widening paths, which exclude shifts. StaticType now returns StaticType(shift.Left) for LeftShift and RightShift.

Effects, with int b and long n:

Before After
Go: var s = b << n; return s; in a long function var s int64 = (b << n), fails to build s := (b << n) … return int64(s)
Go: return b >> n; in a long function no conversion, fails to build return int64((b >> n))
Rust: the same two E0308 return (s as i64);, return ((b >> n) as i64);
JavaScript: (x << n) << 31 with int x, called as (1, 1) BigInt path, returns 4294967296 32-bit <<, returns 0 like C#

Tests

  • NumericWideningTests.Widening() gains shiftedLocal and shiftedReturn. The fixture is shared, so both are now compiled by the Go and Rust MixedNumericWidths_Compile tests, and spelling assertions were added to Go_/Rust_WidensTheNarrowerSide.
  • New JavaScript_AShiftByALongStaysInItsLeftOperandsWidth runs the generated module under node and checks that chained(1, 1) === 0.
  • With the fix reverted, 5 tests fail: both compile tests (cannot use (b << n) (value of type int) as int64 value, E0308), the two spelling tests and the JavaScript run.
  • Full suite: 1665 passed, 0 failed.

Generated by Claude Code

StaticType typed every non-comparison binary as the wider of its operands,
shifts included, so int << long was taken for a long: Go and Rust skipped
the widening a long receiver needs and failed to build, and JavaScript ran
a chained int shift in 64 bits. A shift now has its left operand's type,
the rule the binary and assignment widening paths already follow.

Fixes #362

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vfJW4VpqLXsf6UDQnX46h
@sonarqubecloud

sonarqubecloud Bot commented Nov 6, 2026

Copy link
Copy Markdown

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.

A shift is typed as the wider of its two operands, so int << long fails to compile in Go and Rust and JavaScript computes chained shifts in 64 bits

2 participants