okue / succ-typing

Clone of dialyzer.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Tips

underspecs

strictly more allowing than the success typing = specが弱い. 凡そ, "specで書かれている関数の返り値の型が, success typingで推論できない"

overspecs

strictly less allowing than the success typing = specが強い. 凡そ, "success typingで推論される関数の返り値の型が, specに書かれていない"

%% overspec
-spec hoge(number()) -> 1 | 2.
hoge(X) when X > 0   -> 1;
hoge(X) when X =:= 0 -> 2;
hoge(X) when X < 0   -> 3.

%% underspec
-spec hoge(number()) -> 1 | 2 | 4.
hoge(X) when X > 0   -> 1;
hoge(X) when X =:= 0 -> 2.

overspecsとunderspecsは排反ではない.

%% overspec and underspec
-spec hoge(number()) -> 1 | 2 | 4.
hoge(X) when X > 0   -> 1;
hoge(X) when X =:= 0 -> 2;
hoge(X) when X < 0   -> 3.

(-Wspecdiffs は, overspecsとunderspecsの両方の警告に加えて, CONTRACT_NOT_EQUAL警告を出す)

specの型とsuccess typingの型で明らかな食い違いがある場合は, invalid_contract警告が出る. "入力の型または出力の型について, specの型とsuccess typingの型で共通部分がない"など.

exported functionとlocal function

exported functionとlocal functionでは, 推論される型が異なる. ローカル関数の場合, そのモジュール内でどのような引数で呼ばれているかを見て, 推論される出力の型を小さくしてくれる. f(1 | 2) -> good | bad というローカル関数があって, 引数は常に1で, 返り値はgoodしかありえないなら, f(1) -> good と推論する.

race conditions

おそらく, ets, register, unregisterらへんの警告を出す.

specと推論される型

明らかな間違いがない限りspecの型と推論される型を組み合わせて, 推論が進む. 明らかな間違いというのは, 推論される入出力の型とspecの型に共通部分がないこと. a | b -> c | dと推論される関数に, a -> c | eと書くのは許される. a -> eは, 出力の型が間違いと見なされ警告が出る.

古いバージョンのDialyzerでは, specの出力の型と推論される出力の型で下限(inf)がnone()になる場合は, specが捨てられていた. v3.3では, 捨てられなくなっている.

specの型と推論される型の組み合わせ方

specの出力の型と推論される出力の型の下限(inf)を, 関数の出力の型として推論を進める. {dialyzer_typesig.erl, 818行}

-spec f(integer()) -> ook | error.
f(1) -> ok;
f(2) -> error.

t(X) when is_integer(X) ->
  ok = f(X).

t2(X) when is_integer(X) ->
  error = f(X).

例えば上では, fは (1 | 2) -> ok | error と推論される. fにspecが書かれていない場合, fはokまたはerrorを返す可能性があるので, 関数t, t2はパターンマッチに成功しうる. したがって, t, t2には型 (1 | 2) -> ok, (1 | 2) -> error が付く.

しかし, 今回fには, (integer()) -> ook | error というtypoを含むspecが書かれている. 関数t, t2におけるパターンマッチが成功するか否かを推論するとき, 推論されたfの型に加えてspecの内容が利用される.

推論された型 (1 | 2) -> ok | error と specの型 (integer()) -> ook | error の出力の型を組み合わせ, fの返り値の型は inf(ok | error, ook | error) = error の部分型としてパターンマッチの箇所を推論する.

tについて, fの返り値はerrorの部分型, つまりerrorなのでokとマッチしえないので, 型が付かないと警告が起こる.

t2について, fの返り値はerrorでパターンマッチに成功するので, t2には (1 | 2) -> error 型がつく.

警告の例

  1. 関数適用f(3)の引数の型が, Success typingで推論されない場合: {dialyzer.erl, 496行}
f(1) -> ok;
f(2) -> error.

t(X) when is_integer(X) ->
  ok = f(3).

%% ex1.erl:15: Function t/1 has no local return
%% ex1.erl:16: The call ex1:f(3) will never return since it differs in the 1st argument from the success typing arguments: (1 | 2)
  1. 関数適用f(3)の引数の型が, Success typingにもspecにも反する場合: {dialyzer.erl, 496行}
-spec f(1) -> ok;
       (2) -> error.
f(1) -> ok;
f(2) -> error.

t(X) when is_integer(X) ->
  ok = f(3).

%% ex1.erl:15: Function t/1 has no local return
%% ex1.erl:16: The call ex1:f(3) will never return since the success typing is (1 | 2) -> 'error' | 'ok' and the contract is (1) -> 'ok'; (2) -> 'error'
  1. 関数適用f(3)の引数の型が, specに反する場合: {dialyzer.erl, 496行}
-spec f(2) -> error.
f(1) -> ok;
f(2) -> error.

t(X) when is_integer(X) ->
  ok = f(1).

%% ex1.erl:14: Function t/1 has no local return
%% ex1.erl:15: The call ex1:f(1) breaks the contract (2) -> 'error'

build_plt時のファイルやディレクトリの指定

-c または何も付けずにディレクトリを指定すると, ディレクトリ下のBEAMファイルを探す. -r でディレクトリを指定すると, ディレクトリ下のBEAMファイルを再帰的に探す. --apps で名前を指定すると, 該当するディレクトリ直下のebin以下からBEAMファイルを再帰的に探す.


About

Clone of dialyzer.


Languages

Language:Erlang 100.0%Language:Makefile 0.0%Language:Shell 0.0%