msz/hammox

Exception thrown with Decimal.t

nicholasjhenry opened this issue · 4 comments

Could you please tell me if hammox has support for custom types? For example:

defmodule MyType do
  defstruct [:value]

  @type t :: %__MODULE__{
    value: number()
   }
end

Looking through the source code and the following error, I am assuming it doesn't currently:

     The following arguments were given to Hammox.TypeEngine.match_type/2:

         # 1
         1000

         # 2
         {:op, 93, :-, {:integer, 93, 1}}

     Attempted function clauses (showing 10 out of 89):

         def match_type(value, {:type, _, :union, union_types} = union) when is_list(union_types)
         def match_type(_value, {:type, _, :any, []})
         def match_type(value, {:type, _, :none, []} = type)
         def match_type(value, {:type, _, :atom, []}) when is_atom(value)
         def match_type(value, {:type, _, :atom, []} = type)
         def match_type(value, {:type, _, :map, :any}) when is_map(value)
         def match_type(value, {:type, _, :pid, []}) when is_pid(value)
         def match_type(value, {:type, _, :pid, []} = type)
         def match_type(value, {:type, _, :port, []}) when is_port(value)
         def match_type(value, {:type, _, :port, []} = type)

     stacktrace:
       (hammox) lib/hammox/type_engine.ex:6: Hammox.TypeEngine.match_type/2
       (hammox) lib/hammox/type_engine.ex:9: anonymous fn/3 in Hammox.TypeEngine.match_type/2
       (elixir) lib/enum.ex:3325: Enumerable.List.reduce/3
       (elixir) lib/enum.ex:1998: Enum.reduce_while/3
       (hammox) lib/hammox/type_engine.ex:8: Hammox.TypeEngine.match_type/2
       (hammox) lib/hammox/type_engine.ex:364: anonymous fn/3 in Hammox.TypeEngine.match_type/2
       (elixir) lib/enum.ex:1340: anonymous fn/3 in Enum.map/2
       (stdlib) maps.erl:232: :maps.fold_1/3
       (elixir) lib/enum.ex:1964: Enum.map/2
       (hammox) lib/hammox/type_engine.ex:363: anonymous fn/2 in Hammox.TypeEngine.match_type/2
       (elixir) lib/enum.ex:3358: Enumerable.Map.reduce_list/3
       (elixir) lib/enum.ex:1998: Enum.reduce_while/3
       (hammox) lib/hammox/type_engine.ex:361: Hammox.TypeEngine.match_type/2
       (hammox) lib/hammox/type_engine.ex:364: anonymous fn/3 in Hammox.TypeEngine.match_type/2
       (elixir) lib/enum.ex:1340: anonymous fn/3 in Enum.map/2
       (stdlib) maps.erl:232: :maps.fold_1/3
       (elixir) lib/enum.ex:1964: Enum.map/2
       (hammox) lib/hammox/type_engine.ex:363: anonymous fn/2 in Hammox.TypeEngine.match_type/2
       (elixir) lib/enum.ex:3358: Enumerable.Map.reduce_list/3
       (elixir) lib/enum.ex:1998: Enum.reduce_while/3

Thank you for your help!

msz commented

Hammox has support for custom/remote types, see here:

defmodule Hammox.Test.Struct do
defstruct [:foo]
@type my_list() :: list()

@callback foo_remote_type :: Hammox.Test.Struct.my_list()

hammox/test/hammox_test.exs

Lines 954 to 962 in f172d5b

describe "remote type" do
test "fail" do
assert_fail(:foo_remote_type, :foo)
end
test "pass" do
assert_pass(:foo_remote_type, [1])
end
end

However the error you posted is definitely puzzling. I am not sure how this piece of AST would get into the typespec tree, and if it does then Hammox definitely should not blow up without explanation when encountering it.

Could you post the typespec for the function on which the Hammox check is blowing up, along with any custom types, or ideally a small repo reproducing the problem?

Thank you for the quick reply, @msz. I have located the problem in my application, and are working on trying to reproduce it in a small application/repo to review. I haven't been able to yet reproduce it, but I'll keep at it. Thanks again for your help.

@msz I've managed to isolate the issue, it appears this is an issue with Decimal.t:

https://github.com/nicholasjhenry/hammox_playground

msz commented

Brilliant, thank you! Looking at it briefly, it looks like the issue is with -1 in the typespec. Will work on a fix for this soon.