Skip to content

feat(ts): translate NonZero's unchecked_add and unchecked_mul - #659

Merged
kixelated merged 2 commits into
mainfrom
quest/m3/ts-unsafe/nonzero-unchecked-ops
Nov 7, 2026
Merged

kixelated merged 2 commits into
mainfrom
quest/m3/ts-unsafe/nonzero-unchecked-ops

Conversation

@kixelated

@kixelated kixelated commented Nov 7, 2026 •

Copy link
Copy Markdown
Collaborator

Finishes quest/m3/ts-unsafe/nonzero-unchecked-ops.md, and deletes it.

Problem

rust2-ts refused NonZero::unchecked_add and NonZero::unchecked_mul by name. moq-dev/rust2#622 translated the integers' unchecked_* and NonZero::new_unchecked but left these out. These two aren't #[track_caller], so a violated precondition aborts at a location inside std's source, not at the call.

Approach

  • Removed the refusal arm in ts/src/lower/library.rs. Each method now goes through the NonZero arm to its integer's unchecked_ mapping from feat(ts): translate unchecked integer operations and NonZero::new_unchecked #622, rs.precondition(rs.u8CheckedAdd(a, b), "u8::unchecked_add cannot overflow"). Only the integer's precondition can fail: a non-zero value plus or times something, without overflow, is still non-zero, so the inner new_unchecked never aborts.
  • The location needed no new SITES entry, even though the quest's Plan expected one. std_site (ts/src/lower/mir/mod.rs) already gives a non-tracking std function that a macro defines its outermost macro call. That is the nonzero_integer! { call for that width's NonZero, the same location native code reports, and the existing site path appends it to rs.precondition.
  • Differential tests against native:
    • lang/methods adds kind 49, unchecked_mul at every width, and kind 50, unchecked_add on unsigned widths.
    • lang/panics with the hook feature adds cases 34 (NonZero<u8>::unchecked_add) and 35 (NonZero<i16>::unchecked_mul). Both abort, and the hook's note is compared with native, location included. The two widths give different sites (nonzero.rs:2662 and :2773).
  • Updated ts/README.md's integer-method paragraph.

Impact

  • Translator output: these two methods now translate where they were refused before. No other output changes, apart from the fixture snapshots renumbering.
  • No public API or wire change.

Choices made without asking

  • Reused std_site's macro-call location instead of adding SITES entries, which would have needed one per width.
  • The fixtures enable #![feature(nonzero_ops)]. lang/panics enables it only under hook, the only place that uses it.

Alternatives

  • One SITES key per NonZero width: 12 entries that duplicate what std_site already works out from the def span.

Follow-ups

  • NonZero::from_mut and from_mut_unchecked (unstable nonzero_from_mut) are still unmapped and refused. Plan it: a std gap with no consumer becomes its own m3 quest. NonZero is its integer, so each is the same place plus a non-zero check.

Validation

  • quest gate nix develop --command just ci: passed (89 fixture tests, 10 runtime tests).

Models

Size: XS
Implementer: Claude Code, claude-opus-5-5, high effort

(Written by Claude Opus 5.5 with high effort)

🤖 Generated with Claude Code

Review

Rewritten by quest review after each round.

  • Reviewer: Codex, gpt-6.1-sol, low effort
  • Session: 01a1b78a-3cea-77e0-af9e-15afba95c106, round 1
  • Head: 6fabb93
  • Base: origin/main at db7b7bd
  • Score: 10/10, The specified diff correctly reuses checked-integer lowering and preserves std-source abort locations, with differential cases covering widths, successful results, overflow, and panic-hook output; no actionable defects were found, though tests were not run in this read-only review.
  • Findings: none

@pullfrog

pullfrog Bot commented Nov 7, 2026

Copy link
Copy Markdown

Pullfrog  | Review this ➔

Each is its integer's checked form under rs.precondition, which aborts at
std's call of its integer's method: the nonzero_integer! call that defines
the width's NonZero, as a panic hook reads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated kixelated changed the title NonZero's unchecked arithmetic feat(ts): translate NonZero's unchecked_add and unchecked_mul Nov 7, 2026
@kixelated
kixelated marked this pull request as ready for review November 7, 2026 19:45
@coderabbitai

coderabbitai Bot commented Nov 7, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 10 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 5696d6aa-d11b-4c7e-88d8-73fc42f7a5d9
Commits

Reviewing files that changed from the base of the PR and between db7b7bd and 6fabb93.

Files selected for processing: 13

  • quest/m3/ts-unsafe/README.md
  • quest/m3/ts-unsafe/nonzero-unchecked-ops.md
  • ts/README.md
  • ts/fixtures/lang/methods/caller.ts
  • ts/fixtures/lang/methods/expected/methods.ts
  • ts/fixtures/lang/methods/src/lib.rs
  • ts/fixtures/lang/methods/src/methods.rs
  • ts/fixtures/lang/panics/hook/expected/hooked.Shown.ts
  • ts/fixtures/lang/panics/hook/expected/hooked.ts
  • ts/fixtures/lang/panics/hook/expected/lib.ts
  • ts/fixtures/lang/panics/src/hooked.rs
  • ts/fixtures/lang/panics/src/lib.rs
  • ts/src/lower/library.rs
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@kixelated
kixelated added this pull request to the merge queue Nov 7, 2026

@kixelated kixelated left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Automated review by review (OpenAI)

Reviewed head 6fabb93 against base db7b7bd.

No actionable findings. Removing the NonZero-specific refusal routes these calls through the existing width/sign-aware checked integer operations and precondition abort handling. Unsigned nonzero addition and multiplication of two nonzero integers cannot produce zero without overflow, so the existing overflow guard covers the additional NonZero invariant for these methods.

I checked the NonZero-to-integer dispatch, int_method's unchecked mapping, the existing std_site macro-expansion location path, and the new fixture cases/snapshots. The methods fixture adds multiplication across signed and unsigned widths and addition for unsigned widths; the hook snapshots place the u8 add and i16 multiply precondition failures at their respective std nonzero.rs macro sites rather than the caller.

Direction: keep the native differential suite as the regression gate, particularly when changing the pinned Rust toolchain because std locations are version-dependent. The separately noted from_mut/from_mut_unchecked gap is not implemented by this change.

Verification limits: GitHub-only static inspection. I did not execute the differential tests, runtime tests, compiler, or native panic-hook cases; the PR's reported successful just ci run was not independently reproduced.

(Written by review (OpenAI))

Merged via the queue into main with commit 5c9d405 Nov 7, 2026
10 checks passed
@kixelated
kixelated deleted the quest/m3/ts-unsafe/nonzero-unchecked-ops branch November 7, 2026 19:59
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.

1 participant