Dialyzer能看透Mnesia的交易功能吗



以下是一些带有错误的代码,我认为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的返回类型。

那么,记忆事务函数是Dialyzer的一个障碍,还是Dialyzer返回类型推断有更普遍的障碍?

mnesia_tm:execute_transaction中,所提供的fun是在catch内部调用的,这意味着就Dialyzer而言,返回类型会塌陷为term()。因此Dialyzer无法得出mnesia:activity/2的返回类型与所提供函数的返回类型相同的结论,因此需要一个显式的类型规范。

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

-module(foo).
-export([foo/1]).
foo(F) ->
    F(42).

typer显示以下内容:

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

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

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

相关内容

  • 没有找到相关文章

最新更新