@@ -429,6 +429,26 @@ defmodule Module.Types.Apply do
429429    end 
430430  end 
431431
432+   @ doc  """ 
433+   Returns the type of a remote capture. 
434+   """ 
435+   def  remote_capture ( modules ,  fun ,  arity ,  meta ,  stack ,  context )  do 
436+     # TODO: We cannot return the unions of functions. Do we forbid this? 
437+     # Do we check it is always the same return type? Do we simply say it is a function? 
438+     if  stack . mode  ==  :traversal  do 
439+       { dynamic ( fun ( ) ) ,  context } 
440+     else 
441+       context  = 
442+         Enum . reduce ( 
443+           modules , 
444+           context , 
445+           & ( signature ( & 1 ,  fun ,  arity ,  meta ,  stack ,  & 2 )  |>  elem ( 1 ) ) 
446+         ) 
447+ 
448+       { dynamic ( fun ( ) ) ,  context } 
449+     end 
450+   end 
451+ 
432452  @ doc  """ 
433453  Gets a mfa signature. 
434454
@@ -461,25 +481,30 @@ defmodule Module.Types.Apply do
461481    { signature ( :module_info ,  arity ) ,  context } 
462482  end 
463483
464-   defp  export ( _module ,  _fun ,  _arity ,  _meta ,  % { cache:  % Macro.Env { } } ,  context )  do 
465-     { :none ,  context } 
466-   end 
484+   defp  export ( module ,  fun ,  arity ,  meta ,  % { cache:  cache }  =  stack ,  context )  do 
485+     cond  do 
486+       cache  ==  nil  or  stack . mode  ==  :traversal  -> 
487+         { :none ,  context } 
467488
468-   defp  export ( module ,  fun ,  arity ,  meta ,  stack ,  context )  do 
469-     case  ParallelChecker . fetch_export ( stack . cache ,  module ,  fun ,  arity )  do 
470-       { :ok ,  mode ,  reason ,  info }  -> 
471-         info  =  if  info  ==  :none ,  do:  signature ( fun ,  arity ) ,  else:  info 
472-         { info ,  check_deprecated ( mode ,  module ,  fun ,  arity ,  reason ,  meta ,  stack ,  context ) } 
489+       stack . mode  ==  :infer  and  not  builtin_module? ( module )  -> 
490+         { :none ,  context } 
473491
474-       { :error ,  type }  -> 
475-         context  = 
476-           if  warn_undefined? ( module ,  fun ,  arity ,  stack )  do 
477-             warn ( __MODULE__ ,  { :undefined ,  type ,  module ,  fun ,  arity } ,  meta ,  stack ,  context ) 
478-           else 
479-             context 
480-           end 
492+       true  -> 
493+         case  ParallelChecker . fetch_export ( stack . cache ,  module ,  fun ,  arity )  do 
494+           { :ok ,  mode ,  reason ,  info }  -> 
495+             info  =  if  info  ==  :none ,  do:  signature ( fun ,  arity ) ,  else:  info 
496+             { info ,  check_deprecated ( mode ,  module ,  fun ,  arity ,  reason ,  meta ,  stack ,  context ) } 
481497
482-         { :none ,  context } 
498+           { :error ,  type }  -> 
499+             context  = 
500+               if  warn_undefined? ( module ,  fun ,  arity ,  stack )  do 
501+                 warn ( __MODULE__ ,  { :undefined ,  type ,  module ,  fun ,  arity } ,  meta ,  stack ,  context ) 
502+               else 
503+                 context 
504+               end 
505+ 
506+             { :none ,  context } 
507+         end 
483508    end 
484509  end 
485510
@@ -507,6 +532,27 @@ defmodule Module.Types.Apply do
507532    end 
508533  end 
509534
535+   defp  builtin_module? ( module )  do 
536+     is_map_key ( builtin_modules ( ) ,  module ) 
537+   end 
538+ 
539+   defp  builtin_modules  do 
540+     case  :persistent_term . get ( __MODULE__ ,  nil )  do 
541+       nil  -> 
542+         { :ok ,  mods }  =  :application . get_key ( :elixir ,  :modules ) 
543+         mods  =  Map . from_keys ( mods ,  [ ] ) 
544+         :persistent_term . put ( __MODULE__ ,  mods ) 
545+         mods 
546+ 
547+       % { }  =  mods  -> 
548+         mods 
549+     end 
550+   end 
551+ 
552+   defp  warn_undefined? ( _ ,  _ ,  _ ,  % { no_warn_undefined:  % Macro.Env { } } )  do 
553+     false 
554+   end 
555+ 
510556  defp  warn_undefined? ( _ ,  _ ,  _ ,  % { no_warn_undefined:  :all } )  do 
511557    false 
512558  end 
@@ -572,14 +618,14 @@ defmodule Module.Types.Apply do
572618        { dynamic ( fun ( ) ) ,  context } 
573619
574620      { _kind ,  _info ,  context }  when  stack . mode  ==  :traversal  -> 
575-         { fun ( ) ,  context } 
621+         { dynamic ( fun ( ) ) ,  context } 
576622
577623      { kind ,  _info ,  context }  -> 
578624        if  stack . mode  !=  :infer  and  kind  ==  :defp  do 
579625          # Mark all clauses as used, as the function is being exported. 
580-           { fun ( ) ,  put_in ( context . local_used [ fun_arity ] ,  [ ] ) } 
626+           { dynamic ( fun ( ) ) ,  put_in ( context . local_used [ fun_arity ] ,  [ ] ) } 
581627        else 
582-           { fun ( ) ,  context } 
628+           { dynamic ( fun ( ) ) ,  context } 
583629        end 
584630    end 
585631  end 
0 commit comments