Skip to content

Oddities related to quoted imports #13878

@lukaszsamson

Description

@lukaszsamson

Elixir and Erlang/OTP versions

Erlang/OTP 26 [erts-14.2.5.3] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [jit]

Elixir 1.17.3 (compiled with Erlang/OTP 26)

Operating system

any

Current behavior

I noticed some strange behavior related to quoted imports. Given this compilation tracer

defmodule MyTracer do
  def trace(event, _env) do
    dbg(event)
    :ok
  end
end
Code.put_compiler_option(:tracers, [MyTracer])

when I compile this code

defmodule MyModule do
      def aaa, do: :ok
      defmacro bbb, do: :ok
      defmacro foo do
          quote do
              aaa()
              &aaa/0
              bbb()
              &bbb/0
              inspect(1)
              &inspect/1
              Node.list()
              &Node.list/0
          end
      end
end

The emitted traces are

[iex:7: MyTracer.trace/2]
event #=> :defmodule

[iex:7: MyTracer.trace/2]
event #=> {:imported_macro, [line: 2, column: 3], Kernel, :defmacro, 2}

[iex:7: MyTracer.trace/2]
event #=> {:remote_function, [line: 2], :elixir_def, :store_definition, 3}

[iex:7: MyTracer.trace/2]
event #=> {:remote_function, [line: 1], :elixir_utils, :noop, 0}

[iex:7: MyTracer.trace/2]
event #=> {:imported_function, [line: 5, column: 7], Kernel, :inspect, 1}

[iex:7: MyTracer.trace/2]
event #=> {:imported_quoted, [line: 5, column: 15], Kernel, :/, [2]}

[iex:7: MyTracer.trace/2]
event #=> {:imported_quoted, [line: 5, column: 8], Kernel, :inspect, [1, 2]}

[iex:7: MyTracer.trace/2]
event #=> {:imported_quoted, [line: 4, column: 7], Kernel, :inspect, [1, 2]}

[iex:7: MyTracer.trace/2]
event #=> {:on_module,
 <<70, 79, 82, 49, 0, 0, 6, 16, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 176,
   0, 0, 0, 17, 15, 69, 108, 105, 120, 105, 114, 46, 78, 121, 77, 111, 100, 117,
   108, 101, 8, 95, 95, 105, 110, 102, 111, 95, ...>>, :none}

[iex:7: MyTracer.trace/2]
event #=> :stop
  1. There are undocumented trace events :imported_quoted
  2. Only &inspect/1 results in a trace event. No similar events for remote and local captures
  3. No events for calls

Next, when I eval the macro, it outputs this AST

apply(MyModule, :"MACRO-foo", [__ENV__])
{:__block__, [],
 [
   {:aaa, [], []},
   {:&, [],
    [
      {:/, [context: MyModule, imports: [{2, Kernel}]],
       [{:aaa, [], MyModule}, 0]}
    ]},
   {:bbb, [], []},
   {:&, [],
    [
      {:/, [context: MyModule, imports: [{2, Kernel}]],
       [{:bbb, [], MyModule}, 0]}
    ]},
   {:inspect, [context: MyModule, imports: [{1, Kernel}, {2, Kernel}]], [1]},
   {:&, [imports: [{1, Kernel}], context: MyModule],
    [
      {:/, [context: MyModule, imports: [{2, Kernel}]],
       [
         {:inspect, [context: MyModule, imports: [{1, Kernel}, {2, Kernel}]],
          MyModule},
         1
       ]}
    ]},
   {{:., [], [{:__aliases__, [alias: false], [:Node]}, :list]}, [], []},
   {:&, [],
    [
      {:/, [context: MyModule, imports: [{2, Kernel}]],
       [
         {{:., [], [{:__aliases__, [alias: false], [:Node]}, :list]},
          [no_parens: true], []},
         1
       ]}
    ]}
 ]}
  1. Why is Kernel added twice in meta imports: [{1, Kernel}, {2, Kernel}]?

Expected behavior

  1. Trace event should be documented. Code documentation does not mention any private events and suggests the list given there is exhaustive

I'm not sure if emitting {:imported_quoted, [line: 5, column: 15], Kernel, :/, [2]} should happen

  1. Either all captures should emit events, none should emit events, or if import is special then it should be documented
  2. Call probably should emit events

Alternatively it's possible that events in quoted are not needed at all

  1. This looks strange but I don't understand the code in :elixir_quote so it may be correct

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions