defmodule TypeCheck.Builtin.Reference do
@moduledoc """
Type to check whether the given input is a reference.
Elixir/Erlang uses references for two use-cases:
1. As unique identifiers.
2. To refer to resources created and returned by NIFs (to be passed to other NIFs of the same NIF module).
The property testing generator will generate arbitrary references using `Kernel.make_ref()`.
To property-test the second kind of data, you should create your own kind of generator
that calls the appropriate NIF.
"""
defstruct []
use TypeCheck
@type! t :: %__MODULE__{}
@type! problem_tuple :: {t(), :no_match, %{}, any()}
defimpl TypeCheck.Protocols.ToCheck do
def to_check(s, param) do
quote generated: true, location: :keep do
case unquote(param) do
x when is_reference(x) ->
{:ok, [], x}
_ ->
{:error, {unquote(Macro.escape(s)), :no_match, %{}, unquote(param)}}
end
end
end
end
defimpl TypeCheck.Protocols.Inspect do
def inspect(_, opts) do
"reference()"
|> Inspect.Algebra.color(:builtin_type, opts)
end
end
if Code.ensure_loaded?(StreamData) do
defimpl TypeCheck.Protocols.ToStreamData do
def to_gen(_s) do
# Ensure every iteration we create a _different_ reference
StreamData.constant({})
|> StreamData.map(fn _ -> make_ref() end)
end
end
end
end