Credence.Pattern.NoFindValueDefaultCase (credence v0.7.1)

Copy Markdown

Detects Enum.find_value/2 where the result is immediately checked against nil to provide a default, instead of using the 3-arity version that accepts a default argument.

Bad

case Enum.find_value(list, &process/1) do
  nil -> :default
  val -> val
end

Enum.find_value(list, &process/1) || :default

Good

Enum.find_value(list, :default, &process/1)

Auto-fix

Replaces the case/|| wrapper with the 3-arity call.

Safety

This rule is deliberately limited to Enum.find_value, and (for the case form) only when the nil -> clause comes first. The reason is that the rewrite must give the exact same answer for every input:

  • Enum.find/2 is not covered. find/2 returns the matching element, which can itself be nil (or false). A genuinely found nil element would be treated as "not found" by both the case nil -> clause and by Enum.find/3 differently (find/3 returns the found nil, the case returns the default), so the answers diverge. find_value only ever returns a truthy value or nil, so nil unambiguously means "nothing found".

  • The identity clause must come after the nil -> clause. If it comes first (val -> val; nil -> d) it matches nil too, making the nil -> clause dead code — the expression then returns nil (never the default), so rewriting to /3 would change the answer.

  • || is safe only for find_value (its result is never false). Enum.find/2 || default is not covered: a found false/nil element is falsy and would wrongly fall through to the default.