Dialyzer not being able to recognize a UXID as a string?

Has anyone come across dialyzer not being able to recognize a UXID as a binary()? The UXID will be the second argument in the function I am passing, yet dialyzer does not recognize it as a string unless I interpolate the UXID like this #{"uxid_interpolated"}

Function.function_name([], [nil | map(), ...])

will never return since the 2nd arguments differ
from the success typing arguments:

([any()], [binary()])

Can you please share some more code?

As there is no “native” UXID support in elixir nor erlang, we can do nothing but guessing here.

Oh I just asked a coworker who helped solve it. So we have UXID setup in our system. So just in the dialyzer of the function, and the other function that our function calls on, we had to put the type spec to be [UXID.t()].

UUIDs have a string representation, but that’s just a convenient translation of a long sequence of binary data that fits into hexadecimal form. UUIDs are binarys, but not strings, at heart.

My guess is your UXID generator is returning a binary of the raw-bits nature, not a unicode string, but interpolation ("#{uxid}") implicitly calls to_string, and so passes the dialyzer check. This may actually be unintended behaviour if the uxid is not a struct that implements the String.Chars protocol to correctly turn it into the readable hexadecimal form, if it’s a raw-bits-version binary it’s probably doing something else entirely.

The utility functions documentation of the UUID library reveals how it is just a struct wrapping a raw binary, but with intentional hex encoding formatting functions, and a default hex implementation of the String.Chars protocol.

1 Like