W0060 - Bound Variable in LHS
Error
handle_request(Message) ->
Message = next_action().
%% ^^^^^^^ 💡 warning: W0060: Match on a bound variable
Explanation
This diagnostic flags cases where a variable that is already bound appears on the left-hand side (LHS) of a match expression. This can be problematic if the binding is not intentional and can lead to subtle bugs.
Consider the following code snippet:
foo() ->
AA = foo(),
AA = bar().
The pattern on line 3 will only match if and only if the result of the call to bar/0 is the same as the call to foo/0. This behaviour could be intentional or not. If not, it can easily lead to bugs.
How to fix
First decide whether the match is meant to check that the two values are equal.
Remove a redundant match
If the match can never fail, for example because it repeats a call that always returns the same value, remove it together with any variables that become unused:
%% Before
foo() ->
Config = get_config(),
Config = get_config(),
ok.
%% After
foo() ->
_Config = get_config(),
ok.
Make the check explicit
Replacing a match with an equality check is not always equivalent. A pattern can match a value without being equal to it: #{a := 1} matches any map that has the key a with the value 1, whatever other keys it has. Keep the original semantics when making the check explicit.
An alternative, more explicit, way to express that behaviour - when intentional - could be:
foo() ->
AA = foo(),
BB = bar(),
AA = BB.
Or using an assertion, which is preferred in test code:
foo() ->
AA = foo(),
?assertEqual(AA, bar()).
Semantic highlighting
Note that we also have semantic highlighting of the more general case, where a bound variable appears in any pattern.