Why does dialyxir pretends this function can't return?

Trying to clean dialyzer messages in a new Bitcoin open source library…

Why does it pretend that this function can’t return?

lib/key/address.ex:39:no_return
Function to_public_key_hash/1 has no local return.

Here is the function out of context…

  @doc """
  Extracts the public key hash from an address, and make sure the checkum is ok

  ## Examples
    iex> address = "mwYKDe7uJcgqyVHJAPURddeZvM5zBVQj5L"
    ...> BitcoinLib.Key.Address.to_public_key_hash(address)
    {:ok, <<0xafc3e518577316386188af748a816cd14ce333f2::160>>, :p2pkh}
  """
  @spec to_public_key_hash(binary()) :: {:ok, <<_::160>>, atom()} | {:error, binary()}
  def to_public_key_hash(address) do
    <<prefix::8, public_key_hash::bitstring-160, checksum::bitstring-32>> =
      address
      |> Base58.decode()

    address_type = get_address_type_from_prefix(prefix)

    case test_checksum(prefix, public_key_hash, checksum) do
      {:ok} -> {:ok, public_key_hash, address_type}
      {:error, message} -> {:error, message}
    end
  end

I made a test aside from the doctest above, and both succeed…

  test "convert an address to a public key hash" do
    address = "mtzUk1zTJzTdyC8Pz6PPPyCHTEL5RLVyDJ"

    {:ok, public_key_hash, :p2pkh} =
      address
      |> Address.to_public_key_hash()

    assert <<_::160>> = public_key_hash
  end

It’s likely an incorrect typespec either on this function, or anything in the callstack of it.

1 Like

That’s right, test_checksum/3 below was typespec’d with an integer() as the third argument while to_public_key_hash/1 was calling it with a bitstring()…

Thanks @LostKobrakai!