elixirdialyzertypespec

Typed list typespec never breaks the contract


If you define a typespec and use a different type of parameter it will display an error similar to:

binary() ... breaks the contract ... boolean()

For example this typespec:

@spec check?(binary) :: boolean

But it doesnt seem to work for a typed List, or at least, it will never display the warning, if I have a method which receives a list of strings I would define this typespec:

@spec check?([String.t]) :: boolean

I can then define any spec for the list and it will never complain when running a dialyzer, i.e:

@spec check?(list(boolean)) :: boolean
@spec check?(list(Conn)) :: boolean
@spec check?(list(number)) :: boolean
@spec check?(list(integer)) :: boolean

Is that intended? it looks like if I defined a list with any type [any()]

Is there other way to achieve this?


Solution

  • The reason this happens is that all the list types include the empty list as a valid value.

    For example, in the following case:

    Dialyzer will conclude that there is a possible solution, namely if the list is empty. Since Dialyzer only prints warnings if it can conclude that a certain piece of code will always crash, it doesn't print one in this case.

    I'm not aware of any good solution to this. If you want to explicitly require non-empty lists, you can use e.g. nonempty_list(boolean) instead of list(boolean).