[eeps] Proposal for -type_assert
Michael Truog
mjtruog@REDACTED
Fri Sep 12 19:45:05 CEST 2014
On 09/12/2014 03:45 AM, Hans Bolinder wrote:
> Hi,
>
> I've been pondering your idea for a while now, thinking along the
> lines that it should be possible to do without adding any special
> syntax. It might be possible to use -Wunderspecs (or even the not
> recommended -Wspecdiffs), but there seem to be several things that
> would need to be modified in the dialyzer_contracts module, though.
> I'll try to find some time to look into the details.
>
> BTW, it would be interesting to see how you've implemented the check.
> I couldn't find any examples (looked for nowarn_unused_function), but
> I only downloaded CloudI.
I haven't used nowarn_unused_function to provide a type assertion within the CloudI source code. A module which I would want a type assertion in (once the httpc:method() type exists, I had thought it already exists) is https://github.com/CloudI/CloudI/blob/develop/src/lib/cloudi_service_http_client/src/cloudi_service_http_client.erl#L520-L535 . You can see from the module that there is an implicit assumption that "method() :: head | get | put | post | trace | options | delete" which is valid based on the current inets documentation at http://www.erlang.org/doc/man/httpc.html . A concrete example for what I had meant by "a dirty trick" is the test module at the end of the email. That approach required using -Wspecdiffs which generates a lot of noise that isn't helpful (and isn't recommended as you mentioned). So a -type_assert could make this much clearer and the developer could see a basic type assertion fail to understand that assumptions within a module are no longer
true, making it easier to update the source code.
I started thinking about this problem when using the riak erlang client source code which caused me to create the code below:
-include_lib("riakc/include/riakc.hrl").
-type index_results_check() :: {index_results_v1,
[binary()] | 'undefined',
[{integer() | binary(),
binary()}] | 'undefined',
'undefined' | binary()}.
-export_type([index_results/0]).
% code that uses index_results_check() instead of index_results() is below
That approach can provide something similar, but depends on a local type being hard-coded, replicating an external module's type. That doesn't necessarily work in the cloudi_service_http_client.erl file but may be made to work by adding more functions (unnecessary complication). So the suggestion to add -type_assert was just due to not seeing a better path to making sure dialyzer would break. I haven't attempted to implement changes to support -type_assert syntax and I am not sure about the changes required. I can help with the changes, but I thought it was important to make sure the addition is agreeable before changes are created.
Thanks,
Michael
>
> Best regards,
>
> Hans Bolinder, Erlang/OTP team, Ericsson
>
% run with:
% erlc +debug_info test.erl
% dialyzer -Wspecdiffs test.beam
-module(test).
-export([test/0]).
test() ->
ok.
% would normally be an external module's type to assert on,
% making sure that dialyzer will complain if the type changes
%-type method() :: head | get | put | post | trace | options | delete.
-type method() :: head | get | put | post | trace | options | delete | string().
-compile({nowarn_unused_function,
[{httpc_method_assert, 1},
{httpc_method_check, 1}]}).
-spec httpc_method_assert(head | get | put | post | trace | options | delete) ->
ok.
httpc_method_assert(T) ->
ok = httpc_method_check(T).
-spec httpc_method_check(method()) ->
ok.
httpc_method_check(_) ->
ok.
More information about the eeps
mailing list