Consider the following code:

defmodule Foo do
  @typep foo :: integer
  @type bar :: foo

  @typep re :: integer
  @type mi :: float | re
  @type la :: mi | nil

  @spec baz(integer) :: foo
  def baz(bat), do: bat
end

This code presents several problems, and in my opinion should generate
at least two different compiler warnings, or the semantic of typep
should be changed slightly.

1) When referencing Foo.bar in @specs externally, Dialyzer will
complain (correctly) that it cannot find Foo.foo, since that is not in
the namespace of the code using Foo.bar. This puts Foo.foo into a
pseudo-private state, where other code can see it via Foo.bar but
never actually use Foo.bar for typespecs because it references
Foo.foo.

Proposed warning: Cannot reference @typep in @type.

2) Though a more general case of 1, one should not be able to
indirectly reference a @typep via @type, as in the case of Foo.la
referencing Foo.re. I call this a shadowed @typep, but
have no particular claims to this name being optimal. Feel free to
change.

Proposed warning: Cannot reference shadowed @typep in @type.

3) Foo.bat should not, as a def, be able to reference a @typep in its
@spec. Supposing this were in an @callback, for example, there would
be no way to have an @spec in the implementation for the @behaviour
that would actually work, for similar reasons as above, since you
could never reference Foo.foo in a module besides Foo.

Proposed warning: Cannot reference @typep in @spec for def.

However, one could argue that a simple change in the semantic of
@typep would alleviate all of these issues. If @typep had a sort of
unfolding behavior, where it was simply a shorthand for types locally,
that eventually become their longer forms. So for example someone
referencing Foo.la would see integer | float | nil. I do not
personally like this, it seems rather counterintuitive to me, but I
can see an argument to be made for it.

As an example of how this was inconvenient for me recently, in Ecto
one can set up a module as a logger for Ecto.Repo queries.
Ecto.LogEntry.t is defined https://hexdocs.pm/ecto/Ecto.LogEntry.html#t:t/0
and prior to 
https://github.com/elixir-lang/elixir/commit/240520ce5a8cfaf0ed1aa7c3672499d5b2f97910
would generate a warning when running dialyzer of:

Unknown types:
  'Elixir.IO.ANSI':ansicode/0

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elixir-lang-core+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/1463dbf4-e96c-4d76-922e-ffaa54347152%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to