-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
no dialyzer error if function specification comes from a behaviour #6369
Comments
tl;dr I think this is somewhat expected, but I can see an argument for changing how this works. Why does Dialyzer comes to this conclusion?As I understand it, Dialyzer uses specs as follows:
Dialyzer uses behaviours as follows:
Notably, unlike specs, behaviours don't seem to be used to refine the success type during Dialyzer's dataflow analysis. Although, if a spec is present, the spec will be checked for an overlap with the behaviour, and the implementation will be checked for an overlap with the spec. This means the callback type can have a second-order affect via constraining the spec type, even though it doesn't directly refine the success typing. Could Dialyzer use the behaviour to refine the dataflow analysis and catch the issue?I don't see why not. Looking at the code I linked to above, the dataflow analysis could simply do another Why don't more people complain about this?My best guess is that most of users who would locate this issue would also have linting or similar around exporting and spec'ing callback implementations, so typically they wouldn't be in this state of comparing the effect of the behaviour's type with and without a spec. I also suspect there's a historical effect here, perhaps due to specs and behaviours being introduced at different times, and behaviours having some special cases (such as allowing implementations of callbacks to return Next steps@bjorng / @kikofernandez / @jhogberg: Is my reasoning along the right lines? Does it make sense to include the behaviour type in dataflow analysis like the spec is? Should we make that change? |
I upvote for this. I've lost count of the number of times I've spec'ed a behaviour to repeat the spec in the implementing function, and at the same time having to potentially tweak both when the spec changes 😢. Also, if we're going with the potential change suggested by @TD5 we should also remember the erl_opt |
How would |
And in case the above wasn't convoluted enough, we recently also changed the logic for precisely how we validate a spec against a callback in #6243 |
You'd have something like -module(impl).
-behaviour(bvr).
-export([foo/1, test/0]).
% -type t() :: #{ x => integer(), y => boolean() }.
-impl(bvr).
foo(M) ->
M.
test() ->
foo(#{ x => 12, z => 12 }). Edit: fwiw, this ( Edit: and also, it'd have to be optional for backward compatibility (let the linters take care of warning about it not being present), but if present should be validated against an existing behaviour declaration (and |
I think this motivation, but I wonder if it might better be served by an in-editor hint that would show the type of the corresponding callback definition? |
Describe the bug
the same function specification regarding maps gives a dialyzer error when using
-spec
but gives no error when implementing a behaviour and inferring the type from a-callback
specificationTo Reproduce
given the following behaviour in
bvr.erl
:and the implementation
impl.erl
:no dialyzer error is raised:
Hovewer, decommenting the two lines in
impl.erl
(or removing the behaviour at all and just using thegiven spec
), it correctly gives an error:Expected behavior
the error should be raised in both cases
Affected versions
Tested with master branch, version
Erlang/OTP 26 [DEVELOPMENT] [erts-13.1.1] [source-aa922e1216]
Additional context
The text was updated successfully, but these errors were encountered: