IDEA-210123 BoxedLong.equals(BoxedInteger) is incorrectly reported as 'always true' when their unboxed value is the same

This commit is contained in:
Tagir Valeev
2019-04-02 09:58:29 +07:00
parent b7b906efdc
commit 4ba1315514
3 changed files with 27 additions and 0 deletions
@@ -1134,6 +1134,13 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
dfaRight instanceof DfaVariableValue && !TypeConversionUtil.isPrimitiveWrapper(dfaRight.getType())) {
return true;
}
PsiType leftType = getPsiType(dfaLeft);
PsiType rightType = getPsiType(dfaRight);
if (TypeConversionUtil.isPrimitiveWrapper(leftType) &&
TypeConversionUtil.isPrimitiveWrapper(rightType) && !leftType.equals(rightType)) {
// Boxes of different type (e.g. Long and Integer), cannot be equal even if unboxed values are equal
return negated;
}
DfaValue unboxedLeft = SpecialField.UNBOX.createValue(myFactory, dfaLeft);
DfaValue unboxedRight = SpecialField.UNBOX.createValue(myFactory, dfaRight);
@@ -1149,6 +1156,15 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
return applyRelation(unboxedLeft, unboxedRight, negated);
}
@Nullable
private static PsiType getPsiType(@NotNull DfaValue value) {
if (value instanceof DfaFactMapValue) {
TypeConstraint constraint = ((DfaFactMapValue)value).get(DfaFactType.TYPE_CONSTRAINT);
return constraint == null ? null : constraint.getPsiType();
}
return value.getType();
}
private boolean checkCompareWithBooleanLiteral(DfaValue dfaLeft, DfaValue dfaRight, boolean negated) {
if (dfaRight instanceof DfaConstValue) {
Object constVal = ((DfaConstValue)dfaRight).getValue();
@@ -0,0 +1,10 @@
class Main {
public static void main(String[] args) {
Integer a = 1;
Integer b = 2;
Long c = 3L;
System.out.println(true);
System.out.println(<warning descr="Result of 'c.equals(a+b)' is always 'false'">c.equals(a+b)</warning>);
}
}
@@ -661,4 +661,5 @@ public class DataFlowInspectionTest extends DataFlowInspectionTestCase {
public void testInlineSimpleMethods() { doTest(); }
public void testInferenceForNonStableParameters() { doTest(); }
public void testNullableTernaryInConstructor() { doTest(); }
public void testEqualityLongInteger() { doTest(); }
}