2013-07-10 36 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

完美的答案,謝謝! –