 
   test "@type with keywords" do
     module = test_module do
-      @type mytype :: [first: integer, step: integer, last: integer]
-    end
-
-    assert [type: {:mytype, {:type, _, :list, [
+      @type my_type :: [first: integer, step: integer, last: integer]
+    end
+
+    assert [type: {:my_type, {:type, _, :list, [
       {:type, _, :union, [
         {:type, _, :tuple, [{:atom, _, :first}, {:type, _, :integer, []}]},
         {:type, _, :tuple, [{:atom, _, :step}, {:type, _, :integer, []}]},


  test "@type with an atom" do
    module = test_module do
      @type mytype :: :atom
    end

    assert [type: {:mytype, {:atom, _, :atom}, []}] =
           types(module)
  end

  test "@type with an atom alias" do
    module = test_module do
      @type mytype :: Atom
    end

    assert [type: {:mytype, {:atom, _, Atom}, []}] =
           types(module)
  end



  test "@spec(spec)" do
    module = test_module do
      def my_fun1(x), do: x
      def my_fun2(), do: :ok
      def my_fun3(x, y), do: {x, y}
      def my_fun4(x), do: x
      @spec my_fun1(integer) :: integer
      @spec my_fun2() :: integer
      @spec my_fun3(integer, integer) :: {integer, integer}
      @spec my_fun4(x :: integer) :: integer
    end

    assert [{{:my_fun1, 1}, [{:type, _, :fun, [{:type, _, :product, [{:type, _, :integer, []}]}, {:type, _, :integer, []}]}]},
            {{:my_fun2, 0}, [{:type, _, :fun, [{:type, _, :product, []}, {:type, _, :integer, []}]}]},
            {{:my_fun3, 2}, [{:type, _, :fun, [{:type, _, :product, [{:type, _, :integer, []}, {:type, _, :integer, []}]}, {:type, _, :tuple, [{:type, _, :integer, []}, {:type, _, :integer, []}]}]}]},
            {{:my_fun4, 1}, [{:type, _, :fun, [{:type, _, :product, [{:ann_type, _, [{:var, _, :x}, {:type, _, :integer, []}]}]}, {:type, _, :integer, []}]}]}] =
           specs(module)
  end

  test "@spec(spec) for unreachable private function" do
    # Run it inside capture_io/2 so that the "my_fun/1 is unused"
    # warning doesn't get printed among the ExUnit test results.
    output = ExUnit.CaptureIO.capture_io :stderr, fn ->
      module = test_module do
        defp my_fun(x), do: x
        @spec my_fun(integer) :: integer
      end

      assert [] == specs(module)
    end

    assert output =~ "function my_fun/1 is unused"
  end

  test "@spec(spec) with guards" do
    module = test_module do
      def my_fun1(x), do: x
      @spec my_fun1(x) :: boolean when [x: integer]

      def my_fun2(x), do: x
      @spec my_fun2(x) :: x when [x: var]

      def my_fun3(_x, y), do: y
      @spec my_fun3(x, y) :: y when [y: x, x: var]
    end

    assert [{{:my_fun1, 1}, [{:type, _, :bounded_fun, [{:type, _, :fun, [{:type, _, :product, [{:var, _, :x}]}, {:type, _, :boolean, []}]}, [{:type, _, :constraint, [{:atom, _, :is_subtype}, [{:var, _, :x}, {:type, _, :integer, []}]]}]]}]},
            {{:my_fun2, 1}, [{:type, _, :fun, [{:type, _, :product, [{:var, _, :x}]}, {:var, _, :x}]}]},
            {{:my_fun3, 2}, [{:type, _, :bounded_fun, [{:type, _, :fun, [{:type, _, :product, [{:var, _, :x}, {:var, _, :y}]}, {:var, _, :y}]}, [{:type, _, :constraint, [{:atom, _, :is_subtype}, [{:var, _, :y}, {:var, _, :x}]]}]]}]}] =
           specs(module)
  end

  test "@callback(callback)" do
    module = test_module do
      @callback my_fun(integer) :: integer
      @callback my_fun() :: integer
      @callback my_fun(integer, integer) :: {integer, integer}
    end

    assert [{{:my_fun, 0}, [{:type, _, :fun, [{:type, _, :product, []}, {:type, _, :integer, []}]}]},
            {{:my_fun, 1}, [{:type, _, :fun, [{:type, _, :product, [{:type, _, :integer, []}]}, {:type, _, :integer, []}]}]},
            {{:my_fun, 2}, [{:type, _, :fun, [{:type, _, :product, [{:type, _, :integer, []}, {:type, _, :integer, []}]}, {:type, _, :tuple, [{:type, _, :integer, []}, {:type, _, :integer, []}]}]}]}] =
           callbacks(module)
  end

  test "@spec + @callback" do
    module = test_module do
      def my_fun(x), do: x
      @spec my_fun(integer)   :: integer
      @spec my_fun(charlist) :: charlist
      @callback cb(integer)  :: integer
    end

    assert [{{:cb, 1}, [{:type, _, :fun, [{:type, _, :product, [{:type, _, :integer, []}]}, {:type, _, :integer, []}]}]}] =
           callbacks(module)

    assert [{{:my_fun, 1}, [
             {:type, _, :fun, [{:type, _, :product, [
               {:remote_type, _, [{:atom, _, :elixir}, {:atom, _, :charlist}, []]}]},
               {:remote_type, _, [{:atom, _, :elixir}, {:atom, _, :charlist}, []]}]},
