   defp guard_to_constraints(guard, vars, meta, caller) do
     line = line(meta)
 
-    foldl_fun = fn
-      {_name, {:var, _, context}}, acc when is_atom(context) ->
-        acc
-
-      {name, type}, acc ->
+    Enum.flat_map(guard, fn
+      {_name, {:var, _, context}} when is_atom(context) ->
+        []
+
+      {name, type} ->
         constraint = [
           {:atom, line, :is_subtype},
           [{:var, line, name}, typespec(type, vars, caller)]
         ]
 
-        type = {:type, line, :constraint, constraint}
-        [type | acc]
-    end
-
-    :lists.reverse(:lists.foldl(foldl_fun, [], guard))
+        [{:type, line, :constraint, constraint}]
+    end)
   end
 
   ## To AST conversion

  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)
    {:type, line(meta), :map, fields}
  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)

