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.

_______________________________________________
eeps mailing list
[email protected]
http://erlang.org/mailman/listinfo/eeps

Reply via email to