[erlang-questions] dialyzer and #record vs tuple

Kostis Sagonas kostis@REDACTED
Fri Jun 7 11:08:18 CEST 2013


On 06/07/13 11:50, Vincent de Phily wrote:
> Hi List,
>
> I'm doing a long-overdue set of dialyzer checks on our software, and have a
> few occurences of the following problem:
>
>> % Define a record with a constrained field
>> -record(foo, {bar = 0 :: integer()}).
>>
>> % Use the record, works as expected
>> new_foo(Id) ->  #foo{bar=Id}.
>>
>> % Use a similar-looking tuple, dialyzer complains about
>> %     Record construction #foo{bar::true} violates the declared type of
>> %     field bar::integer()
>> default_options() ->  [{foo, true}].
>
> I understand why dialyzer gets confused, since it can't (?) differenciate
> between a "raw" tuple and a record. But at the semantic level, they really are
> different things, so changing the record definition to allow booleans doesn't
> really make sense.
>
> How would you handle that kind of problem ? So far I have resorted to changing
> either the name of the record or the tag/arity of the tuple, but it generally
> feels wrong and inelegant, and later commits might inadvertantly reintroduce
> the natural-but-clashing tuple.

There is no perfect `solution' to this .

Dialyzer works at a level where records have been expanded into tuples 
and thus records and tuples are indistinguishable between them. 
Furthermore, it makes the assumption that within a module any tuple with 
a record tag and with a size that matches some typed record declaration 
refers to the declared types. So you have two options:

  1. Use different tags for records and tuples e.g. foo_rec vs. foo (as 
you write)

  2. Do not declare types for records that for some reason or another 
you also want to have similar looking tuples (as you write, declaring 
the "union" of the types does not make much sense).

 From the two options, I personally very much prefer the first.

Kostis



More information about the erlang-questions mailing list