“ Dialyzer通常永远不会出错”,但我无法弄清楚我的@spec如何不正确

时间:2018-11-14 14:24:15

标签: elixir dialyzer

我有一些无法通过透析器的代码,我不明白为什么。无论我在函数顶部的@spec中放入什么内容,对该函数的调用都会返回令人困惑的透析器错误。这是功能的简化。据我所知,我已经正确指定了该功能。

@spec balances(uuid :: String.t(), retries :: non_neg_integer) ::
        {:ok, list()}
        | {:internal_server_error, String.t(), String.t()}
        | {:internal_server_error, map | list, String.t()}
def balances(uuid, retries \\ 0) do
  url = "/url/for/balances" |> process_url

  case HTTPoison.get(
         url,
         [, {"Content-Type", "application/json"}],
         []
       ) do
    {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
      response = Poison.decode!(body, as: %{"message" => [%Currency{}]})

      cond response["message"] do
        length(bal) > 0 ->
          {:ok, bal}

        retries >= 1 ->
          {:ok, []}

        true ->
          init(uuid)
          balances(uuid, retries + 1)
      end

    {:error, %HTTPoison.Error{reason: reason}} ->
      Notifier.notify(url, reason, Helpers.line_info(__ENV__))
      {:internal_server_error, reason, url}

    {_, %HTTPoison.Response{body: body} = res} ->
      response = Poison.decode!(body)
      Notifier.notify(url, response, Helpers.line_info(__ENV__))

      {:internal_server_error, response, url}
  end
end

我的问题是,如果我希望得到除{:ok, balances}之外的任何内容,那么跨代码库对该函数的每次调用都会失败:

  user_balances =
    case balances(uuid) do
      {:ok, user_balances} -> user_balances
      _ -> [] # Dialyzer error here
    end

Dialyzer警告The variable _ can never match since previous clauses completely covered the type {'ok',[map()]}。我的意思是,任何对余额的调用都将始终返回{:ok, balances},但事实并非如此,因为HTTPoison.get的case语句是函数中最后评估的事情,它似乎具有只有三种可能的结果:

  • {:ok, list}
  • {:internal_server_error, String.t(), String.t()}
  • {:internal_server_error, map | list, String.t()}

我知道我可能会遗漏一些非常明显的内容,但是我无法弄清楚它是什么。任何帮助将不胜感激。谢谢!

1 个答案:

答案 0 :(得分:2)

由于@legoscia的评论,我调查了对Notifier.notify的调用,并确定在该函数中也有一个透析器警告(我将PR转到一个开放源代码项目,以修复引起该问题的规范。通知功能使透析仪失败)。如果我修改了notify函数,使得不发生警告,请确保对balances的调用不再产生透析器警告。

tl; dr如果透析器给您有关似乎未正确指定功能的警告,请开始遍历功能内的函数调用以查找下游透析器错误。