Skip to content

OTP 29: exception thrown if record name is a macro #98

@g-andrade

Description

@g-andrade

Bug Description

On OTP 29, rebar3_hank fails to run when a record name is a macro: an exception is thrown from within erl_syntax_lib. This didn't happen on OTP 28 or older.

I assume the root origin to be in katana_code - not in rebar3_hank nor in erl_syntax_lib - since the AST returned by ktn_dodger results in the exception, unlike the AST returned by beam_lib or the compiler. 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):

-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.

I get this on OTP 29:

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)

Expected Behavior

What I get when I run the test on OTP 28:

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'}

rebar3 Logs

The original error I encountered with rebar3_hank 1.6.1:

===> 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}">>}

Additional Context

  • katana_code ref: 8264b4a
  • OS: GNU/Linux
  • Erlang version: OTP 29.0 / OTP 28.4.1
  • rebar3 version: 3.27.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions