当前位置:  开发笔记 > 编程语言 > 正文

结构的透析器错误

如何解决《结构的透析器错误》经验,为你挑选了1个好方法。

这是Elixir 1.3中最小的破坏示例:

defmodule Foo do
  @type t :: %__MODULE__{x: non_neg_integer}
  defstruct x: 0

  @spec test(t) :: t
  def test(%__MODULE__{} = foo), do: test2(foo)

  @spec test2(t) :: t
  defp test2(%__MODULE__{} = foo), do: %__MODULE__{foo | x: 5}

end

这无法使用以下方式键入check : foo.ex:9: The variable _@1 can never match since previous clauses completely covered the type #{'__struct__':='Elixir.Foo', _=>_}.

我搜索和搜索过,不能为我的生活找到解释这意味着什么,或如何解决它.



1> Dogbert..:

如果您将代码简化为:

defmodule Foo do
  @type t :: %__MODULE__{x: non_neg_integer}
  defstruct x: 0

  @spec set_x_to_5(t) :: t
  def set_x_to_5(%__MODULE__{} = foo), do: %__MODULE__{foo | x: 5}
end

然后反编译生成的.beam文件,得到:

set_x_to_5(#{'__struct__' := 'Elixir.Foo'} = foo@1) ->
    case foo@1 of
      _@1 = #{'__struct__' := 'Elixir.Foo'} -> _@1#{x := 5};
      _@1 -> erlang:error({badstruct, 'Elixir.Foo', _@1})
    end.

如果您仔细查看caseElixir生成的语句%__MODULE__{foo | x: 5},您将看到它包含一个永远不能匹配的分支,因为__struct__它保证Foo在该函数内部.这是由Elixir生成的,因为如果您使用具有不同结构的%Struct{map | ...}语法,Elixir会抛出错误map:

iex(1)> defmodule Foo, do: defstruct [:x]
iex(2)> defmodule Bar, do: defstruct [:x]
iex(3)> %Foo{%Bar{x: 1} | x: 2}
** (BadStructError) expected a struct named Foo, got: %Bar{x: 1}

要解决此问题,您可以删除该__MODULE__部件,然后执行以下操作:

%{foo | x: 5}

结果将是相同的,你将得到没有警告.


神圣的牛,这是我在StackOverflow上收到的最快和最好的答案之一 - 非常感谢!
推荐阅读
放ch养奶牛
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有