Dialyzer does not recognize type

I am defining specs in my project, but dialyzer doesn’t seem to pick up the types I am creating.

Code

defmodule Mastery.Core.Question do

  alias Mastery.Core.Template
  alias __MODULE__

  @type t() :: %__MODULE__{
    asked: String.t,
    template: Template.t,
    substitutions: %{substitution: any}
  }

  @enforce_keys [:asked, :substitutions, :template]
  defstruct ~w[asked substitutions template]a

  @spec new(Template.t) :: Question.t
  def new(%Template{} = template) do
    template.generators
    |> Enum.map(&build_substitution/1)
    |> evaluate(template)
  end

@spec evaluate(any, Template.t) :: Question.t
  defp evaluate(substitutions, template), do:
    %__MODULE__{
      asked: compile(template, substitutions),
      substitutions: substitutions,
      template: template
    }

  @spec compile(Template.t, Enum.t) :: String.t
  defp compile(template, substitutions) do
    template.compiled
    |> Code.eval_quoted(assigns: substitutions)
    |> elem(0)
  end
end

This is small piece of the code I have>. Dialyzer reports the following:

Function new/1 has no local return

Which happens because the evaluate function has an incorrect spec. I don’t see how that is the case.

Question

What am I doing wrong?

2 Likes

I can’t say if that’s necessarily the issue, but having substitutions declared as any() in evaluate/2 and as Enum.t() in compile/2 does not seem right.
Having a look at Template might help too.

4 Likes