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

Inability to import shared types upgrading from 0.4 to 0.5

baldwindavid opened this issue · comments

In moving from 0.4 to 0.5 (and up) it seems that I can no longer import shared types. Example:

defmodule Typetest.MyTypes do
  use TypeCheck

  @type! a_name :: binary()
end
defmodule Typetest do
  use TypeCheck
  import Typetest.MyTypes

  @spec! hello(a_name()) :: binary()
  def hello(name) do
    "Hello, #{name}"
  end
end

This works in 0.4, but the following error happens in 0.5 and up...

== Compilation error in file lib/typetest.ex ==                                                                                                                                                                  
  9 ** (CompileError) lib/typetest.ex:1: type a_name/0 undefined (no such type in Typetest)                                                                                                                          
  8     (elixir 1.12.2) lib/kernel/typespec.ex:925: Kernel.Typespec.compile_error/2                                                                                                                                  
  7     (stdlib 3.15.2) lists.erl:1358: :lists.mapfoldl/3                                                                                                                                                            
  6     (elixir 1.12.2) lib/kernel/typespec.ex:977: Kernel.Typespec.fn_args/5                                                                                                                                        
  5     (elixir 1.12.2) lib/kernel/typespec.ex:963: Kernel.Typespec.fn_args/6                                                                                                                                        
  4     (elixir 1.12.2) lib/kernel/typespec.ex:390: Kernel.Typespec.translate_spec/8                                                                                                                                 
  3     (stdlib 3.15.2) lists.erl:1358: :lists.mapfoldl/3                                                                                                                                                            
  2     (elixir 1.12.2) lib/kernel/typespec.ex:236: Kernel.Typespec.translate_typespecs_for_module/2

If I add that same @type directly within the file while still importing Types, the resulting error is clear that the shared one is imported...

defmodule Typetest do
  use TypeCheck
  import Typetest.MyTypes

  @type! a_name :: binary()

  @spec! hello(a_name()) :: binary()
  def hello(name) do
    "Hello, #{name}"
  end
end
  6 == Compilation error in file lib/typetest.ex ==                                                                                                                                                                  
  5 ** (CompileError) lib/typetest.ex:7: function a_name/0 imported from both TypeCheck.Internals.UserTypes.Typetest and Typetest.MyTypes, call is ambiguous                                                         
  4     (type_check 0.5.0) expanding macro: TypeCheck.Macros.__before_compile__/1                                                                                                                                    
  3     lib/typetest.ex:1: Typetest (module)                                                                                                                                                                         
  2     (elixir 1.12.2) lib/kernel/parallel_compiler.ex:319: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/7  

Is there a different method in order to share types via imports now? I'd rather not alias some very commonly used types.

Elixir does not support importing types between modules.
(This is the reason for the first error you received, the type a_name/0 undefined (no such type in Typetest))

That this worked in versions of TypeCheck older than 0.5.0 was caused by an oversight, where it did not correctly add a @spec for all @spec!s.

I see the following solutions:

  1. While importing types is not possible, aliasing a module is. So alias Typetest.MyTypes, as: T and then using T.a_name() might be a clean solution to your problem.
  2. If you really want to use the types as if they were local, you will need to
  • either redefine them without importing the other module. With some metaprogramming, this could become as concise as use Typetest.MyTypes.
  • Or add @autogen_typespec false to all types/specs which use the type-functions which have been added to the local scope by the import Typetest.MyTypes statement.

I'm pretty sure that (1) is the cleaner solution.

Yeah, I guess I felt like I needed this ability to import previously because of literals missing from https://hexdocs.pm/elixir/1.12/typespecs.html

For example, I had my own keyword() type for awhile until it was added to the library. Now that most of that page (I think) is in the library that really shouldn't be necessary.

Any truly custom types that wouldn't be in regular typespecs should really be aliased anyway, so I guess this isn't a problem.