   # Finally compile the module and emit its bytecode.
   defp compile(protocol, code, {compile_info, docs}) do
     opts = Keyword.take(compile_info, [:source])
-    opts = if Code.compiler_options[:debug_info], do: [:debug_info | opts], else: opts
+    opts = if Code.compiler_options()[:debug_info], do: [:debug_info | opts], else: opts
     {:ok, ^protocol, binary, _warnings} = :compile.forms(code, [:return | opts])
-    {:ok,
+
+    {
+      :ok,
       case docs do
         :missing_chunk -> binary
         _ -> :elixir_erl.add_beam_chunks(binary, [{"ExDc", docs}])
-      end}
+      end
+    }
   end
 
   ## Definition callbacks
 
   @doc false
-  def __protocol__(name, [do: block]) do
+  def __protocol__(name, do: block) do
     quote do
       defmodule unquote(name) do
         # We don't allow function definition inside protocols
-        import Kernel, except: [
-          defmacrop: 1, defmacrop: 2, defmacro: 1, defmacro: 2,
-          defp: 1, defp: 2, def: 1, def: 2
-        ]
+        import Kernel,
+          except: [
+            defmacrop: 1,
+            defmacrop: 2,
+            defmacro: 1,
+            defmacro: 2,
+            defp: 1,
+            defp: 2,
+            def: 1,
+            def: 2
+          ]
 
         # Import the new dsl that holds the new def
         import Protocol, only: [def: 1]

      true

  """
  @spec extract_protocols([charlist | String.t]) :: [atom]
  def extract_protocols(paths) do
    extract_matching_by_attribute paths, 'Elixir.',
      fn module, attributes ->
        case attributes[:protocol] do
          [fallback_to_any: _] -> module
          _ -> nil
        end
      end
  end

  @doc """

  def __derive__(derives, for, %Macro.Env{} = env) when is_atom(for) do
    struct =
      if for == env.module do
        Module.get_attribute(for, :struct) || raise "struct is not defined for #{inspect(for)}"
      else
        for.__struct__
      end

    :lists.foreach(
      fn
        proto when is_atom(proto) ->
          derive(proto, for, struct, [], env)

        {proto, opts} when is_atom(proto) ->
          derive(proto, for, struct, opts, env)
      end,
      :lists.flatten(derives)
    )

    :ok
  end

  defp derive(protocol, for, struct, opts, env) do
    extra = ", cannot derive #{inspect(protocol)} for #{inspect(for)}"
    assert_protocol!(protocol, extra)
    __ensure_defimpl__(protocol, for, env)
    assert_impl!(protocol, Any, extra)

    # Clean up variables from eval context
    env = %{env | vars: [], export_vars: nil}
    args = [for, struct, opts]
    impl = Module.concat(protocol, Any)

    :elixir_module.expand_callback(env.line, impl, :__deriving__, args, env, fn mod, fun, args ->
      if function_exported?(mod, fun, length(args)) do
        apply(mod, fun, args)
      else
        Module.create(
          Module.concat(protocol, for),
          quote do
            Module.register_attribute(__MODULE__, :protocol_impl, persist: true)
            @protocol_impl [protocol: unquote(protocol), for: unquote(for)]

