Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dialyzer error #109

Open
OvermindDL1 opened this issue Jan 16, 2019 · 1 comment
Open

Dialyzer error #109

OvermindDL1 opened this issue Jan 16, 2019 · 1 comment

Comments

@OvermindDL1
Copy link

OvermindDL1 commented Jan 16, 2019

For the given code:

  def changeset(struct, params \\ %{}) do
    struct
    |> cast(params, [:id, :type, :data, :removed_at])
    |> cast_attachments(params, [:file_id])
    |> validate_required([:id, :type, :file_id])
  end

The cast_attachments(params, [:file_id]) expression is causing a dialyzer failure of (some formatting so it's actually readable):

The pattern
  #{'__meta__':=_}
can never match the type
  #{'__struct__':='Elixir.Ecto.Changeset',
    'action':='delete' | 'ignore' | 'insert' | 'nil' | 'replace' | 'update',
    'changes':=#{atom()=>_},
    'constraints':=[
      #{'constraint':=binary(),
        'error_message':=binary(),
        'error_type':=atom(),
        'field':=atom(),
        'match':='exact' | 'prefix' | 'suffix', 'type':='check' | 'exclusion' | 'foreign_key' | 'unique'
      }
    ],
    'data':='nil' | map(),
    'empty_values':=_,
    'errors':=[{atom(),{_,_}}],
    'filters':=#{atom()=>_}, 'params':='nil' | #{binary()=>_},
    'prepare':=[fun((_) -> any())],
    'repo':=atom(),
    'repo_opts':=[{atom(),_}],
    'required':=[atom()],
    'types':='nil' | #{atom()=>atom() | {'array',_} | {'embed',map()} | {'in',_} | {'map',_}},
    'valid?':=boolean(),
    'validations':=[{atom(),_}]
  }

In arc_ecto's schema.ex file lines 15 to 18 are:

      scope = case changeset_or_data do
        %Ecto.Changeset{} -> Ecto.Changeset.apply_changes(changeset_or_data)
        %{__meta__: _} -> changeset_or_data
      end

Because this is a defmacro the whole body is getting inlined, which is what's causing this error. There is not really a need for it to be a defmacro and it could/should probably just be a normal def, in which case the inferred spec then should work. Alternatively you can change the case changeset_or_data do to be wrapped be something like case Arc.Ecto.Schema.wrap(changeset_or_data) do to opaque it, but then you could just do the work there as well. Likely all around easier and better for cast_attachments to just not be a macro at all however. :-)

@OvermindDL1
Copy link
Author

Interestingly a PR implementing the second suggestion appears to be at #106 but has not been accepted or rejected yet a month later. Although that does fix it and keeps the API, it's probably better to just bump the API version and change the defmacro to just dev, since a cross module call is being performed anyway it doesn't save anything otherwise and can actually slow down the function calling cast_attachments due to ballooning its opcode size (not that it really matters on this path). :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant