[erlang-questions] Dialyzer warning on pattern match with sub-record

Russell Brown russell@REDACTED
Thu Mar 30 09:04:10 CEST 2017


Hi,

I have a dialyzer error I can’t figure out, at all, it’s truly very weird, even for dialyzer.

The error is: 

riak_kv_vnode.erl:2695: Matching of pattern State = {'state', _, _, _, _, _, VId, _, _, _, _, _, _, _, _, _, _, _, _, _, {'counter_state', 'false', _, _, _, _}, _, _} tagged with a record name violates the declared type of #state{idx::'undefined' | integer(),mod::atom() | tuple(),async_put::'false' | 'true' | 'undefined',vnodeid::'undefined' | binary(),delete_mode::'immediate' | 'keep' | 'undefined' | pos_integer(),bucket_buf_size::'undefined' | pos_integer(),index_buf_size::'undefined' | pos_integer(),key_buf_size::'undefined' | pos_integer(),async_folding::'false' | 'true' | 'undefined',in_handoff::boolean(),handoff_target::atom(),handoffs_rejected::integer(),forward::atom() | [{integer(),atom()}],hashtrees::'undefined' | pid(),upgrade_hashtree::boolean(),md_cache::atom() | tid(),md_cache_size::'undefined' | pos_integer(),counter::'undefined' | #counter_state{use::'true',cnt::non_neg_integer(),lease::non_neg_integer(),lease_size::non_neg_integer(),leasing::boolean()},status_mgr_pid::'undefined' | pid(),update_hook::atom() | tuple()}
  riak_object:object/0


The code in question is:

%% @private generate an epoch actor, and update the vnode state.
-spec new_key_epoch(#state{}) -> {NewEpoch::boolean(), EpochActor :: binary(), #state{}}.
new_key_epoch(State=#state{vnodeid=VId, counter=#counter_state{use=false}}) ->
    {false, VId, State};
new_key_epoch(State) ->
    NewState=#state{counter=#counter_state{cnt=Cntr}, vnodeid=VId} = update_counter(State),
    EpochId = key_epoch_actor(VId, Cntr),
    {true, EpochId, NewState}.


What is really freaky (to me) is that this code (the previous version) does not provoke a dialyzer warning:

%% @private generate an epoch actor, and update the vnode state.
-spec new_key_epoch(#state{}) -> {EpochActor :: binary(), #state{}}.
new_key_epoch(State=#state{vnodeid=VId, counter=#counter_state{use=false}}) ->
    {VId, State};
new_key_epoch(State) ->
    NewState=#state{counter=#counter_state{cnt=Cntr}, vnodeid=VId} = update_counter(State),
    EpochId = key_epoch_actor(VId, Cntr),
    {EpochId, NewState}.

The record definition for #counter_state is:

-record(counter_state, {
          use = true :: boolean(),
          cnt = 0 :: non_neg_integer(),
          lease = 0 :: non_neg_integer(),
          lease_size = 0 :: non_neg_integer(),
          leasing = false :: boolean()
         }).

I have missed out the record definition for #state as it is huge, but crucially, unchanged between the two definitions of new_key_epoch/1 above.

If the match in the function head, and the record, are exactly the same between the two versions of the code, why does the one that returns a three tuple provoke a warning?

Many thanks in advance if you can help

Cheers

Russell




More information about the erlang-questions mailing list