[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