Skip to main content

W0025 - Boolean Precedence

Warning​

foo(X) ->
predicate(X) or X > 10.
%% ^^ 💡 warning: 'or' has higher precedence than the operator around it, so this may not be grouped as intended.
%% | Use 'orelse' instead, or add parentheses to make the grouping explicit.

Explanation​

The and/or operands have higher precedence than comparison ops (unlike andalso/orelse) so this could be a source of bugs.

17> F = fun(X) -> is_integer(X) and X > 0 end.
#Fun<erl_eval.42.105768164>
18> F(-1).
** exception error: bad argument
in operator and/2
called as true and -1

Note that changing this may affect the semantics, as and/or always evaluate both arguments, so guarantee any side-effects in those computations take place. In contrast, andalso/orelse do short circuit evaluation so may not execute the RHS of the expression.

Fixes​

Two fixes are available. elp lint --apply-fix applies the first one, unless another is selected with --fix-id:

  • boolean_precedence_replace_operator: replace and with andalso (or , in a guard) and or with orelse.
  • boolean_precedence_add_parens: keep the operator and add parentheses around the operand of the surrounding operator, e.g. predicate(X) or (X > 10).

If it is necessary to use and/or, you can preceed the expression with a special comment to silence the linter:

% elp:ignore W0025 - An optional explanation here