Question about behaviours and expected return values

I’ve been using behaviours and explicit contracts to test when using external libraries. One thing I’ve noticed is that callbacks don’t seem to care whether or not the implementations return value matches that of the callback. See the code below. It compiles without any warnings, when I’d expect it to complain about the implementation not returning a matching value. I ran dialyzer in the hopes that it would throw a warning, but unless I’m not seeing it, dialyzer seems to be okay with this as well. This makes me a little more cautious about using behaviours if the implementing functions can simply return anything. Am I thinking about this correctly?

defmodule MyBehaviour do
  @callback list_something(my_var :: binary) :: :ok
end

defmodule MyLister do
  @behaviour MyBehaviour

  def list_something(_my_var) do
    :not_ok
  end
end

Have you seen Does dialyzer check behaviours and callbacks?

It seems

  • Direct calls to MyLister.list_something don’t to have to honour the constraints of the behaviour.
  • When list_something is called in the context of the behaviour Dialyzer may not be able to infer that it’s MyLister's function in particular.
  • If static analysis can infer that MyLister.list_something is being called in the context of the behaviour then you should be seeing an "The inferred return type ... has nothing in common with ..." error.
1 Like

I had not seen that post. Thanks for the link. That definitely answers some questions.

1 Like