statix icon indicating copy to clipboard operation
statix copied to clipboard

bool comparison false positive

Open nrdxp opened this issue 3 years ago • 6 comments

There are cases where we may want to test a value that may or may not be a boolean like so if v == true. Statix currently suggests I reduce this to if v.

If I do the reduction, and v is not a boolean, evaluation aborts with a type mismatch error. I could change it to if builtins.isBool v && v, but if v == true seems more concise in that case.

nrdxp avatar Sep 08 '22 19:09 nrdxp

I could change it to if builtins.isBool v && v

I think that would make it obvious that the value might not be a boolean whereas v == true seems pretty redundant and also without statix could easily be refactored out.

SuperSandro2000 avatar Sep 08 '22 20:09 SuperSandro2000

One is more explicit the other more concise, I guess my main concern is that if v == true and if v are not semantically equivalent.

nrdxp avatar Sep 08 '22 20:09 nrdxp

would you have a few examples of this scenario? perhaps there are some heuristics to determine and avoid such cases.

oppiliappan avatar Sep 10 '22 04:09 oppiliappan

@nerdypepper For a snippet like this:

let
  f = value:
    if <condition>
      then <first branch>
      else <second branch>;
in
f <argument>

The below is a table that shows the evaluation result when <condition> and <argument> are replaced with different values:

condition value argument evaluation result
value true <first branch>
value 2 error: value is an integer while a Boolean was expected
value == true true <first branch>
value == true 2 <second branch>
isBool value && value true <first branch>
isBool value && value 2 <second branch>

statix prints the following output when the condition is value == true:

[W01] Warning: Unnecessary comparison with boolean
   ╭─[default.nix:3:8]
   │
 3 │     if value == true
   ·        ──────┬──────
   ·              ╰──────── Comparing value with boolean literal true
───╯

The warning message suggests that value == true and value are equivalent but this is not true. value == true can be replaced with isBool value && value but not with value.

ilkecan avatar Sep 24 '22 01:09 ilkecan

This is a function that I use:

let
  # Imply that `cond` is not falsy, if it is,
  # return `default` and otherwise `val`.
  imply = cond: val: implyDefault cond null val;
  implyDefault = cond: default: val:
    if (cond == null) || cond == false || cond == { } || cond == [ ] || cond == ""
    || cond == 0 then
      default
    else
      val;
in

Statiz wants to change cond == false to !cond, which is incorrect.

spikespaz avatar Sep 21 '23 04:09 spikespaz