Qqwy / elixir-type_check

TypeCheck: Fast and flexible runtime type-checking for your Elixir projects.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Unexpected behaviour when defining multiple specs for a function

lbueso opened this issue · comments

commented
defmodule A do
  use TypeCheck

  @spec! f(integer()) :: integer()
  @spec! f(boolean()) :: boolean()
  def f(x), do: x
end

With this function definition of f I would expect TypeCheck to allow calling f with integers and booleans, but the current behaviour is:

iex(1)> A.f(1)
** (TypeCheck.TypeError) At lib/examples.ex:6:
    The call to `f/1` failed,
    because parameter no. 1 does not adhere to the spec `boolean()`.
    Rather, its value is: `1`.
    Details:
      The call `f(1)`
      does not adhere to spec `f(boolean()) :: boolean()`. Reason:
        parameter no. 1:
          `1` is not a boolean.
    (examples 0.1.0) lib/type_check/spec.ex:203: A."f (overridable 2)"/1
    (examples 0.1.0) lib/type_check/spec.ex:6: A.f/1
iex(1)> A.f(true)
** (TypeCheck.TypeError) At lib/examples.ex:6:
    The call to `f/1` failed,
    because parameter no. 1 does not adhere to the spec `boolean()`.
    Rather, its value is: `true`.
    Details:
      The call `f(true)`
      does not adhere to spec `f(boolean()) :: boolean()`. Reason:
        parameter no. 1:
          `true` is not an integer.
    (examples 0.1.0) lib/type_check/spec.ex:203: A.f/1

Thank you for submitting this bug report!

Defining multiple different specs for the same function is indeed allowed in Elixir/Erlang's own typespecs, but not currently in TypeCheck.
We do want to support this in the future, but it requires some work to get the implementation right.
Maybe the current limitation was surprising.
Do you think we should make it more visible in the documentation maybe?

For the time being, I recommend writing down a single spec in the format

@spec! f(integer()) :: integer() | boolean()
commented

Making it more visible in the documentation will definetely be very useful while this is not implemented.

Maybe TypeCheck could also throw a compilation warning when it finds more than one spec for a function. This will be very useful for the user, because the current behaviour doesn't allow the user to correctly invoke the function with multiple specs.