Skip to content

BE-525: HashQL: Remove implicit type-widening from Integer operations, and make comparison size aware#8693

Open
indietyp wants to merge 3 commits into
bm/be-515-hashql-remove-offset-0-materialization-fence-from-generatedfrom
bm/be-525-hashql-remove-implicit-type-widening-into-num-for-int
Open

BE-525: HashQL: Remove implicit type-widening from Integer operations, and make comparison size aware#8693
indietyp wants to merge 3 commits into
bm/be-515-hashql-remove-offset-0-materialization-fence-from-generatedfrom
bm/be-525-hashql-remove-implicit-type-widening-into-num-for-int

Conversation

@indietyp
Copy link
Copy Markdown
Member

@indietyp indietyp commented May 4, 2026

🌟 What is the purpose of this PR?

Integer arithmetic in the MIR interpreter previously silently promoted overflowing i128 operations to floating-point results via a Numeric enum. This was semantically incorrect: the language specifies arbitrary-precision integers, and silently widening to f64 loses precision and masks errors. This PR replaces that silent promotion with explicit overflow detection, surfacing a user-facing IntegerOverflow runtime error when addition, subtraction, or negation exceeds the 128-bit range supported by the interpreter.

As a side effect, the Int type's equality, ordering, and hashing semantics are corrected so that booleans (1-bit integers) are treated as a distinct type from integers (128-bit), rather than comparing equal to numeric integers with the same value. This restores type-level correctness for Bool vs Int comparisons throughout the value layer.

🔍 What does this change?

  • Adds a RuntimeError::IntegerOverflow variant with an operation field, and a corresponding integer_overflow diagnostic emitted under the RuntimeLimit category with a note that the interpreter supports up to 128-bit integers.
  • Replaces the Neg, Add<Int>, and Sub<Int> operator impls on Int (which returned Numeric and silently promoted to f64 on overflow) with checked_neg, checked_add, and checked_sub methods that return Option<Int>.
  • Removes the Numeric enum entirely, along with the From<Numeric> for Value conversion and all associated forwarding impls.
  • Updates the binary and unary operation dispatch in the interpreter runtime to use the new checked methods and return RuntimeError::IntegerOverflow on None.
  • Fixes Int's PartialEq, Ord, and Hash implementations to include the size field, so that Int::from(true) (1-bit) and Int::from(1_i32) (128-bit) are no longer considered equal.
  • Fixes PartialEq<Int> for Num, PartialOrd<Int> for Num, and their reverses to return false/None when the Int is a boolean, since booleans are not a subtype of Number.
  • Updates Value::Ord to guard the cross-type Integer/Number ordering arms with !this.is_bool() / !other.is_bool().
  • Updates InstSimplifyVisitor::eval_un_op to return Option<Int> and skip constant folding for negation of i128::MIN.
  • Adds interpreter tests for addition, subtraction, and negation overflow, and an inst_simplify test confirming that neg(i128::MIN) is not folded.
  • Updates all unit tests in int.rs and mod.rs to reflect the corrected bool/int distinction.

Pre-Merge Checklist 🚀

🚢 Has this modified a publishable library?

This PR:

  • does not modify any publishable blocks or libraries, or modifications do not need publishing

📜 Does this require a change to the docs?

The changes in this PR:

  • are internal and do not require a docs change

🕸️ Does this require a change to the Turbo Graph?

The changes in this PR:

  • do not affect the execution graph

🛡 What tests cover this?

  • New interpreter tests: integer_add_overflow, integer_sub_overflow, integer_neg_overflow — each confirms a RuntimeLimit diagnostic is produced.
  • New inst_simplify test: const_fold_neg_overflow — confirms that negation of i128::MIN is left unfolded.
  • Updated unit tests in Int and Value covering corrected equality, ordering, hashing, and cross-type Num/Int comparisons.

❓ How to test this?

  1. Run cargo test -p hashql-mir and confirm all tests pass.
  2. Verify that the new snapshot const_fold_neg_overflow.snap matches the expected unfold output.
  3. Confirm that expressions producing integer overflow at runtime emit a diagnostic with category RuntimeLimit and a message referencing the 128-bit limit.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 4, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hash Ready Ready Preview, Comment May 19, 2026 3:55pm
petrinaut Ready Ready Preview May 19, 2026 3:55pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
hashdotdesign-tokens Ignored Ignored Preview May 19, 2026 3:55pm

@vercel vercel Bot temporarily deployed to Preview – petrinaut May 4, 2026 10:33 Inactive
@cursor
Copy link
Copy Markdown

cursor Bot commented May 4, 2026

PR Summary

Medium Risk
Changes runtime arithmetic semantics to error on i128 overflow (instead of silently widening) and changes equality/ordering/hashing for Bool vs Int, which can affect interpreter results and constant-folding behavior.

Overview
Integer arithmetic no longer silently widens on overflow. The interpreter now detects overflow for +, -, and unary neg on integer operands and raises a new user-facing RuntimeError::IntegerOverflow, surfaced as a RuntimeLimit diagnostic.

Comparison semantics are tightened to be size-aware. Int equality/ordering/hashing now incorporate the stored bit-width so Bool (1-bit) is distinct from Int (128-bit), and cross-type NumInt comparisons/ordering are guarded to exclude boolean-sized ints; constant folding in inst_simplify is updated accordingly (including skipping neg(i128::MIN) folding). Tests and snapshots are updated/added to cover overflow and the new comparison behavior.

Reviewed by Cursor Bugbot for commit 07bb2cf. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions github-actions Bot added area/libs Relates to first-party libraries/crates/packages (area) type/eng > backend Owned by the @backend team area/tests New or updated tests labels May 4, 2026
Copy link
Copy Markdown
Member Author

indietyp commented May 4, 2026

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

@augmentcode
Copy link
Copy Markdown

augmentcode Bot commented May 4, 2026

🤖 Augment PR Summary

Summary: This PR fixes HashQL MIR interpreter integer semantics by removing implicit type-widening on overflow and making comparisons size-aware.

Changes:

  • Adds RuntimeError::IntegerOverflow plus a new RuntimeLimit diagnostic for i128-range overflows.
  • Updates runtime dispatch for Add/Sub/Neg on Int to use checked arithmetic and surface overflow as an explicit runtime error.
  • Removes the Numeric enum and associated conversion plumbing that previously promoted overflowing Int operations into f64.
  • Makes Int equality/ordering/hashing include the size field so Bool (1-bit) and Int (128-bit) are distinct at the value layer.
  • Adjusts NumInt cross-type comparison to treat booleans as neither equal nor orderable with Num.
  • Updates Value::Ord to only apply numeric ordering between Integer/Number for non-bool integers.
  • Updates constant folding to avoid folding neg(i128::MIN) and adds interpreter + inst_simplify regression tests/snapshots for overflow cases.

🤖 Was this summary useful? React with 👍 or 👎

Copy link
Copy Markdown

@augmentcode augmentcode Bot left a comment

Choose a reason for hiding this comment

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

Review completed. 1 suggestion posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread libs/@local/hashql/mir/src/interpret/value/int.rs
@codecov
Copy link
Copy Markdown

codecov Bot commented May 4, 2026

Codecov Report

❌ Patch coverage is 97.42268% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 57.38%. Comparing base (b7cbc1d) to head (07bb2cf).

Files with missing lines Patch % Lines
libs/@local/hashql/mir/src/interpret/value/mod.rs 83.33% 1 Missing and 2 partials ⚠️
libs/@local/hashql/mir/src/interpret/error.rs 90.90% 1 Missing ⚠️
...hashql/mir/src/pass/transform/inst_simplify/mod.rs 87.50% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@                                            Coverage Diff                                             @@
##           bm/be-515-hashql-remove-offset-0-materialization-fence-from-generated    #8693       +/-   ##
==========================================================================================================
+ Coverage                                                                   5.74%   57.38%   +51.64%     
==========================================================================================================
  Files                                                                        486      700      +214     
  Lines                                                                      16035    53751    +37716     
  Branches                                                                    2885     3620      +735     
==========================================================================================================
+ Hits                                                                         921    30845    +29924     
- Misses                                                                     15087    22610     +7523     
- Partials                                                                      27      296      +269     
Flag Coverage Δ
apps.hash-ai-worker-ts 1.41% <ø> (ø)
apps.hash-api 0.00% <ø> (ø)
local.hash-backend-utils 2.81% <ø> (ø)
local.hash-graph-sdk 9.63% <ø> (ø)
local.hash-isomorphic-utils 0.00% <ø> (ø)
rust.hash-graph-api 2.52% <ø> (?)
rust.hashql-compiletest 28.26% <ø> (ø)
rust.hashql-eval 79.70% <ø> (?)
rust.hashql-mir 91.86% <97.42%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 4, 2026

Merging this PR will not alter performance

✅ 24 untouched benchmarks
⏩ 56 skipped benchmarks1


Comparing bm/be-525-hashql-remove-implicit-type-widening-into-num-for-int (07bb2cf) with bm/be-515-hashql-remove-offset-0-materialization-fence-from-generated (9db238d)2

Open in CodSpeed

Footnotes

  1. 56 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on bm/be-515-hashql-remove-offset-0-materialization-fence-from-generated (b7cbc1d) during the generation of this report, so 161d40f was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@indietyp indietyp force-pushed the bm/be-515-hashql-remove-offset-0-materialization-fence-from-generated branch from 58bba8c to 2a89970 Compare May 8, 2026 08:33
@indietyp indietyp force-pushed the bm/be-525-hashql-remove-implicit-type-widening-into-num-for-int branch from b87ca3d to 1d64eff Compare May 8, 2026 08:33
@indietyp indietyp force-pushed the bm/be-525-hashql-remove-implicit-type-widening-into-num-for-int branch from 1d64eff to b63a08d Compare May 11, 2026 10:58
@indietyp indietyp force-pushed the bm/be-515-hashql-remove-offset-0-materialization-fence-from-generated branch from 2a89970 to 3610d86 Compare May 11, 2026 10:58
@indietyp indietyp force-pushed the bm/be-515-hashql-remove-offset-0-materialization-fence-from-generated branch from 3610d86 to 1d27736 Compare May 12, 2026 13:58
@indietyp indietyp force-pushed the bm/be-525-hashql-remove-implicit-type-widening-into-num-for-int branch from b63a08d to 0fcfe76 Compare May 12, 2026 13:58
@indietyp indietyp force-pushed the bm/be-515-hashql-remove-offset-0-materialization-fence-from-generated branch from 1d27736 to f952099 Compare May 13, 2026 09:38
@indietyp indietyp force-pushed the bm/be-525-hashql-remove-implicit-type-widening-into-num-for-int branch from 0fcfe76 to 8e7b7a8 Compare May 13, 2026 09:38
@indietyp indietyp force-pushed the bm/be-515-hashql-remove-offset-0-materialization-fence-from-generated branch from f952099 to 677b341 Compare May 13, 2026 09:57
@indietyp indietyp force-pushed the bm/be-525-hashql-remove-implicit-type-widening-into-num-for-int branch from 8e7b7a8 to 80c753b Compare May 13, 2026 09:57
@indietyp indietyp force-pushed the bm/be-525-hashql-remove-implicit-type-widening-into-num-for-int branch from 80c753b to bb9d9da Compare May 15, 2026 07:49
@indietyp indietyp force-pushed the bm/be-515-hashql-remove-offset-0-materialization-fence-from-generated branch from 677b341 to 5b4aeb0 Compare May 15, 2026 07:49
@indietyp indietyp force-pushed the bm/be-515-hashql-remove-offset-0-materialization-fence-from-generated branch from 5b4aeb0 to b7cbc1d Compare May 19, 2026 15:43
@indietyp indietyp force-pushed the bm/be-525-hashql-remove-implicit-type-widening-into-num-for-int branch from bb9d9da to 07bb2cf Compare May 19, 2026 15:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/libs Relates to first-party libraries/crates/packages (area) area/tests New or updated tests type/eng > backend Owned by the @backend team

Development

Successfully merging this pull request may close these issues.

1 participant