Module.module_info doesn't include all behaviours

I have a module which defines a behavior

defmodule Light.Trigger do
  @callback initialize(%{}) :: {:ok, any()}

  defmacro __using__(_) do
    quote do
      use GenServer
      @behaviour Light.Trigger
      ...
    end
end

And I am using it like

defmodule Light.Test do
  use Light.Trigger
  
  @impl true
  def initialize(state) do
    {:ok, state}
  end

  @impl true
  def handle_info(:test, state) do
    ...
    {:noreply, state}
  end
end

This happens

iex> Light.Test.module_info[:attributes][:behaviour]
[GenServer]

But it should be

iex> Light.Test.module_info[:attributes][:behaviour]
[GenServer, Trigger]

right?

On further inspection:

iex> Light.Test.module_info[:attributes]
[
  vsn: [325461190013957173593492030108196297138],
  behaviour: [GenServer],
  behaviour: [Light.Test]
]
1 Like

You can use Keyword — Elixir v1.12.1 to get the list that you want.

Keyword.get_values(Light.Test.module_info[:attributes], :behaviour)
6 Likes

1.Use more idiomatic mod.module_info(:attributes).
2. It will mention only behaviours set via module attribute (you do not need to set that to implement behaviour). So there is no “100% correct” solution to list all implemented behaviours.

2 Likes

Is there a case where, the behaviour in module_info is a returned as a list with multiple behaviours? If not, should this be treated as a bug?

It should not really matter whether it accepts a list or not (it does not FYI).
This is the way attributes work with accumulate true.

1 Like

see model_info i think it’s work as expected:

Returns a list of {AttributeName,ValueList} tuples,
where AttributeName is the name of an attribute, and ValueList is a list of values.
Notice that a given attribute can occur more than once in the list with different values if the attribute occurs more than once in the module.