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

t() issues with struct!/2 #177

Open
alanvardy opened this issue May 19, 2023 · 1 comment
Open

t() issues with struct!/2 #177

alanvardy opened this issue May 19, 2023 · 1 comment

Comments

@alanvardy
Copy link
Contributor

Code:

  @type t :: %__MODULE__{
          ..fields here
        }


  @doc false
  @spec new(map) :: t()
  def new(params) do
    struct!(__MODULE__, params)
  end

Error

The function call on line 44 is expected to have type t() but it has type struct()
42   @spec new(map) :: t()
43   def new(params) do
44     struct!(__MODULE__, params)
45   end
46 end
@erszcz
Copy link
Member

erszcz commented Jun 15, 2023

Hey, Alan!

This requires an explicit downcast, since not every struct() is a valid t(). You know this particular one is, but the typechecker doesn't. That's where Gradient.TypeAnnotation comes in handy:

defmodule TestStruct do
  use Gradient.TypeAnnotation

  defstruct f: "some value"

  @type t :: %__MODULE__{
    :f => String.t()
  }

  @doc false
  @spec new(map) :: t()
  def new(params) do
    struct!(__MODULE__, params) |> assert_type(t())
  end
end

That way struct!/2 does the runtime check that params are valid for this particular struct, whereas assert_type(_, t()) let's the typechecker know that from now on it's not a general struct() type instance, but a proper t() instance.

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

2 participants