   end
 
   defp typespec({:%{}, meta, fields} = map, vars, caller) do
-    map_fun = fn
-      {k, v} when is_atom(k) ->
-        args = [typespec(k, vars, caller), typespec(v, vars, caller)]
-        {:type, line(meta), :map_field_exact, args}
-
-      {{:required, meta2, [k]}, v} ->
-        args = [typespec(k, vars, caller), typespec(v, vars, caller)]
-        {:type, line(meta2), :map_field_exact, args}
-
-      {{:optional, meta2, [k]}, v} ->
-        args = [typespec(k, vars, caller), typespec(v, vars, caller)]
-        {:type, line(meta2), :map_field_assoc, args}
-
-      {k, v} ->
-        # TODO: Warn on Elixir v1.8 (since v1.6 is the first version to drop support for 18 and
-        # older)
-        # warning =
-        #   "invalid map specification. %{foo => bar} is deprecated in favor of " <>
-        #   "%{required(foo) => bar} and %{optional(foo) => bar}."
-        # :elixir_errors.warn(caller.line, caller.file, warning)
-        args = [typespec(k, vars, caller), typespec(v, vars, caller)]
-        {:type, line(meta), :map_field_assoc, args}
-
-      {:|, _, [_, _]} ->
-        error =
-          "invalid map specification. When using the | operator in the map key, " <>
-            "make sure to wrap the key type in parentheses: #{Macro.to_string(map)}"
-
-        compile_error(caller, error)
-
-      _ ->
-        compile_error(caller, "invalid map specification: #{Macro.to_string(map)}")
-    end
-
-    fields = :lists.map(map_fun, fields)
+    fields =
+      Enum.map(fields, fn
+        {k, v} when is_atom(k) ->
+          args = [typespec(k, vars, caller), typespec(v, vars, caller)]
+          {:type, line(meta), :map_field_exact, args}
+
+        {{:required, meta2, [k]}, v} ->
+          args = [typespec(k, vars, caller), typespec(v, vars, caller)]
+          {:type, line(meta2), :map_field_exact, args}
+
+        {{:optional, meta2, [k]}, v} ->
+          args = [typespec(k, vars, caller), typespec(v, vars, caller)]
+          {:type, line(meta2), :map_field_assoc, args}
+
+        {k, v} ->
+          # TODO: Warn on Elixir v1.8 (since v1.6 is the first version to drop support for 18 and
+          # older)
+          # warning =
+          #   "invalid map specification. %{foo => bar} is deprecated in favor of " <>
+          #   "%{required(foo) => bar} and %{optional(foo) => bar}."
+          # :elixir_errors.warn(caller.line, caller.file, warning)
+          args = [typespec(k, vars, caller), typespec(v, vars, caller)]
+          {:type, line(meta), :map_field_assoc, args}
+
+        {:|, _, [_, _]} ->
+          error =
+            "invalid map specification. When using the | operator in the map key, " <>
+              "make sure to wrap the key type in parentheses: #{Macro.to_string(map)}"
+
+          compile_error(caller, error)
+
+        _ ->
+          compile_error(caller, "invalid map specification: #{Macro.to_string(map)}")
+      end)
+
     {:type, line(meta), :map, fields}
   end
 

  end

  defp typespec(list, vars, caller) when is_list(list) do
    [h | t] = :lists.reverse(list)

    foldl_fun = fn x, acc -> {:|, [], [validate_kw(x, list, caller), acc]} end
    union = :lists.foldl(foldl_fun, validate_kw(h, list, caller), t)
    typespec({:list, [], [union]}, vars, caller)
  end


    # as a compile time dependency because for records it actually is one.
    case Macro.expand({atom, [], [{atom, [], []}]}, caller) do
      keyword when is_list(keyword) ->
        types =
          Enum.map(keyword, fn {field, _} ->
            Keyword.get(fields, field, quote(do: term()))
          end)

        Enum.each(fields, fn {field, _} ->
          unless Keyword.has_key?(keyword, field) do
            compile_error(caller, "undefined field #{field} on record #{inspect(atom)}")
          end
        end)

        typespec({:{}, meta, [atom | types]}, vars, caller)

