   compiled match_spec, nor can it be stored on disk).
   """
   @spec compile_requirement(Requirement.t()) :: Requirement.t()
-  def compile_requirement(%Requirement{matchspec: spec} = req) do
-    %{req | matchspec: :ets.match_spec_compile(spec), compiled: true}
+  def compile_requirement(requirement) do
+    Requirement.compile(requirement)
   end
 
   defp to_matchable(%Version{major: major, minor: minor, patch: patch, pre: pre}, allow_pre?) do

    match?(version, parse_requirement!(requirement), opts)
  end

  def match?(version, %Requirement{matchspec: spec, compiled: false}, opts) do
    allow_pre = Keyword.get(opts, :allow_pre, true)
    {:ok, result} = :ets.test_ms(to_matchable(version, allow_pre), spec)
    result != false
  end

  def match?(version, %Requirement{matchspec: spec, compiled: true}, opts) do
    allow_pre = Keyword.get(opts, :allow_pre, true)
    :ets.match_spec_run([to_matchable(version, allow_pre)], spec) != []
  end

  @doc """


    defstruct [:source, :matchspec, :compiled]

    @opaque t :: %__MODULE__{
              source: String.t(),
              matchspec: :ets.match_spec() | :ets.comp_match_spec(),
              compiled: boolean
            }

    @doc false
    @spec new(String.t(), :ets.match_spec()) :: t
    def new(source, spec) do
      %__MODULE__{source: source, matchspec: spec, compiled: false}
    end

    @doc false
    @spec compile(t) :: t
    def compile(%__MODULE__{matchspec: spec} = requirement) do
      %{requirement | matchspec: :ets.match_spec_compile(spec), compiled: true}
    end

    @doc false
    @spec match?(t, tuple) :: boolean
    def match?(%__MODULE__{matchspec: spec, compiled: true}, matchable_pattern) do
      matches = :ets.match_spec_run([matchable_pattern], spec)
      matches != []
    end

    def match?(%__MODULE__{matchspec: spec, compiled: false}, matchable_pattern) do
      {:ok, result} = :ets.test_ms(matchable_pattern, spec)
      result != false
    end
  end

  defmodule InvalidRequirementError do
