How to fix "warning: function X is undefined or private" in my macro?

I’ve written a small library to serialize Ecto results/changesets into a specific shape needed for a project I’m working on.

Here is the GitHub repo: https://github.com/somlor/tyson

Since upgrading to Elixir 1.3 I’m seeing several warnings running my tests:

warning: function Tyson.FederationSerializer.attributes/1 is undefined or private
  test/support/serializers/federation_serializer.ex:2

warning: function Tyson.FederationSerializer.attributes/2 is undefined or private
  test/support/serializers/federation_serializer.ex:2
...

It appears the culprit are these direct (non-apply) function calls here:
https://github.com/somlor/tyson/blob/db7750041f3d964fae0c239a2571a663dacccd00/lib/tyson/serializer.ex#L201

The problem is, if I rewrite them using apply, e.g.,

apply(__MODULE__, :attributes, [raw_data])

The warnings disappear but another very strange thing happens. My tests pass the first time after save, but then fail consistently afterwards. :confused:

Any ideas on what I’m doing wrong? Also feel free to tear apart my code in general, it’s my first Elixir library.

Thanks!
Sean

1 Like

This is killing me. :upside_down:

Trying to fix warnings again today, in a separate branch I’ve consolidated code into one file for simplicity, renamed the attributes callback to attributes_filter, for clarity (since there is also a macro named attributes) and specified these as an @optional_callbacks. Still no dice. :confused:

https://github.com/somlor/tyson/pull/1/files

This seems related:

Note: Unlike Erlang, user defined attributes are not stored in the module by default. The value exists only during compilation time. A developer can configure an attribute to behave closer to Erlang by calling Module.register_attribute/3.

1 Like

Thanks for your input!

Interesting, I wasn’t aware of this function. I’m definitely suspecting it’s related to compilation time, considering my tests pass once on compile but then fail after.

Unfortunately I’m not sure register_attribute will help in this case, since it pertains to Elixir @attributes whereas this problem is related to a function that just happens to be called attributes.

Ah, likely not then. Can you reduce it to a minimal test-case? I’m not able to test at moment but I or another possibly could soon? :slight_smile:

1 Like

I think I figured it out finally! :nerd: I stopped trying to support multiple arities for attributes function (now called attributes_filter) and defined a default version along with a defoverridable.

https://github.com/somlor/tyson/blob/5de91cb38831c1964a0db6818ca98d266fde2d9a/lib/tyson.ex#L15

1 Like