Can't define type "product()" in OTP 26.0.2

Hello there!

When I try to create type product(), dialyzer reported an error:

===> Error in dialyzing apps: Analysis failed with error:
Unable to find type 'fun'/2

Last messages in the log cache:
  Reading files and computing callgraph... done in 0.13 secs
  Removing edges... done in 0.00 secs

Full module looks like this:

-module(test_product_app).

-behaviour(application).

-export([start/2, stop/1, test/0]).

-type product() :: binary().

start(_StartType, _StartArgs) ->
    test_product_sup:start_link().

stop(_State) ->
    ok.

-spec test() -> Result when
    Result :: product().
test() ->
    <<"123">>.

If I remove -spec for function test, then error not reproduced.

I use Erlang/OTP 26.0.2 on Debian 10 with rebar3 v. 3.22.1

Anybody knows is it bug in dialyzer or I use it wrong?

2 Likes

Confirmed on OTP 26.0-rc1 and 26.0.0 (but it works wo error on 25.3.2.5) with rebar 3.22.0

1 Like

It’s look like a bug…

I’m pretty sure this going to be related to abstract code (raw_abstract_v1), specifically function types

If I take the following code, compile it, then dump the abstract code (thanks to beam_lib:chunks/2) we can spot something in there :slight_smile:

:point_down: erlang source

-module(whoops).

-export([oops/0]).

-type eh() :: any().

-spec oops() -> eh.
oops() ->
    ok.

:point_down: abstract code

{ok,{whoops,[{abstract_code,{raw_abstract_v1,[{attribute,{1,
                                                          1},
                                                         file,
                                                         {".../devel/erlang/whoops/src/whoops.erl",1}},
                                              {attribute,{1,2},module,whoops},
                                              {attribute,{3,2},export,[{oops,0}]},
                                              {attribute,{5,2},type,{eh,{type,{5,15},any,[]},[]}},
                                              {attribute,{7,2},
                                                         spec,
                                                         {{oops,0},
                                                          [{type,{7,11},
                                                                 'fun',
                                                                 [{type,{7,...},product,...},{atom,{...},...}]}]}},
                                              {function,{8,1},
                                                        oops,0,
                                                        [{clause,{8,1},[],[],[{atom,{...},...}]}]},
                                              {eof,{10,1}}]}}]}}

:point_up: I see the term product in there :slight_smile:

We can also state that at least in some places dialyzer uses beam chunks to do its work.

I can not assert that this is 100% the case, but I think it’s a reasonable hypothesis. Regardless, it’s definitely a bug and bug report would be fantastic :slight_smile:

1 Like

Ok, so I couldn’t help myself :stuck_out_tongue:

I changed my source code to product() and did the same as above, but this time with some printf debugging in erl_types, here’s what the function type_from_form1/12 gets and fails on :

{fun,[{user_type,{7,11},product,[]},{user_type,{7,17},product,[]}],2,#{{type,product,0}=>{{whoops,{"...devel/erlang/whoops/src/whoops.erl",{5,2}},{type,{5,20},any,[]},[]},any}},{type,{whoops,fun,2}},[],{spec,{whoops,oops,0},"...devel/erlang/whoops/src/whoops.erl"},{from_form,{spec,{whoops,oops,0},"...devel/erlang/whoops/src/whoops.erl"},#Ref<0.513244525.2512519169.32828>,#Ref<0.513244525.2512519169.32827>,#{},[]},16,10000,{cache,#{},#{whoops=>#{{type,product,0}=>{{whoops,{"...devel/erlang/whoops/src/whoops.erl",{5,2}},{type,{5,20},any,[]},[]},any}}}}}

If my eyes are not failing me (possible!) then we’re falling down because lookup_type/3 is missing a match for user_type. Don’t know this code well, so either a big ole miss, or a subtle bug was introduced somewhere before we hit here (i.e., something responsible for translating user_type to type was missed).

That’s as far as I will go on this one (for now) :slight_smile: , but I hope that helps with the bug report.

Edit:

My eyes were failing me, something goes wrong before lookup_type/2, the lookup for module types doesn’t end well, it seems. Seems like fun/2 getting passed to lookup_type/3 is strange, going back to the original hypothesis that something is getting gunked up with the translation along the way per the use of the term product in the abstract code. Might be less nefarious than that though.

Definitely interested to know more :slight_smile:

Thanks a lot for your diagnostic! I opened bug issue on github.

1 Like