【问题标题】:Dialyzer says function will never be called, even though it isDialyzer 说函数永远不会被调用,即使它是
【发布时间】:2016-09-12 07:55:33
【问题描述】:

我正在使用 elixir_talk 库。连接后,我想在连接到 beanstalkd 后调用一个私有函数。我刚刚添加了 typespecs 并运行了 Dialyzer(通过 dialyxir)。我得到错误:

my_module.ex:3: The specification for 'Elixir.MyModule':f/0 states that the function might also return 'ok' | {'error',_} but the inferred return is none()
my_module.ex:4: Function f/0 has no local return
my_module.ex:14: Function g/1 will never be called

我能找到的最小例子是

defmodule MyModule do
  @spec f() :: :ok | {:error, term}
  def f() do
    case ElixirTalk.connect('127.0.0.1', 11300) do
      {:ok, conn} ->
        g(conn)
      {:error, err} ->
        {:error, err}
    end
  end

  @spec g(pid) :: :ok
  defp g(pid) do
    :ok
  end
end

如果我将调用ElixirTalk.connect 替换为调用spawn,Dialyzer 将不再报告任何问题。

defmodule MyModule do
  @spec f() :: :ok
  def f() do
    x = spawn fn -> :done end
    g(x)
  end

  @spec g(pid) :: :ok
  defp g(pid) do
    :ok
  end
end

有人知道为什么 Dialyzer 会在这里感到困惑吗?

【问题讨论】:

  • 如果将超时值作为第三个参数传递给ElixirTalk.connect,是否得到相同的结果?
  • 看看the source,类型规范说第三个参数总是一个整数,即使默认值是原子infinity。因此,无限超时调用ElixirTalk.connect 将违反类型规范。在 Erlang 中,您可以通过将类型指定为 timeout() 来解决此问题,它允许整数和 infinity;不确定这如何转化为 Elixir。
  • 不错!这也应该表现为对ElixirTalk.connect/2 本身的警告,但由于它可能在 PLT 中,所以没有显示?
  • 嗨@legoscia——也许你应该提取你的评论作为答案,这样每个人都可以看到。 :)
  • ElixirTalk.connect的返回值是多少?

标签: erlang elixir dialyzer


【解决方案1】:

查看源代码,类型规范说第三个参数始终是整数,即使默认值是原子无穷大。因此,以无限超时调用 ElixirTalk.connect 将违反类型规范。在 Erlang 中,您可以通过将类型指定为 timeout() 来解决此问题,它允许整数和无穷大;不确定这如何转化为 Elixir。 – legoscia 2016 年 5 月 16 日 15:56

【讨论】:

  • type timeout :: integer | :infinity
猜你喜欢
  • 2022-12-09
  • 2013-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-30
  • 2017-12-17
  • 2018-09-02
  • 2013-08-31
相关资源
最近更新 更多