Skip to main content

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.