Credence.Pattern.InconsistentParamNames
(credence v0.7.0)
Copy Markdown
Detects functions where the same positional parameter uses different variable names across clauses.
Why this matters
LLMs generate function clauses semi-independently, often drifting parameter names between clauses of the same function:
# Flagged — first arg is "current" in one clause, "prev" in another
defp do_fibonacci(current, _next, 0), do: current
defp do_fibonacci(prev, current, steps), do: do_fibonacci(current, prev + current, steps - 1)
# Consistent — same name at each position across all clauses
defp do_fibonacci(prev, _current, 0), do: prev
defp do_fibonacci(prev, current, steps), do: do_fibonacci(current, prev + current, steps - 1)Inconsistent names make the reader question whether the function is
correct — if the first argument is called current in one clause and
prev in another, which is it?
Auto-fix strategy
The first clause establishes canonical base names. Subsequent clauses
are renamed to match. Underscore prefixes are preserved: if a clause
uses _banana and the canonical base is number, it becomes _number.
Bare _ and non-variable patterns (literals, destructuring) at a
given position cause that position to be skipped entirely.
Pattern-match equality between arguments
When the same variable name appears at multiple argument positions within one clause — top-level or nested inside a tuple, list, map, struct, or binary — Elixir enforces equality between those positions:
def validate(errors, q, ans, ans), do: errors # 3rd arg must equal 4th
def lookup(id, %User{id: id}), do: id # top-level arg must equal nested fieldSuch names are load-bearing. Renaming one occurrence breaks the equality; renaming a free name in another clause to the same target invents an equality that wasn't there. Whenever any clause in a group has such an intra-clause name sharing, every position that participates is skipped — for both detection and renaming — so the rule never produces an unsafe fix.