-module(kc_error_on_otp29).
-export([run/1]).
%%%
-define(state, 'kc_error_on_otp29.state').
-record(?state, {}).
%%%
run(AST_Source) ->
AST = get_ast_from(AST_Source),
FoldFun = fun(_Node, Acc) -> Acc end,
FormList = erl_syntax:form_list(AST),
[] = erl_syntax_lib:fold(FoldFun, [], FormList),
#?state{}.
%%%
get_ast_from(beam_chunks) ->
{ok, {?MODULE, [{abstract_code, {raw_abstract_v1, AST}}]}} =
beam_lib:chunks(code:which(?MODULE), [abstract_code]),
AST;
get_ast_from(compiled_source) ->
{ok, [], AST, []} = compile:file("src/kc_error_on_otp29.erl", [to_pp, binary, return]),
AST;
get_ast_from(ktn_dodger) ->
File = "src/kc_error_on_otp29.erl",
{ok, AST} = ktn_dodger:parse_file(File, [no_fail, parse_macro_definitions]),
AST.
1> kc_error_on_otp29:run(beam_chunks).
{'kc_error_on_otp29.state'}
2> kc_error_on_otp29:run(compiled_source).
{'kc_error_on_otp29.state'}
3> kc_error_on_otp29:run(ktn_dodger).
** exception error: no case clause matching macro
in function erl_syntax:subtrees/1 (erl_syntax.erl:8077)
in call from erl_syntax_lib:fold/3 (erl_syntax_lib.erl:124)
in call from erl_syntax_lib:fold_2/3 (erl_syntax_lib.erl:137)
in call from erl_syntax_lib:fold_1/3 (erl_syntax_lib.erl:132)
in call from erl_syntax_lib:fold/3 (erl_syntax_lib.erl:128)
in call from erl_syntax_lib:fold_2/3 (erl_syntax_lib.erl:137)
in call from erl_syntax_lib:fold_1/3 (erl_syntax_lib.erl:132)
in call from erl_syntax_lib:fold/3 (erl_syntax_lib.erl:128)
1> kc_error_on_otp29:run(beam_chunks).
{'kc_error_on_otp29.state'}
2> kc_error_on_otp29:run(compiled_source).
{'kc_error_on_otp29.state'}
3> kc_error_on_otp29:run(ktn_dodger).
{'kc_error_on_otp29.state'}
===> Running provider: hank
===> Looking for code to kill with fire...
===> Hank rules: [single_use_hrl_attrs,single_use_hrls,
unnecessary_function_arguments,unused_callbacks,
unused_configuration_options,unused_hrls,
unused_macros,unused_record_fields]
===> Hank Context: #{project_apps => [lager],
app_dirs =>
#{lager =>
"/home/[...]/fake_lager"}}
===> Hank will use 12 files for analysis: ["elvis.config",
"include/lager.hrl",
"rebar.config",
"src/fake_lager_app.erl",
"src/fake_lager_pr.erl",
"src/fake_lager_sup.erl",
"src/lager.app.src",
"src/lager.erl",
"src/lager_msg.erl",
"src/lager_transform.erl",
"test/config/sys.config",
"test/fake_lager_tests_pr_SUITE.erl"]
===> error analyzing files: {case_clause,macro}
Stack: [{erl_syntax,subtrees,1,[{file,"erl_syntax.erl"},{line,8077}]},
{erl_syntax_lib,fold,3,[{file,"erl_syntax_lib.erl"},{line,124}]},
{erl_syntax_lib,fold_2,3,[{file,"erl_syntax_lib.erl"},{line,137}]},
{erl_syntax_lib,fold_1,3,[{file,"erl_syntax_lib.erl"},{line,132}]},
{erl_syntax_lib,fold,3,[{file,"erl_syntax_lib.erl"},{line,128}]},
{erl_syntax_lib,fold_2,3,[{file,"erl_syntax_lib.erl"},{line,137}]},
{erl_syntax_lib,fold_1,3,[{file,"erl_syntax_lib.erl"},{line,132}]},
{erl_syntax_lib,fold,3,[{file,"erl_syntax_lib.erl"},{line,128}]}]
===> Uncaught error in rebar_core. Run with DIAGNOSTIC=1 to see stacktrace or consult rebar3.crashdump
===> Uncaught error: {error,<<"{case_clause,macro}">>}
Bug Description
On OTP 29,
rebar3_hankfails to run when a record name is a macro: an exception is thrown from withinerl_syntax_lib. This didn't happen on OTP 28 or older.I assume the root origin to be in
katana_code- not inrebar3_hanknor inerl_syntax_lib- since the AST returned byktn_dodgerresults in the exception, unlike the AST returned bybeam_libor thecompiler. Further investigation may prove otherwise.This is where the exception is raised:
https://github.com/erlang/otp/blob/550d7b7898706c7822362c42e7b93120c1d1f29a/lib/syntax_tools/src/erl_syntax.erl#L8077-L8080
To Reproduce
Given the following test module and a shell with access to
katana_code(rebar3 test app: kc_error_on_otp29.zip):I get this on OTP 29:
Expected Behavior
What I get when I run the test on OTP 28:
rebar3LogsThe original error I encountered with
rebar3_hank1.6.1:Additional Context
katana_coderef:8264b4a