aaronrenner / phx_gen_auth

An authentication system generator for Phoenix 1.5 applications.
774 stars 56 forks source link

Typespec issue with user_token schema #72

Closed petejodo closed 4 years ago

petejodo commented 4 years ago

This is probably an error on my part but I'm not sure what it could be.

I tried adding typespecs to some of the functions created by the generator and I'm getting a warning from dialyzer that I just can't seem to figure out why it's occurring. I generated the files by using the example in the readme i.e. mix phx.gen.auth Accounts User users and then added the following:

user.ex

  @type t() :: %__MODULE__{
    __meta__: Ecto.Schema.Metadata.t(),
    id: integer() | nil,
    email: String.t() | nil,
    password: String.t() | nil,
    hashed_password: String.t() | nil,
    confirmed_at: NaiveDateTime.t(),

    inserted_at: NaiveDateTime.t(),
    updated_at: NaiveDateTime.t()
  }

user_token.ex

  @type t() :: %__MODULE__{
    __meta__: Ecto.Schema.Metadata.t(),
    id: integer() | nil,
    token: binary() | nil,
    context: String.t() | nil,
    sent_to: String.t() | nil,
    user_id: integer() | nil,
    user: User.t() | Ecto.Association.NotLoaded.t() | nil,
    inserted_at: NaiveDateTime.t()
  }

  # ...

  # warning on this typespec
  @spec build_session_token(User.t()) :: {binary(), t()}
  def build_session_token(user) do
    token = :crypto.strong_rand_bytes(@rand_size)
    {token, %TempAuthExperiment.Accounts.UserToken{token: token, context: "session", user_id: user.id}}
  end

The warning I get is

The @spec for the function does not match the success typing of the function.

Success typing:
@spec build_session_token(atom() | %{:id => _, _ => _}) ::
  {binary(),
   %TempAuthExperiment.Accounts.UserToken{
     :__meta__ => %Ecto.Schema.Metadata{
       :context => nil,
       :prefix => nil,
       :schema => TempAuthExperiment.Accounts.UserToken,
       :source => <<_::96>>,
       :state => :built
     },
     :context => <<_::56>>,
     :id => nil,
     :inserted_at => nil,
     :sent_to => nil,
     :token => binary(),
     :user => %Ecto.Association.NotLoaded{
       :__cardinality__ => :one,
       :__field__ => :user,
       :__owner__ => TempAuthExperiment.Accounts.UserToken
     },
     :user_id => _
  }}

I feel like I barely added any code to get this to mess up. I get it has to do with the user type but I don't see why it's resolving to atom() | %{:id => _, _ => _}

josevalim commented 4 years ago

Looking at the code, it seems you should have tagged inserted_at as being possibly nil too. I am not a heavy Dialyzer though, so I recommend using the ElixirForum if you have more questions around this. :)