         nil
     end
 
-    contains_any = L.keyfind(Any, 1, conversions) != false
-    { conversions, fallback, contains_any }
+    # If any is not in the list and we don't implement all
+    # protocols, we need to handle nil cases.
+    returns_nil = L.keyfind(Any, 1, conversions) == false and length(conversions) < 10
+    { conversions, fallback, returns_nil }
   end
 
   ## Helpers


  # Defines meta information about the protocol and internal callbacks.
  @doc false
  def meta(functions, conversions, fallback, any, env) do
    contents = quote do
      unless Kernel.Typespec.defines_type?(__MODULE__, :t, 0) do
        @type t :: unquote(generate_type(conversions, any))
      end

      def __protocol__(:name),      do: __MODULE__
      def __protocol__(:functions), do: unquote(:lists.sort(functions))

      def __impl_for__(arg) do
        case __raw_impl__(arg) do
          __MODULE__.Record ->
            target = Module.concat(__MODULE__, :erlang.element(1, arg))
            try do
              target.__impl__
              target
            catch
              :error, :undef, [[{ ^target, :__impl__, [], _ }|_]|_] ->
                unquote(fallback)
            end
          other ->
            other
        end
      end

      def __impl_for__!(arg) do
        if module = __impl_for__(arg) do
          module
        else
          raise Protocol.UndefinedError, protocol: __MODULE__, structure: arg
        end
      end
    end

    Module.eval_quoted env, contents
  end

  # Returns the default conversions according to the given

defmodule Protocol.DSL do
  @moduledoc false

  # We need to use :lists because Enum is not available yet
  require :lists, as: L

  def args_and_body(module, name, arity) do
    # Generate arguments according the arity. The arguments
    # are named xa, xb and so forth. We cannot use string
