Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected behaviour when defining multiple specs for a function #145

Open
lbueso opened this issue Sep 27, 2022 · 2 comments
Open

Unexpected behaviour when defining multiple specs for a function #145

lbueso opened this issue Sep 27, 2022 · 2 comments
Labels
documentation Improvements or additions to documentation enhancement New feature or request

Comments

@lbueso
Copy link

lbueso commented Sep 27, 2022

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
@Qqwy
Copy link
Owner

Qqwy commented Sep 27, 2022

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()

@Qqwy Qqwy added the enhancement New feature or request label Sep 27, 2022
@Qqwy Qqwy added this to the Some future version milestone Sep 27, 2022
@lbueso
Copy link
Author

lbueso commented Sep 29, 2022

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.

@Qqwy Qqwy added the documentation Improvements or additions to documentation label Oct 12, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants