@@ -472,8 +472,6 @@ defmodule Module.Types.Apply do
472472  Returns the type of a remote capture. 
473473  """ 
474474  def  remote_capture ( modules ,  fun ,  arity ,  meta ,  stack ,  context )  do 
475-     # TODO: Do we check when the union of functions is invalid? 
476-     # TODO: Deal with :infer types 
477475    if  stack . mode  ==  :traversal  or  modules  ==  [ ]  do 
478476      { dynamic ( fun ( arity ) ) ,  context } 
479477    else 
@@ -483,6 +481,9 @@ defmodule Module.Types.Apply do
483481            { { :strong ,  _ ,  clauses } ,  context }  -> 
484482              { union ( type ,  fun_from_non_overlapping_clauses ( clauses ) ) ,  fallback? ,  context } 
485483
484+             { { :infer ,  _ ,  clauses } ,  context }  when  length ( clauses )  <=  @ max_clauses  -> 
485+               { union ( type ,  fun_from_overlapping_clauses ( clauses ) ) ,  fallback? ,  context } 
486+ 
486487            { _ ,  context }  -> 
487488              { type ,  true ,  context } 
488489          end 
@@ -610,6 +611,19 @@ defmodule Module.Types.Apply do
610611    not  Enum . any? ( stack . no_warn_undefined ,  & ( & 1  ==  module  or  & 1  ==  { module ,  fun ,  arity } ) ) 
611612  end 
612613
614+   ## Funs 
615+ 
616+   def  fun_apply ( fun_type ,  args_types ,  call ,  stack ,  context )  do 
617+     case  fun_apply ( fun_type ,  args_types )  do 
618+       { :ok ,  res }  -> 
619+         { res ,  context } 
620+ 
621+       reason  -> 
622+         error  =  { { :badapply ,  reason } ,  args_types ,  fun_type ,  call ,  context } 
623+         { error_type ( ) ,  error ( __MODULE__ ,  error ,  elem ( call ,  1 ) ,  stack ,  context ) } 
624+     end 
625+   end 
626+ 
613627  ## Local 
614628
615629  def  local_domain ( fun ,  args ,  expected ,  meta ,  stack ,  context )  do 
@@ -682,13 +696,25 @@ defmodule Module.Types.Apply do
682696      { _kind ,  _info ,  context }  when  stack . mode  ==  :traversal  -> 
683697        { dynamic ( fun ( arity ) ) ,  context } 
684698
685-       { kind ,  _info ,  context }  -> 
686-         if  stack . mode  !=  :infer  and  kind  ==  :defp  do 
687-           # Mark all clauses as used, as the function is being exported. 
688-           { dynamic ( fun ( arity ) ) ,  put_in ( context . local_used [ fun_arity ] ,  [ ] ) } 
689-         else 
690-           { dynamic ( fun ( arity ) ) ,  context } 
691-         end 
699+       { kind ,  info ,  context }  -> 
700+         result  = 
701+           case  info  do 
702+             { :infer ,  _ ,  clauses }  when  length ( clauses )  <=  @ max_clauses  -> 
703+               fun_from_overlapping_clauses ( clauses ) 
704+ 
705+             _  -> 
706+               dynamic ( fun ( arity ) ) 
707+           end 
708+ 
709+         context  = 
710+           if  stack . mode  !=  :infer  and  kind  ==  :defp  do 
711+             # Mark all clauses as used, as the function is being exported. 
712+             put_in ( context . local_used [ fun_arity ] ,  [ ] ) 
713+           else 
714+             context 
715+           end 
716+ 
717+         { result ,  context } 
692718    end 
693719  end 
694720
@@ -805,6 +831,78 @@ defmodule Module.Types.Apply do
805831
806832  ## Diagnostics 
807833
834+   def  format_diagnostic ( { { :badapply ,  reason } ,  args_types ,  fun_type ,  expr ,  context } )  do 
835+     traces  = 
836+       case  reason  do 
837+         # Include arguments in traces in case of badarg 
838+         { :badarg ,  _ }  ->  collect_traces ( expr ,  context ) 
839+         # Otherwise just the fun 
840+         _  ->  collect_traces ( elem ( expr ,  0 ) ,  context ) 
841+       end 
842+ 
843+     message  = 
844+       case  reason  do 
845+         { :badarg ,  domain }  -> 
846+           """ 
847+           incompatible types given on function application: 
848+ 
849+               #{ expr_to_string ( expr )  |>  indent ( 4 ) }  
850+ 
851+           given types: 
852+ 
853+               #{ args_to_quoted_string ( args_types ,  domain ,  & Function . identity / 1 )  |>  indent ( 4 ) }  
854+ 
855+           but function has type: 
856+ 
857+               #{ to_quoted_string ( fun_type )  |>  indent ( 4 ) }  
858+           """ 
859+ 
860+         :badarg  -> 
861+           """ 
862+           expected a #{ length ( args_types ) }  -arity function on call: 
863+ 
864+               #{ expr_to_string ( expr )  |>  indent ( 4 ) }  
865+ 
866+           but got type: 
867+ 
868+               #{ to_quoted_string ( fun_type )  |>  indent ( 4 ) }  
869+           """ 
870+ 
871+         { :badarity ,  arities }  -> 
872+           info  = 
873+             case  arities  do 
874+               [ arity ]  ->  "function with arity #{ arity }  " 
875+               _  ->  "function with arities #{ Enum . join ( arities ,  "," ) }  " 
876+             end 
877+ 
878+           """ 
879+           expected a #{ length ( args_types ) }  -arity function on call: 
880+ 
881+               #{ expr_to_string ( expr )  |>  indent ( 4 ) }  
882+ 
883+           but got #{ info }  : 
884+ 
885+               #{ to_quoted_string ( fun_type )  |>  indent ( 4 ) }  
886+           """ 
887+ 
888+         :badfun  -> 
889+           """ 
890+           expected a #{ length ( args_types ) }  -arity function on call: 
891+ 
892+               #{ expr_to_string ( expr )  |>  indent ( 4 ) }  
893+ 
894+           but got type: 
895+ 
896+               #{ to_quoted_string ( fun_type )  |>  indent ( 4 ) }  
897+           """ 
898+       end 
899+ 
900+     % { 
901+       details:  % { typing_traces:  traces } , 
902+       message:  IO . iodata_to_binary ( [ message ,  format_traces ( traces ) ] ) 
903+     } 
904+   end 
905+ 
808906  def  format_diagnostic ( { :badlocal ,  { _ ,  domain ,  clauses } ,  args_types ,  expr ,  context } )  do 
809907    domain  =  domain ( domain ,  clauses ) 
810908    traces  =  collect_traces ( expr ,  context ) 
0 commit comments