Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IntelliJ IDEA Reporting Contract Violation Warning

Here is the Java code:

public static boolean anyEqual(Object needle, Object... haystack) {
    if(needle == null || haystack == null) {
        return false;
    }
    if(haystack.length == 0) {
        return false;
    }
    for(Object match : haystack) {
        if(match != null && needle.getClass() == match.getClass() && needle.equals(match)) {
            return true; // warning from IntelliJ here, 'contract clause !null, null -> false is violated'
        }
    }
    return false;
}

Does anyone have any idea why this is being shown? contract clause !null, null -> false is violated? Thanks!

IntelliJ 14.0.2 build: 139.659

Screenshot: enter image description here

like image 427
jn1kk Avatar asked Feb 12 '15 18:02

jn1kk


2 Answers

IntelliJ is inferring the formal contract of your method to be this:

null, _ -> false; !null, null -> false

What this actually means:

  • The first contract specifies that, so long as the first parameter is null, it will return false. This is observed by your first if statement:

    if(needle == null || haystack == null) {
        return false;
    }
    
  • The second contract specifies that, if the second parameter is null, then it will return false. This is also specified by the same if statement above.

My gut is telling me that IntelliJ is having some trouble discerning what the loop's formal contract is in addition to all of the above, although it'd be as simple as another condition in the contract expression.

for(Object match : haystack) {
    if(match != null && needle.getClass() == match.getClass() && needle.equals(match)) {
        return true;
    }
}

Let's briefly go through this.

  • The enhanced-for statement won't fire if haystack is of length 0, so that's something to take into consideration.
  • The elements inside of the array could be null, and I'm not entirely sure that IntelliJ's static analysis covers that piece yet.
  • We've established already that needle must be non-null, so there's nothing violating the contract at that line.
  • If we have a scenario in which match != null && needle.getClass() == match.getClass() && needle.equals(match) is true, we return true. Otherwise, we return false.

There's nothing that I can see in the formal documentation that gives us the expression we require to say, "hey - we're checking elements of an array!"; it may be the case that the analysis is tripping up on the fact that we're returning true in spite of what we stated above (since haystack is non-null).

Allow me to stress this point:

haystack has to be non-null in order for you to enter into the enhanced-for. Your code will not work otherwise.

All in all, I wouldn't worry about it. Better yet, file a bug against it so that this sort of thing could be fixed or expanded upon.

like image 63
Makoto Avatar answered Sep 20 '22 19:09

Makoto


This looks like an IntelliJ bug to me, since by removing the static keyword from the method the warning disappears.

Something must be confusing the static analysis here. One can always submit this to youtrack so jetbrains devs can look at it.

Someone already reported this issue Here

(tested on v14.0.3)

like image 34
vikingsteve Avatar answered Sep 18 '22 19:09

vikingsteve