FunctionClauseError raised on return type annotation
nicholasjhenry opened this issue · comments
For example, the following type definition works:
@type greeting :: String.t()
@callback perform(Decimal.t()) :: greeting
but the following raises a FunctionCaluseError
exception:
@callback perform(Decimal.t()) :: greeting :: String.t()
Stacktrace:
** (FunctionClauseError) no function clause matching in Hammox.TypeEngine.match_type/2
The following arguments were given to Hammox.TypeEngine.match_type/2:
# 1
"hello"
# 2
{:ann_type, 7, [{:var, 7, :greeting}, {:remote_type, 7, [{:atom, 0, String}, {:atom, 0, :t}, []]}]}
Attempted function clauses (showing 10 out of 91):
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)
code: HammoxPlayground.Mock.perform(Decimal.new("0.992"))
stacktrace:
(hammox) lib/hammox/type_engine.ex:6: Hammox.TypeEngine.match_type/2
(hammox) lib/hammox.ex:312: Hammox.match_return_value/2
(hammox) lib/hammox.ex:280: Hammox.match_call/3
(hammox) lib/hammox.ex:264: anonymous fn/4 in Hammox.check_call/3
(elixir) lib/enum.ex:3325: Enumerable.List.reduce/3
(elixir) lib/enum.ex:1998: Enum.reduce_while/3
(hammox) lib/hammox.ex:263: Hammox.check_call/3
(hammox) lib/hammox.ex:256: Hammox.protected_code/3
test/hammox_playground_test.exs:13: (test)
To clarify, this appears to be only an issue for inline definitions for return types.
Wow, didn't even know this was valid syntax!
I believe the snippets you posted are not equivalent - @type
defines a named type accessible throughout the module and from outside, while the "inline syntax" seems to be annotation just like for arguments. Example: arg_name
in foo(arg_name :: String.t()) :: String.t()
.
Updated the issue title accordingly.