-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Description
Environment
- Elixir & Erlang/OTP versions (elixir --version): Elixir 1.13.0
- Operating system: any
Current behavior
:for
in protocol implementations creates transitive compile-time dependencies. Here you can see an example, within a basic newly created phoenix app.
Ecto.Schema wrapper:
defmodule ProtoComp.Schema do
defmacro __using__(_) do
quote do
use Ecto.Schema
@timestamps_opts type: :utc_datetime_usec
end
end
end
Schema:
defmodule ProtoComp.Things.Chair do
use ProtoComp.Schema
import Ecto.Changeset
schema "chairs" do
field :attributes, :string
field :color, :string
timestamps()
end
@doc false
def changeset(chair, attrs) do
chair
|> cast(attrs, [:color, :attributes])
|> validate_required([:color, :attributes])
end
end
Protocol:
defprotocol ProtoCompWeb.UseCases.GrabWith do
def accessories(thing)
end
Implementation:
defimpl ProtoCompWeb.UseCases.GrabWith, for: ProtoComp.Things.Chair do
def accessories(_), do: "use your hands"
end
With this setup, when running mix xref graph --label compile-connected
the result is that the Chair schema is a transitive dependency for the protocol implementation.
However, if I remove the Ecto.Schema
wrapper and use it directly, that compile-time dependency disappears:
defmodule ProtoComp.Things.Chair do
use Ecto.Schema
import Ecto.Changeset
@timestamps_opts type: :utc_datetime_usec
schema "chairs" do
field :attributes, :string
...
end
There is a thread explaining that issue also in the elixirforum: https://elixirforum.com/t/wrapping-ecto-schema-in-macro-results-in-transitive-compile-time-dependency/46611
And you can check the repo created to reproduce the issue here: https://github.com/ribanez7/protocols_compilation
Expected behavior
:for
should not add a compile-time dependency. I expect to run mix xref graph --label compile-connected
within a similar setup, using protocols implemented by ecto schemas, and not having them as transitive dependencies.