Skip to main content

W0087 - discouraged_type

Severity: Warning

Problem​

This diagnostic fires on type positions holding one of the types configured for the linter.

-module(main).
-spec lookup(key()) -> dynamic().
%% ^^^^^^^^^ 💡 warning: W0087: `dynamic()` is a discouraged type.

Explanation​

A project may want to discourage some types, for example loose types such as dynamic(), map() or term(), which say little about the values they describe and so hide bugs from the type checker and from readers. Which types are discouraged is a project decision, so you list them in the [discouraged_type] section of .elp_lint.toml:

[discouraged_type]
types = [
"dynamic()",
"map()",
"#{_ => _}",
"list()",
"tuple()",
"fun()",
"{error, term()}",
"term()",
]

Each entry is an Erlang type. It is compared structurally with every type in -spec, -type, -opaque, -nominal and -callback attributes and in -record field types, so spacing, parentheses and an explicit erlang: qualifier on a built-in type make no difference. Type variables are compared by name: #{_ => _} matches that map type, not #{K => V}. The list is closed and there is no notion of subtyping: listing map() does not report #{atom() => binary()}. Entries cannot use macros.

A type that comes from a macro is reported on the macro call. When matches nest, only the outermost one is reported: with the configuration above, {error, term()} is reported once, not also as term().

The linter is enabled by default but does nothing until types is configured.

Fix​

Replace the type with one that is not discouraged, typically a more specific one.