@@ -382,7 +382,8 @@ defmodule Module.Types.Descr do
382382      { dynamic ,  descr }  = 
383383        case  :maps . take ( :dynamic ,  descr )  do 
384384          :error  ->  { [ ] ,  descr } 
385-           { dynamic ,  descr }  ->  { to_quoted ( :dynamic ,  dynamic ,  opts ) ,  descr } 
385+           { :term ,  descr }  ->  { to_quoted ( :dynamic ,  :term ,  opts ) ,  descr } 
386+           { dynamic ,  descr }  ->  { to_quoted ( :dynamic ,  difference ( dynamic ,  descr ) ,  opts ) ,  descr } 
386387        end 
387388
388389      # Merge empty list and list together if they both exist 
@@ -547,6 +548,41 @@ defmodule Module.Types.Descr do
547548    end 
548549  end 
549550
551+   @ doc  """ 
552+   Returns the intersection between two types 
553+   only if they are compatible. Otherwise returns `:error`. 
554+ 
555+   This finds the intersection between the arguments and the 
556+   domain of a function. It is used to refine dynamic types 
557+   as we traverse the program. 
558+   """ 
559+   def  compatible_intersection ( left ,  right )  do 
560+     { left_dynamic ,  left_static }  = 
561+       case  left  do 
562+         :term  ->  { :term ,  :term } 
563+         _  ->  Map . pop ( left ,  :dynamic ,  left ) 
564+       end 
565+ 
566+     right_dynamic  = 
567+       case  right  do 
568+         % { dynamic:  dynamic }  ->  dynamic 
569+         _  ->  right 
570+       end 
571+ 
572+     cond  do 
573+       empty? ( left_static )  -> 
574+         dynamic  =  intersection_static ( unfold ( left_dynamic ) ,  unfold ( right_dynamic ) ) 
575+         if  empty? ( dynamic ) ,  do:  :error ,  else:  { :ok ,  dynamic ( dynamic ) } 
576+ 
577+       subtype_static? ( left_static ,  right_dynamic )  -> 
578+         dynamic  =  intersection_static ( unfold ( left_dynamic ) ,  unfold ( right_dynamic ) ) 
579+         { :ok ,  union ( dynamic ( dynamic ) ,  left_static ) } 
580+ 
581+       true  -> 
582+         :error 
583+     end 
584+   end 
585+ 
550586  @ doc  """ 
551587  Optimized version of `not empty?(term(), type)`. 
552588  """ 
0 commit comments