Gradualizer
Gradualizer copied to clipboard
function_clause error in typechecker:unary_op_arg_type/2 with --use_beams
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
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}]}]
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()
).
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?
Actually, I also added unary_op_arg_type(_Op, {var, _, _}) -> type(any)
on that branch to check if it fixes the crash.
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.
@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.
I think all the stability problems flagged in this ticket are now solved on the master branch:
-
function_clause
intypechecker,unary_op_arg_type
-
noproc
ofgradualizer_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?