Skip to content

Conversation

@shubhamk0205
Copy link

solves #6141

This PR updates the isTypeCastSafe method in ValueVisitor to better handle type casts between double and float. Previously, the method only handled integer casts, which could cause valid floating-point casts to be incorrectly flagged as unsafe.

For double to float casts, the code now checks whether the value after casting behaves the same way Java would normally handle the conversion. If the values match, the cast is treated as safe.

For float to double casts, the method always considers the cast safe since this conversion does not lose information.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 16, 2026

📝 Walkthrough

Walkthrough

Adds floating-point cast-safety handling to type-cast logic: when both cast and expression types are floating-point, casts are treated as safe if primary annotations match. If each side has a single annotation and both denote DOUBLEVAL, value-based checks are applied for float↔double casts (exact rounded-equality for float→double; matching rounded float values for double→float). Other cases defer to existing safety logic. Also updates docs/manual/contributors.tex to adjust punctuation and add two contributor lines.

🚥 Pre-merge checks | ✅ 1
✅ Passed checks (1 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@framework/src/main/java/org/checkerframework/common/value/ValueVisitor.java`:
- Around line 421-441: The Float-to-Double comparison block calls
atypeFactory.getDoubleValues(castAnno)/getDoubleValues(exprAnno) without
verifying the annotation types; add checks like the integer branch does by using
atypeFactory.areSameByClass(castAnno, DoubleVal.class) and
atypeFactory.areSameByClass(exprAnno, DoubleVal.class) (similar to the IntVal
checks) before calling getDoubleValues so you only extract double values when
both annotations are DoubleVal; update the condition guarding the block that
currently tests castTypeKind/exprTypeKind and castAnnos/exprAnnos to also
require both annotations are DoubleVal (use the same pattern as the IntVal
verification).
- Around line 408-411: The comment in ValueVisitor about handling floating-point
type casts only mentions double → float but the surrounding code also handles
float → double; update the comment above the floating-point cast handling to
mention both directions (double → float and float → double), describing that
double→float may lose precision while float→double promotes without precision
loss but both follow IEEE 754 semantics and should not be flagged when correctly
rounded or representable; keep the note brief and place it with the existing
floating-point cast handling block in ValueVisitor so the comment accurately
describes both cases.

Comment on lines +408 to +411
// Handle floating-point type casts (double -> float).
// When a double is cast to float, precision loss may occur, but this is expected
// IEEE 754 behavior and should not be flagged as an unsafe cast if the result
// is the correctly-rounded representation.
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Comment is incomplete — also handles float → double.

The comment only describes the double → float case, but lines 442-444 also handle float → double. Consider updating the comment to reflect both directions.

-    // Handle floating-point type casts (double -> float).
-    // When a double is cast to float, precision loss may occur, but this is expected
-    // IEEE 754 behavior and should not be flagged as an unsafe cast if the result
-    // is the correctly-rounded representation.
+    // Handle floating-point type casts (double <-> float).
+    // When a double is cast to float, precision loss may occur, but this is expected
+    // IEEE 754 behavior and should not be flagged as an unsafe cast if the result
+    // is the correctly-rounded representation.
+    // When a float is cast to double, no precision is lost, so it is always safe.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Handle floating-point type casts (double -> float).
// When a double is cast to float, precision loss may occur, but this is expected
// IEEE 754 behavior and should not be flagged as an unsafe cast if the result
// is the correctly-rounded representation.
// Handle floating-point type casts (double <-> float).
// When a double is cast to float, precision loss may occur, but this is expected
// IEEE 754 behavior and should not be flagged as an unsafe cast if the result
// is the correctly-rounded representation.
// When a float is cast to double, no precision is lost, so it is always safe.
🤖 Prompt for AI Agents
In `@framework/src/main/java/org/checkerframework/common/value/ValueVisitor.java`
around lines 408 - 411, The comment in ValueVisitor about handling
floating-point type casts only mentions double → float but the surrounding code
also handles float → double; update the comment above the floating-point cast
handling to mention both directions (double → float and float → double),
describing that double→float may lose precision while float→double promotes
without precision loss but both follow IEEE 754 semantics and should not be
flagged when correctly rounded or representable; keep the note brief and place
it with the existing floating-point cast handling block in ValueVisitor so the
comment accurately describes both cases.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@docs/manual/contributors.tex`:
- Line 155: Update the contributor entry string "shubham kapoor." to title case
and match the other entries by changing it to "Shubham Kapoor." — locate the
literal text "shubham kapoor." in the contributors list in contributors.tex (the
contributor line), replace it with "Shubham Kapoor." preserving the trailing
period and surrounding formatting so the list remains consistent.

In `@framework/src/main/java/org/checkerframework/common/value/ValueVisitor.java`:
- Around line 435-448: The current index-based loop in ValueVisitor compares
castValues and exprValues by position, which is order-dependent and can fail if
the lists are differently ordered; change this to an order-independent
containment check by converting both lists into sets of the same element type
(e.g., HashSet<Double> or a TreeSet with a consistent comparator) after applying
the cast logic ((double)(float)exprVal) to exprValues, then use the existing
sortedSetContainsAll (or an equivalent set-contains-all) to check membership
between the set made from castValues and the set made from exprValues; update
the block that references castValues and exprValues to build these sets and
replace the index loop with the set-based comparison so the result is
order-independent.
- Around line 450-452: In ValueVisitor (the cast-handling block using
castTypeKind and exprTypeKind) the branch for float→double currently returns
true unconditionally; change it to mirror the double→float branch by verifying
both the cast target and the expression are annotated with `@DoubleVal` before
returning true (i.e., check the same annotation presence used in the
double→float check), so the float→double case only succeeds when both sides
carry the `@DoubleVal` annotation.

Werner Dietl,
Zhiping Cai.
Zhiping Cai,
shubham kapoor.
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Capitalize name to match contributor list format.

All other contributor names use title case. For consistency, this should be "Shubham Kapoor."

📝 Suggested fix
-shubham kapoor.
+Shubham Kapoor.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
shubham kapoor.
Shubham Kapoor.
🤖 Prompt for AI Agents
In `@docs/manual/contributors.tex` at line 155, Update the contributor entry
string "shubham kapoor." to title case and match the other entries by changing
it to "Shubham Kapoor." — locate the literal text "shubham kapoor." in the
contributors list in contributors.tex (the contributor line), replace it with
"Shubham Kapoor." preserving the trailing period and surrounding formatting so
the list remains consistent.

Comment on lines +435 to +448
if (castValues != null && exprValues != null && castValues.size() == exprValues.size()) {
boolean allMatch = true;
for (int i = 0; i < exprValues.size(); i++) {
double exprVal = exprValues.get(i);
double castVal = castValues.get(i);
if (Double.compare(castVal, (double) (float) exprVal) != 0) {
allMatch = false;
break;
}
}
if (allMatch) {
return true;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Index-based comparison assumes value ordering — consider set-based containment.

The integer cast handling (lines 371-402) uses TreeSet and sortedSetContainsAll for order-independent comparison. The floating-point handling assumes castValues and exprValues are in the same order by index. If the annotation value lists are derived or stored differently, this could incorrectly fail.

Consider using set-based comparison for robustness:

♻️ Suggested approach
           if (castValues != null && exprValues != null && castValues.size() == exprValues.size()) {
-            boolean allMatch = true;
-            for (int i = 0; i < exprValues.size(); i++) {
-              double exprVal = exprValues.get(i);
-              double castVal = castValues.get(i);
-              if (Double.compare(castVal, (double) (float) exprVal) != 0) {
-                allMatch = false;
-                break;
-              }
-            }
-            if (allMatch) {
-              return true;
+            // Compute expected cast values (double→float→double round-trip)
+            TreeSet<Double> expectedCastValues = new TreeSet<>();
+            for (Double exprVal : exprValues) {
+              expectedCastValues.add((double) (float) exprVal.doubleValue());
             }
+            TreeSet<Double> actualCastValues = new TreeSet<>(castValues);
+            if (actualCastValues.equals(expectedCastValues)) {
+              return true;
+            }
           }
🤖 Prompt for AI Agents
In `@framework/src/main/java/org/checkerframework/common/value/ValueVisitor.java`
around lines 435 - 448, The current index-based loop in ValueVisitor compares
castValues and exprValues by position, which is order-dependent and can fail if
the lists are differently ordered; change this to an order-independent
containment check by converting both lists into sets of the same element type
(e.g., HashSet<Double> or a TreeSet with a consistent comparator) after applying
the cast logic ((double)(float)exprVal) to exprValues, then use the existing
sortedSetContainsAll (or an equivalent set-contains-all) to check membership
between the set made from castValues and the set made from exprValues; update
the block that references castValues and exprValues to build these sets and
replace the index loop with the set-based comparison so the result is
order-independent.

@shubhamk0205 shubhamk0205 force-pushed the fix/floating-point-cast-safety branch from bef74a1 to 762d67d Compare January 17, 2026 04:54
@shubhamk0205 shubhamk0205 force-pushed the fix/floating-point-cast-safety branch from 762d67d to 3213a02 Compare January 17, 2026 12:25
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@docs/manual/contributors.tex`:
- Around line 155-156: Remove the redundant contributor entry by keeping only
the proper name "Shubham Kapoor" and deleting the duplicate username
"shubhamk0205." Locate the two lines containing "shubham kapoor," and
"shubhamk0205." in the contributors list and remove the username entry (or vice
versa if you prefer the username), ensuring formatting and punctuation match the
surrounding entries.
♻️ Duplicate comments (2)
docs/manual/contributors.tex (1)

155-155: Capitalize name to match contributor list format.

All other contributor names use title case (e.g., "Abhijit Kulkarni", "Abraham Lin"). This should be "Shubham Kapoor," for consistency.

📝 Suggested fix
-shubham kapoor,
+Shubham Kapoor,
framework/src/main/java/org/checkerframework/common/value/ValueVisitor.java (1)

437-444: Consider set-based comparison for robustness.

The index-based comparison assumes castValues and exprValues are in the same order. The integer handling (lines 372-402) uses TreeSet and sortedSetContainsAll for order-independent comparison. Consider the same approach here for consistency.

♻️ Suggested approach using set-based comparison
           if (castValues != null && exprValues != null && castValues.size() == exprValues.size()) {
-            boolean allMatch = true;
-            for (int i = 0; i < exprValues.size(); i++) {
-              double exprVal = exprValues.get(i);
-              double castVal = castValues.get(i);
-              if (Double.compare(castVal, (double) (float) exprVal) != 0) {
-                allMatch = false;
-                break;
-              }
-            }
-            if (allMatch) {
-              return true;
-            }
+            TreeSet<Double> expectedCastValues = new TreeSet<>();
+            for (Double exprVal : exprValues) {
+              expectedCastValues.add((double) (float) exprVal.doubleValue());
+            }
+            TreeSet<Double> actualCastValues = new TreeSet<>(castValues);
+            if (actualCastValues.equals(expectedCastValues)) {
+              return true;
+            }
           }

Comment on lines +155 to +156
shubham kapoor,
shubhamk0205.
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Redundant contributor entries.

Both entries appear to refer to the same contributor (name and GitHub username). Consider keeping only one entry — either the proper name "Shubham Kapoor" or the username "shubhamk0205", but not both.

📝 Suggested fix (keep only proper name)
 Zhiping Cai,
-shubham kapoor,
-shubhamk0205.
+Shubham Kapoor.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
shubham kapoor,
shubhamk0205.
Zhiping Cai,
Shubham Kapoor.
🤖 Prompt for AI Agents
In `@docs/manual/contributors.tex` around lines 155 - 156, Remove the redundant
contributor entry by keeping only the proper name "Shubham Kapoor" and deleting
the duplicate username "shubhamk0205." Locate the two lines containing "shubham
kapoor," and "shubhamk0205." in the contributors list and remove the username
entry (or vice versa if you prefer the username), ensuring formatting and
punctuation match the surrounding entries.

@shubhamk0205
Copy link
Author

@mernst all checks are passing please review this pr when u get time

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