Credence.Pattern.NoListDuplicateJoin (credence v0.7.1)

Copy Markdown

Detects List.duplicate(string_literal, n) |> Enum.join() (and the nested Enum.join(List.duplicate(string_literal, n))) and suggests String.duplicate/2 instead.

When the goal is to repeat a string N times, String.duplicate/2 is the idiomatic function. LLMs often produce List.duplicate/2 followed by Enum.join/1 to achieve the same result, which is less readable and allocates an intermediate list.

Safe core: string-literal first argument only

Enum.join/1 calls to_string/1 on each element, so Enum.join(List.duplicate(value, n)) works for any value — e.g. Enum.join(List.duplicate(7, 3)) == "777". String.duplicate/2, by contrast, requires a binary and raises on anything else (String.duplicate(7, 3) raises ArgumentError). The two are only guaranteed to agree when the duplicated value is already a string.

Since a non-literal first argument (a variable, a function call) cannot be proven to be a binary syntactically, this rule fires only when the duplicated value is a string literal, where the rewrite is exactly behaviour-preserving. The n argument may be anything: both List.duplicate/2 and String.duplicate/2 require a non-negative integer and raise identically otherwise.

Bad

List.duplicate("=", n) |> Enum.join()
Enum.join(List.duplicate("=", n))

Good

String.duplicate("=", n)