Repository navigation
fix(ts): fold a comparison of two constants a generic function's instance makes - #480
Conversation
Quest-Claim: 35037afddfbef8bf
…ance makes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…compares # Conflicts: # ts/fixtures/lang/expected/harness.ts # ts/fixtures/lang/src/harness.rs
…compares # Conflicts: # ts/fixtures/lang/errors/expected/errors.ts # ts/fixtures/lang/expected/harness.ts # ts/fixtures/lang/ints/expected/ints.ts # ts/fixtures/lang/shapes/expected/constants.ts # ts/fixtures/lang/shapes/src/constants.rs # ts/fixtures/lang/src/harness.rs # ts/fixtures/lang/src/lib.rs # ts/fixtures/lang/strs/expected/core/str.ts # ts/fixtures/lang/strs/expected/strs.ts
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars.
|
|
quest land watch: the merge queue removed this pull request at f8439ed because it conflicts with The land fixer works on it in the background, and the watcher re-enqueues it at the back of the queue once it is fixed or judged flaky, or hands it back here with what it needs. (written by quest land watch) |
|
quest land watch: armed auto-merge on this pull request at 33eca9f, so it joins the back of the merge queue once its required checks pass, with the land fixer's fix ( (written by quest land watch) |
Problem
An instance of a generic function can compare two constants, such as
size_of::<T>() == 1, whichu64's instance writes as8 === 1.tscrefuses an equality of two literal types that differ (TS2367), so the crate fails to translate. Found translating the deque's slices fixture (moq-dev/rust2#443).It reaches every kind of constant: integers (
8 === 2,-1 === -2),chars (99 === 98), floats (1.5 === 0),bools (false === true), a wide integer cast from a narrow one (T::I32 as i128), and a constant folded into a temporary that a comparison then reads (T::U8 / 2 == 1as4 === 1).Approach
The translator already folds comparisons of two number literals, through
foldinlower/mir, but only for switch tests and asserts. Now:foldalso folds two boolean literals, and reads literals through a source location, as asize_ofcall's result has one.Expr::notnegates a boolean literal to the other, so a folded test readsif (true), notif (!false).The fold computes what JS would compute at run time from the same two literals, so it keeps the output's semantics. The differential test checks the result against native Rust.
A new
lang/constantsfixture runs each of the six operators on each kind of constant:size_of,u8,i32,u64,i128,bool,char,f32,f64, casts, and temporaries, plus twoifs. It runs for aTbelow, equal to, and above the one it compares with, and for one at the limits, NaN, and-0.0. Without the fix,tscrejects that output with 40+ TS2367 errors.Other snapshot changes are the same fold showing up in std's code, such as
const isSignedTy: boolean = 0 > -128becomingtrue. Std instances named by a hash of their text get new names.Impact
Alternatives
(8 as number) === 1. Rejected: noisier output, and it would leaveif (8 === 1)for later code to reason about. Folding reuses the existingfold.Follow-ups
std::mem::needs_drop::<T>()is refused as an unsupported call, which I found while reproducing this. No quest covers it yet.Review
mechanical fix by codex / Codex:
Merged base, preserving both generated symbol renames and error wrappers; regenerated errors snapshot. Passed in ts/ on nightly-2026-10-15: cargo build --locked -p rust2-ts; UPDATE_EXPECT=1 cargo test --locked -p rust2-ts --test fixtures lang::errors -- --exact; cargo test --locked -p rust2-ts (97 tests).(head 33eca9f)quest review --base origin/main.b4ad4bdd: no findings.a7689cef, after merging main's per-module split of the lang fixture (moq-dev/rust2#474): no findings.c8e03978. Snapshots were regenerated with no changes, andjust cipassed atf8439ed0.🤖 Generated with Claude Code