2013-07-10 28 views
2

下面是一些代码,我认为透析器应该能够发现错误:透析器能透过Mnesia交易功能吗?

-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(). 

但它看起来像透析器不能看Mnesia的交易功能内部存在,或因其他原因不能推断thing_exists返回类型。

那么,mnesia交易对Dialyzer来说是一个障碍,还是对Dialyzer的返回类型推断有一个更普遍的障碍?

+0

据我所看到的,'函数mnesia:活动/ 2'没有一个类型'-spec '。添加类似'-spec mnesia:activity(atom(),fun(() - > X)) - > X.'可能会有帮助(尽管我没有尝试过)。 – legoscia

+0

你可以在函数规范中使用类型变量!?凉! http://www.erlang.org/doc/reference_manual/typespec.html#id76207但是,我宁愿不拨弄mnesia来源。我正在myapp_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.,然后打字员接受它。

(我敢肯定,透析器开发人员将可以更完整和深入的答案。)

+0

完美的答案,谢谢! –