I'm trying to create a typespec that represents a fixed length framed binary packet. Therefore using a bitstring of fixed N bytes (say 25 for example) seemed like the right idea.
The Elixir typespec docs stated the following:
## Bitstrings
| <<>> # empty bitstring
| <<_::size>> # size is 0 or a positive integer
| <<_::_*unit>> # unit is an integer from 1 to 256
| <<_::size, _::_*unit>>
From this I would assume you could use @spec my_type :: <_::25, _::_*8>>
@type my_type :: <<_::25, _::_*8>>
@spec my_type_test() :: my_type
def my_type_test() do
# 25 byte bitstring with start-of-frame byte
<< 0xA5::size(8) , 0::size(24)-unit(8) >>
end
But Dialyzer comes back with the following:
[ElixirLS Dialyzer] Invalid type specification for function
'TestModule':my_type_test/0. The success typing
is () -> <<_:200>>
Huh? But they're both bitstrings and the bit length is the same!
Anybody know why Dialyzer doesn't like this?
The number just after ::
specifies the number of bits, not bytes. If you want the type to match 25 bytes plus N * 8 bytes, the type needs to be:
@type my_type :: <<_::200, _::_*64>>
After this change, your original expression passes Dialyzer's checks and incrementing the size by 1 bit or 1 byte fails, as expected.