Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
### Does -callback work with Dialyzer? | ||
|
||
I'm not so sure at this point. I've run the following using Erlang R15B02 (we're on an old version). | ||
```bash | ||
> dialyzer --build_plt --apps erts stdlib kernel | ||
Compiling some key modules to native code... done in 0m17.77s | ||
Creating PLT /Users/Ceryni/.dialyzer_plt ... | ||
Unknown functions: | ||
compile:file/2 | ||
compile:forms/2 | ||
compile:noenv_forms/2 | ||
compile:output_generated/1 | ||
crypto:des3_cbc_decrypt/5 | ||
crypto:start/0 | ||
Unknown types: | ||
compile:option/0 | ||
done in 0m27.91s | ||
done (passed successfully) | ||
> dialyzer dude.erl runner.erl no_spec_dude.erl spec_dude.erl | ||
Checking whether the PLT /Users/Ceryni/.dialyzer_plt is up-to-date... yes | ||
Proceeding with analysis... | ||
runner.erl:7: Function run/0 has no local return | ||
runner.erl:9: The call spec_dude:hey_dude(42) breaks the contract (Say::string()) -> Res::string() | ||
done in 0m0.31s | ||
done (warnings were emitted) | ||
``` | ||
|
||
So as you see, dialyzer issues a warning on line 9 but not line 8 as I would have expected. The `-spec` defined in `spec_dude.erl` is the same as the `-callback` defined on the behavior `dude.erl`. I'm not sure why but it seems like dialyzer is not applying the `-callback` to the implementing callback module `no_spec_dude.erl`. | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
ivoryfitz
Owner
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
-module(dude). | ||
|
||
-callback hey_dude(Say :: string()) -> Res :: string(). |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
-module(no_spec_dude). | ||
|
||
-behaviour(dude). | ||
|
||
-export([hey_dude/1]). | ||
|
||
hey_dude(Say) -> | ||
lists:flatten(io_lib:format("Hey Dude, ~p", [Say])). |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
-module(runner). | ||
|
||
|
||
-export([run/0]). | ||
|
||
-spec run() -> ok. | ||
run() -> | ||
io:format("~p", [no_spec_dude:hey_dude(42)]), | ||
io:format("~p", [spec_dude:hey_dude(42)]). |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
-module(spec_dude). | ||
|
||
-behaviour(dude). | ||
|
||
-export([hey_dude/1]). | ||
|
||
-spec hey_dude(Say :: string()) -> Res :: string(). | ||
hey_dude(Say) -> | ||
lists:flatten(io_lib:format("Hey Dude, ~p", [Say])). |
Indeed!
-callback
specifications are not automatically applied to behaviour implementations, hence the need for your-spec
. What-callback
specifications do is ensure that the implementation itself conforms to the specification described by the behaviour. If theno_spec_dude:hey_dude/1
was trying to add 1 toSay
before printing it you would get the following:Does this clear things up?