@@ -33,9 +33,8 @@ defmodule Module.Types do
3333  @ no_infer  [ __protocol__:  1 ,  behaviour_info:  1 ] 
3434
3535  @ doc  false 
36-   def  infer ( module ,  file ,  defs ,  private ,  defmacrop ,  env )  do 
36+   def  infer ( module ,  file ,  defs ,  private ,  used_private ,  env )  do 
3737    infer_signatures?  =  :elixir_config . get ( :infer_signatures ) 
38-     defmacrop  =  Map . from_keys ( defmacrop ,  [ ] ) 
3938
4039    finder  = 
4140      fn  fun_arity  -> 
@@ -63,9 +62,9 @@ defmodule Module.Types do
6362
6463    stack  =  stack ( :infer ,  file ,  module ,  { :__info__ ,  1 } ,  :all ,  env ,  handler ) 
6564
66-     { types ,  % { local_sigs:  local_sigs }  =  context }  = 
65+     { types ,  % { local_sigs:  reachable_sigs }  =  context }  = 
6766      for  { fun_arity ,  kind ,  meta ,  _clauses }  =  def  <-  defs , 
68-           kind  in  [ :def ,  :defmacro ]   or   ( kind   ==   :defmacrop   and   is_map_key ( defmacrop ,   fun_arity ) ) , 
67+           kind  in  [ :def ,  :defmacro ] , 
6968          reduce:  { [ ] ,  context ( ) }  do 
7069        { types ,  context }  -> 
7170          finder  =  fn  _  ->  { infer_mode ( kind ,  infer_signatures? ) ,  def }  end 
@@ -78,20 +77,32 @@ defmodule Module.Types do
7877          end 
7978      end 
8079
81-     for   { fun_arity ,   kind ,   meta ,   _clauses }   =   def   <-   defs , 
82-          kind   in   [ :defp ,   :defmacrop ] , 
83-          reduce:  context   do 
84-       context   -> 
85-         finder   =   fn   _   ->   { :traversal ,   def }   end 
86-         { _kind ,  _inferred ,  context }  =  local_handler ( meta ,  fun_arity ,  stack ,  context ,  finder ) 
87-         context 
88-     end 
80+     # Now traverse all used privates to find any other private that have been used by them. 
81+     context   = 
82+       % { local_sigs:  used_sigs }   = 
83+       for   fun_arity   <-   used_private ,   reduce:  context   do 
84+         context   -> 
85+            { _kind ,  _inferred ,  context }  =  local_handler ( [ ] ,  fun_arity ,  stack ,  context ,  finder ) 
86+            context 
87+        end 
8988
90-     unreachable  = 
91-       for  { fun_arity ,  _kind ,  _meta ,  _defaults }  =  info  <-  private , 
92-           warn_unused_def ( info ,  local_sigs ,  defmacrop ,  env ) , 
93-           not  is_map_key ( local_sigs ,  fun_arity ) , 
94-           do:  fun_arity 
89+     { unreachable ,  _context }  = 
90+       Enum . reduce ( private ,  { [ ] ,  context } ,  fn 
91+         { fun_arity ,  kind ,  _meta ,  _defaults }  =  info ,  { unreachable ,  context }  -> 
92+           warn_unused_def ( info ,  used_sigs ,  env ) 
93+ 
94+           # Find anything undefined within unused functions 
95+           { _kind ,  _inferred ,  context }  =  local_handler ( [ ] ,  fun_arity ,  stack ,  context ,  finder ) 
96+ 
97+           # defp is reachable if used, defmacrop only if directly invoked 
98+           private_sigs  =  if  kind  ==  :defp ,  do:  used_sigs ,  else:  reachable_sigs 
99+ 
100+           if  is_map_key ( private_sigs ,  fun_arity )  do 
101+             { unreachable ,  context } 
102+           else 
103+             { [ fun_arity  |  unreachable ] ,  context } 
104+           end 
105+       end ) 
95106
96107    { Map . new ( types ) ,  unreachable } 
97108  end 
@@ -106,25 +117,25 @@ defmodule Module.Types do
106117    :elixir_errors . module_error ( Helpers . with_span ( meta ,  fun ) ,  env ,  __MODULE__ ,  tuple ) 
107118  end 
108119
109-   defp  warn_unused_def ( { _fun_arity ,  _kind ,  false ,  _ } ,  _reachable ,   _used ,  _env )  do 
120+   defp  warn_unused_def ( { _fun_arity ,  _kind ,  false ,  _ } ,  _used ,  _env )  do 
110121    :ok 
111122  end 
112123
113-   defp  warn_unused_def ( { fun_arity ,  kind ,  meta ,  0 } ,  reachable ,   used ,  env )  do 
114-     case  is_map_key ( reachable ,   fun_arity )   or   is_map_key ( used ,  fun_arity )  do 
124+   defp  warn_unused_def ( { fun_arity ,  kind ,  meta ,  0 } ,  used ,  env )  do 
125+     case  is_map_key ( used ,  fun_arity )  do 
115126      true  ->  :ok 
116127      false  ->  :elixir_errors . file_warn ( meta ,  env ,  __MODULE__ ,  { :unused_def ,  fun_arity ,  kind } ) 
117128    end 
118129
119130    :ok 
120131  end 
121132
122-   defp  warn_unused_def ( { tuple ,  kind ,  meta ,  default } ,  reachable ,   used ,  env )  when  default  >  0  do 
133+   defp  warn_unused_def ( { tuple ,  kind ,  meta ,  default } ,  used ,  env )  when  default  >  0  do 
123134    { name ,  arity }  =  tuple 
124135    min  =  arity  -  default 
125136    max  =  arity 
126137
127-     case  min_reachable_default ( max ,  min ,  :none ,  name ,  reachable ,   used )  do 
138+     case  min_reachable_default ( max ,  min ,  :none ,  name ,  used )  do 
128139      :none  ->  :elixir_errors . file_warn ( meta ,  env ,  __MODULE__ ,  { :unused_def ,  tuple ,  kind } ) 
129140      ^ min  ->  :ok 
130141      ^ max  ->  :elixir_errors . file_warn ( meta ,  env ,  __MODULE__ ,  { :unused_args ,  tuple } ) 
@@ -134,16 +145,16 @@ defmodule Module.Types do
134145    :ok 
135146  end 
136147
137-   defp  min_reachable_default ( max ,  min ,  last ,  name ,  reachable ,   used )  when  max  >=  min  do 
148+   defp  min_reachable_default ( max ,  min ,  last ,  name ,  used )  when  max  >=  min  do 
138149    fun_arity  =  { name ,  max } 
139150
140-     case  is_map_key ( reachable ,   fun_arity )   or   is_map_key ( used ,  fun_arity )  do 
141-       true  ->  min_reachable_default ( max  -  1 ,  min ,  max ,  name ,  reachable ,   used ) 
142-       false  ->  min_reachable_default ( max  -  1 ,  min ,  last ,  name ,  reachable ,   used ) 
151+     case  is_map_key ( used ,  fun_arity )  do 
152+       true  ->  min_reachable_default ( max  -  1 ,  min ,  max ,  name ,  used ) 
153+       false  ->  min_reachable_default ( max  -  1 ,  min ,  last ,  name ,  used ) 
143154    end 
144155  end 
145156
146-   defp  min_reachable_default ( _max ,  _min ,  last ,  _name ,  _reachable ,   _used )  do 
157+   defp  min_reachable_default ( _max ,  _min ,  last ,  _name ,  _used )  do 
147158    last 
148159  end 
149160
0 commit comments