Gradualizer icon indicating copy to clipboard operation
Gradualizer copied to clipboard

function_clause error in typechecker:unary_op_arg_type/2 with --use_beams

Open jesperes opened this issue 3 years ago • 7 comments

Trying to run gradualizer on my "Advent of Code" solutions (https://github.com/jesperes/aoc_erlang) triggered a function_clause error when running rebar3 gradualizer --use_beams:

===> Uncaught error: function_clause
===> Stack trace to the error location:
[{typechecker,unary_op_arg_type,
              ['-',{var,0,"_TyVar-576460752303423391"}],
              [{file,"/home/jespereskilson/dev/aoc_erlang/_build/default/plugins/gradualizer/src/typechecker.erl"},
               {line,2735}]},
 {typechecker,type_check_unary_op_in,5,
              [{file,"/home/jespereskilson/dev/aoc_erlang/_build/default/plugins/gradualizer/src/typechecker.erl"},
               {line,2728}]},
 {typechecker,type_check_expr_in,3,
              [{file,"/home/jespereskilson/dev/aoc_erlang/_build/default/plugins/gradualizer/src/typechecker.erl"},
               {line,2051}]},
 {typechecker,'-type_check_call_ty/4-lc$^0/1-0-',2,
              [{file,"/home/jespereskilson/dev/aoc_erlang/_build/default/plugins/gradualizer/src/typechecker.erl"},
               {line,1864}]},
 {typechecker,'-type_check_call_ty/4-lc$^0/1-0-',2,
              [{file,"/home/jespereskilson/dev/aoc_erlang/_build/default/plugins/gradualizer/src/typechecker.erl"},
               {line,1865}]},
 {typechecker,type_check_call_ty,4,
              [{file,"/home/jespereskilson/dev/aoc_erlang/_build/default/plugins/gradualizer/src/typechecker.erl"},
               {line,1865}]},
 {typechecker,do_type_check_expr,2,
              [{file,"/home/jespereskilson/dev/aoc_erlang/_build/default/plugins/gradualizer/src/typechecker.erl"},
               {line,1434}]},
 {typechecker,type_check_expr,2,
              [{file,"/home/jespereskilson/dev/aoc_erlang/_build/default/plugins/gradualizer/src/typechecker.erl"},
               {line,1311}]}]

To reproduce:

  • Clone https://github.com/jesperes/aoc_erlang/commit/573a16409e9cf2b29ccb5fdfb809c2da407d845c
  • Do rebar3 gradualizer --use_beams

Gradualizer version: 0.1.3 Verified on OTP versions: 24.0.6, 23.3.4.2

jesperes avatar Oct 20 '21 07:10 jesperes

With latest gradualizer version (today's master), the error is different

Error: {noproc,{gen_server,call,[gradualizer_db,{get_spec,lists,map,2},5000]}}
[{gen_server,call,3,[{file,"gen_server.erl"},{line,247}]},
 {typechecker,type_check_fun,3,
              [{file,"/home/jespereskilson/dev/aoc_erlang/_build/default/plugins/gradualizer/src/typechecker.erl"},
               {line,3025}]},
 {typechecker,do_type_check_expr,2,
              [{file,"/home/jespereskilson/dev/aoc_erlang/_build/default/plugins/gradualizer/src/typechecker.erl"},
               {line,1547}]},
 {typechecker,type_check_expr,2,
              [{file,"/home/jespereskilson/dev/aoc_erlang/_build/default/plugins/gradualizer/src/typechecker.erl"},
               {line,1425}]},
 {typechecker,infer_clause,2,
              [{file,"/home/jespereskilson/dev/aoc_erlang/_build/default/plugins/gradualizer/src/typechecker.erl"},
               {line,3267}]},
 {lists,map,2,[{file,"lists.erl"},{line,1243}]},
 {typechecker,infer_clauses,2,
              [{file,"/home/jespereskilson/dev/aoc_erlang/_build/default/plugins/gradualizer/src/typechecker.erl"},
               {line,3247}]},
 {typechecker,type_check_fun,2,
              [{file,"/home/jespereskilson/dev/aoc_erlang/_build/default/plugins/gradualizer/src/typechecker.erl"},
               {line,1804}]}]

jesperes avatar Oct 20 '21 07:10 jesperes

Thanks for the report!

The noproc error is probably specific to the rebar3 plugin. My guess is that it doesn't start gradualizer as an OTP application, or something like that which was changed recently in the rest of Gradualizer, except in the rebar3 plugin. (@erszcz makes sense?) I guess we don't have enough tests for it. Fixes and tests are very welcome.

Have you tried running the standalone Gradualizer escript or from an Erlang shell?

If you do, I guess you'll get the other error. It looks like there's a missing clause for unary operators (not, bnot, -, +) with (implicit) type variable.

A simple workaround would be to add unary_op_arg_type(_Op, {var, _, _}) -> type(any);, but if we want to catch some type errors here, we should consider the Op and (if we think the constraints solving will ever work) also add constraints on the type variable (e.g. for not A we add A :: boolean()).

zuiderkwast avatar Oct 20 '21 08:10 zuiderkwast

The noproc error is probably specific to the rebar3 plugin. My guess is that it doesn't start gradualizer as an OTP application, or something like that which was changed recently in the rest of Gradualizer, except in the rebar3 plugin. (@erszcz makes sense?)

It seems so, indeed.

@jesperes Could you try this branch - https://github.com/erszcz/Gradualizer/tree/start-app-in-rebar-plugin - to check if noproc goes away?

erszcz avatar Oct 20 '21 09:10 erszcz

Actually, I also added unary_op_arg_type(_Op, {var, _, _}) -> type(any) on that branch to check if it fixes the crash.

erszcz avatar Oct 20 '21 09:10 erszcz

I tried the https://github.com/erszcz/Gradualizer/tree/start-app-in-rebar-plugin on jesperes/aoc_erlang@573a164 - the Rebar plugin app startup and the unary_op_arg_type issues are gone, but Gradualizer falls into an infinite loop.

I guess the next step for Gradualizer in general is to get more serious about https://github.com/josefs/Gradualizer/pull/324, since it's also a blocker for correctness fixes as outlined in https://github.com/josefs/Gradualizer/pull/359.

erszcz avatar Oct 20 '21 10:10 erszcz

@jesperes Could you try this branch - https://github.com/erszcz/Gradualizer/tree/start-app-in-rebar-plugin - to check if noproc goes away?

I confirm that commit e0a1dbc286596be34cffd45807ffec656aec61b9 resolves the noproc issue.

berbiche avatar Oct 25 '21 21:10 berbiche

I think all the stability problems flagged in this ticket are now solved on the master branch:

  • function_clause in typechecker,unary_op_arg_type
  • noproc of gradualizer_db

In other words, we can run Gradualizer on https://github.com/jesperes/aoc_erlang, it will not crash, it will terminate, and it will report warnings, as evidenced by https://gist.github.com/erszcz/4323e97860e67da290f52e2b0998a863.

There are still known correctness issues, i.e. some false positives might be reported - these are a work in progress. I think we can close this ticket. @zuiderkwast @jesperes what do you think?

erszcz avatar Mar 01 '22 11:03 erszcz