Handle Sub Overflow Edge Case#29
Merged
coriolinus merged 3 commits intocoriolinus:mainfrom Mar 7, 2026
Merged
Conversation
coriolinus
approved these changes
Mar 6, 2026
Owner
coriolinus
left a comment
There was a problem hiding this comment.
Thanks for doing this work! I'm going make a small change, to parametrize the tests you wrote. But good catch, and I appreciate the fix!
Owner
|
Rather I'm going to ask you to apply this patch to the test cases, because I prefer that independent cases run independently: diff --git a/src/value/arithmetic.rs b/src/value/arithmetic.rs
index 17c1860..83f4401 100644
--- a/src/value/arithmetic.rs
+++ b/src/value/arithmetic.rs
@@ -397,39 +397,26 @@ mod tests {
assert_eq!(result, (-1_i64).into());
}
- #[test]
- fn sub_overflow_promotes_to_signed_or_float() {
- // ------------------------------------------------------------------------
- // -- sub overflow i64 bounds, result should promote to SignedBigInt
- // ------------------------------------------------------------------------
- let left: Value = 0_i64.into();
- let right: Value = i64::MIN.into();
+ #[rstest]
+ #[case::i64_overflows_to_i128(0_i64, i64::MIN, Order::SignedBigInt, 9223372036854775808_i128)]
+ #[case::i128_overflows_to_float(0_i128, i128::MIN, Order::Float, 1.7014118346046923e38)]
+ fn sub_overflow_promotes_to_signed_or_float(
+ #[case] left: impl Into<Value>,
+ #[case] right: impl Into<Value>,
+ #[case] expected_order: Order,
+ #[case] expected_value: impl Into<Value>,
+ ) {
+ let left = left.into();
+ let right = right.into();
let result = left - right;
- let expected_order = Order::SignedBigInt;
- assert_eq!(
- result.order(),
- expected_order,
- "sub overflow should promote this to {expected_order:?} : got = {result:?}"
- );
- let expected_value = (9223372036854775808_i128).into();
- assert_eq!(
- result, expected_value,
- "sub overflow value should be {expected_value:?} : got = {result:?}"
- );
- // ------------------------------------------------------------------------
- // -- sub overflow i128 bounds, result should promote to Float
- // ------------------------------------------------------------------------
- let left: Value = 0_i128.into();
- let right: Value = i128::MIN.into();
- let result = left - right;
- let expected_order = Order::Float;
assert_eq!(
result.order(),
expected_order,
"sub overflow should promote this to {expected_order:?} : got = {result:?}"
);
- let expected_value = (1.7014118346046923e38).into();
+
+ let expected_value = expected_value.into();
assert_eq!(
result, expected_value,
"sub overflow value should be {expected_value:?} : got = {result:?}"Once that's in, I'll merge. |
Contributor
Author
|
Makes sense! I have applied those changes. Also, on another note, I noticed this same 'promotion overflow' issue in |
Owner
|
A batch PR makes sense. The main thing is that test cases should cover all changes. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hello! Thank you for this amazing library!!
The Issue
When trying to do something like
Value::SignedInt(0) - Value::SignedInt(i64::MIN)I would receive a panic :attempt to subtract with overflow.As far as I could tell, sub-underflow was accounted for, but not sub-overflow. However, it is entirely possible I overlooked something and this PR is incorrect.
The Fix
I created another shim for
f64,CheckedSub:and mirrored the
AddAssignimplementation:I also added edge case tests:
Click to show test
Now sub-overflow and promotion of the result seem to be working as expected.
Please let me know if you have any questions or concerns!