jn1kk
jn1kk

Reputation: 5102

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

Upvotes: 7

Views: 1441

Answers (3)

Makoto
Makoto

Reputation: 106430

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.

Upvotes: 5

vikingsteve
vikingsteve

Reputation: 40388

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)

Upvotes: 1

zmitrok
zmitrok

Reputation: 378

This message is being shown because IntelliJ checks for method contract violations. It's a relatively new feature, read more at https://www.jetbrains.com/idea/features/annotation_java.html

Upvotes: -3

Related Questions