【问题标题】:Can Dialyzer see through Mnesia transaction functions?Dialyzer 可以看穿 Mnesia 交易功能吗?
【发布时间】:2013-07-10 20:23:29
【问题描述】:

这是一些我认为 Dialyzer 应该能够发现的错误代码:

-module(myapp_thing).

-spec exists(pos_integer()) -> yes | no.
exists(Id) ->
    myapp_mnesia:thing_exists(Id).

 

-module(myapp_mnesia).

thing_exists(Id) ->
    Exists = fun() -> 
                     case mnesia:read({thing, Id}) of
                         [] -> false;
                         _ ->  true
                     end
             end,
    mnesia:activity(transaction, Exists).

 

myapp_thing:exists/1被指定为返回yes | no,但返回类型实际上是true | false(即boolean()),也就是myapp_mnesia:thing_exists/1返回的内容。

但是,在 myapp 上运行 Dialyzer 会通过它而不会发出警告。

如果我将myapp_mnesia:thing_exists/1 更改为只返回true,我会收到适当的警告;同样,如果我添加正确的规范:

-spec session_exists(pos_integer()) -> boolean().

但看起来 Dialyzer 无法查看 mnesia 事务函数 Exists 内部,或者由于某些其他原因无法推断出 thing_exists 的返回类型。

那么,mnesia 事务函数是 Dialyzer 的障碍,还是 Dialyzer 的返回类型推断存在更普遍的障碍?

【问题讨论】:

  • 据我所知,mnesia:activity/2 没有-spec 类型。添加 -spec mnesia:activity(atom(), fun(()->X)) -> X. 之类的内容可能会有所帮助(尽管我还没有尝试过)。
  • 函数规范中可以有类型变量!?凉爽的! erlang.org/doc/reference_manual/typespec.html#id76207 但是,我宁愿不摆弄 mnesia 源。我在 myapp_mnesia 中键入函数。我想了解更多有关 Dialyzer 推理障碍的信息。

标签: erlang mnesia dialyzer


【解决方案1】:

mnesia_tm:execute_transaction 中,提供的乐趣在catch 内被调用,这意味着就Dialyzer 而言,返回类型折叠为term()。因此,Dialyzer 无法断定 mnesia:activity/2 的返回类型与提供的函数的返回类型相同,因此需要明确的类型规范。

此外,我相信 Dialyzer 通常不会根据作为参数提供的函数的返回值来推断返回值类型。例如,使用这个模块:

-module(foo).

-export([foo/1]).

foo(F) ->
    F(42).

打字机显示如下:

$ typer /tmp/foo.erl

%% File: "/tmp/foo.erl"
%% --------------------
-spec foo(fun((_) -> any())) -> any().

虽然如果我添加显式类型规范 -spec foo(fun((_) -> X)) -> X.,那么 typer 会接受它。

(我相信 Dialyzer 开发人员会对此有更完整、更有洞察力的答案。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-24
    • 1970-01-01
    • 2018-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多