<div dir="ltr"><div dir="ltr"></div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Aug 20, 2019 at 8:26 AM Valentin Micic <<a href="mailto:v@micic.co.za">v@micic.co.za</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="overflow-wrap: break-word;">Hi all,<div><br></div><div>Recently I’ve made a silly mistake. I wrote:</div><div><br></div><div><div style="margin:0px;font-stretch:normal;line-height:normal"><font face="Courier New">case Payload of</font></div><div style="margin:0px;font-stretch:normal;line-height:normal"><font face="Courier New"> <<_:4/binary-unit:8, _:<b><font color="#e32400">255</font></b>, _:7/binary-unit:8, 0:16>> -> Payload;</font></div><div style="margin:0px;font-stretch:normal;line-height:normal"><font face="Courier New"> _ -> throw( drop )</font></div><div style="margin:0px;font-stretch:normal;line-height:normal"><font face="Courier New">end</font></div></div><div style="margin:0px;font-stretch:normal;line-height:normal"><div><font face="Courier New"><br></font></div><div><font face="Courier New"><br></font></div><div>Considering that overall pattern (which erroneously references 255 bits long field, instead of an octet with a value of 255 ) is not aligned to 8-bit boundary, is it unreasonable to expect the compiler to report this as a potential problem, or at least generate a warning (support for bit-fields notwithstanding).</div><div><br></div><div>What am I missing here?</div><br></div></div></blockquote><div> </div><div>There are informally two kinds of binaries: 8-bit aligned binaries (regular ones) are those people call 'binaries', and then you have bitstrings. Bitstrings don't need any alignment whatsoever. Your pattern can be made to work by using any fitting bitstring. For example:</div><div><br></div><div>1> <<_:4/binary-unit:8, _:255, _:7/binary-unit:8, 0:16>> = <<0:(32+255+7*8+16)>>.<br><<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,<br> 0,...>></div><div><br></div><div>But more generally, the binary/bitstring distinction will make sense when pattern matching:</div><div><br></div><div>3> <<_:4/binary-unit:8, _/binary>> = <<0:(32+255+7*8+16)>>. <br>** exception error: no match of right hand side value <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,<br> 0,...>></div><div>4> <<_:4/binary-unit:8, _/bitstring>> = <<0:(32+255+7*8+16)>>.<br><<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,<br> 0,...>></div><div>5> <<_:4/binary-unit:8, _/bits>> = <<0:(32+255+7*8+16)>>. <br><<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,<br> 0,...>><br><br></div><div></div><div>Note that bits is shorthand for bitstring. Do note as well that you can always cheat the pattern match by specifying units:</div><div><br></div><div>6> <<_:4/binary-unit:8, _/binary-unit:1>> = <<0:(32+255+7*8+16)>>.<br><<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,<br> 0,...>><br></div><div><br></div><div>Nothing in Erlang actually mandates exact alignment, it's just that with the default widths of various types impacts pattern matching. Dialyzer, however, does enforce some semantic values. Here's a sample module:</div><div><br></div><div>-module(chk).<br>-export([f/0, f/1, g/0, g/1]).<br><br>f() -> f(<<0:17>>).<br>g() -> g(<<0:17>>).<br><br>-spec f(binary()) -> ok.<br>f(Bin) -><br> <<_/binary>> = Bin,<br> ok.<br><br>-spec g(binary()) -> ok.<br>g(Bin) -><br> <<_/bits>> = Bin,<br> ok.</div><div><br></div><div>If you run dialyzer on it, you'll find out the following:</div><div><br></div><div>chk.erl:4: Function f/0 has no local return<br>chk.erl:4: The call chk:f(<<_:17>>) will never return since the success typing is (binary()) -> 'ok' and the contract is (binary()) -> 'ok'<br>chk.erl:5: Function g/0 has no local return<br>chk.erl:5: The call chk:g(<<_:17>>) breaks the contract (binary()) -> 'ok'</div><div><br></div><div>the type binary(), to Dialyzer, implies the 8-bit alignment you're looking after. The bitstring() type will not care for alignment. This is because Dialyzer supports defining binary types as:</div><div></div><div><pre> <<>> %% empty binary
<<_:M>> <span class="gmail-hljs-comment">%% fixed-size binary, where M is a positive integer</span>
<<_:_*N>> <span class="gmail-hljs-comment">%% variable-size binary with an alignment on N</span>
<<_:M, _:_*N>> %% binary of at least M size, with a variable-sized tail aligned on N</pre></div><div>Essentially, binary() is defined as <<_:_*8>> and bitstring() is defined as <<_:_*1>>. This lets you encode whatever check semantics you'd like within type specifications, and Dialyzer can try to figure it out for you. But nothing, by default, would necessarily warrant compiler warnings since alignment on 8 bits is not mandated by the runtime.<br></div><div><br></div></div></div>