 
       {:available, kind, module} ->
         available =
-          for {^kind, _, ref, _, ^module, _defining, _deadlock} <- waiting,
-              do: {ref, :found}
+          for {pid, {^kind, _, _, ^module, _defining, _deadlock}} <- waiting,
+              do: {pid, :found}
 
         result = Map.put(result, {kind, module}, true)
         spawn_workers(available ++ queue, spawned, waiting, files, result, warnings, state)

         warnings,
         %{schedulers: schedulers} = state
       )
       when map_size(spawned) - length(waiting) >= schedulers do
    wait_for_messages(queue, spawned, waiting, files, result, warnings, state)
  end

  # Release waiting processes
  defp spawn_workers([{ref, found} | t], spawned, waiting, files, result, warnings, state) do
    {files, waiting} =
      case List.keytake(waiting, ref, 2) do
        {{_kind, pid, ^ref, file_pid, _on, _defining, _deadlock}, waiting} ->
          send(pid, {ref, found})
          {update_timing(files, file_pid, :waiting), waiting}

        nil ->
          # In case the waiting process died (for example, it was an async process),
          # it will no longer be on the list. So we need to take it into account here.
          {files, waiting}

        {:current_stacktrace, stacktrace} = Process.info(pid, :current_stacktrace)
        Process.exit(pid, :kill)

        {kind, _, _, on, _, _} = Map.fetch!(waiting, pid)
        description = "deadlocked waiting on #{kind} #{inspect(on)}"
        error = CompileError.exception(description: description, file: nil, line: nil)
        print_error(file, :error, error, stacktrace)
