Credence.Pattern.NoLiteralListTypespec
(credence v0.7.0)
Copy Markdown
Correctness rule: Detects a multi-element literal list used as an
@spec return type — e.g. [pos_integer(), pos_integer()]. This is not
valid Elixir: in a typespec [type] means "a list of type", and a list
with two or more comma-separated element types raises
Kernel.TypespecError at compile time. LLMs translating fixed-size return
values from other languages (a Python tuple, say) emit this shape.
The fix converts the literal list to a tuple, the idiomatic way to
express a fixed-size heterogeneous type. A @spec has no runtime effect and
the original does not compile, so the rewrite only ever touches already-broken
specs.
Scope (deliberately narrow)
Only fires when every element is a plain type call (pos_integer(),
atom(), String.t(), list(integer()), …). It does not touch:
- keyword-list types (
[ok: integer(), error: atom()]) — those are valid; - non-empty list types (
[type, ...]) — also valid; literal-atom lists (
[:ok, :error]) — ambiguous (likely a:ok | :errorunion, not a tuple), so left for a human;- single-element list types (
[type]) — valid.
Bad
@spec foo(integer()) :: [pos_integer(), pos_integer()]Good
@spec foo(integer()) :: {pos_integer(), pos_integer()}