eproxus / meck

A mocking library for Erlang
http://eproxus.github.io/meck
Apache License 2.0
811 stars 231 forks source link

meck:ret_spec() opaqueness violates documented usage patterns #212

Closed jesperes closed 4 years ago

jesperes commented 4 years ago

The type meck:ret_spec() is declared opaque, but its documentation also says:

%% Note that any Erlang term `X' is a valid `ret_spec()' equivalent to
%% `meck:val(X)'.

This is not compatible with how opaque types work, and will cause dialyzer errors when attempting to call e.g. meck:expect/4 like this:

meck:expect(foo, bar, 2, fun ?MODULE:run/2)

Dialyzer will complain that the code is attempting to pass something other than an opaque type as the 4th argument:

....: The call meck:expect(...) does not have an opaque term of type meck:ret_spec() as 4th argument

The only (compatible) way of fixing this is to change the ret_spec() type to

-type ret_spec() :: any().

Reproduction Steps

  1. Given this module:
    -module(foo).
    -export([main/0]).
    main() ->
    ok = meck:expect(foo, foo, 0, any_value).
  2. Run dialyzer
    dialyzer --plt ..../otp.plt  ./foo.erl .../meck.beam

Expected behavior

No dialyzer errors, since according to the documentation any_value is a valid ret_spec().

Observed behavior

foo.erl:4: The call meck:expect
         ('foo',
          'foo',
          0,
          'any_value') does not have an opaque term of type 
          meck:ret_spec() as 4th argument

Versions

eproxus commented 4 years ago

Thanks! I thin any() is the correct type here. Not sure why opaque() is there, perhaps Dialyzer got smarter or I simply just misunderstood the types. Care to make a PR? 😉

jesperes commented 4 years ago

I'll fix a PR for it.

jesperes commented 4 years ago

https://github.com/eproxus/meck/pull/213

eproxus commented 4 years ago

Fixed by #213.