@@ -138,7 +138,7 @@ defmodule Module.Types.Expr do
138138 end
139139
140140 # left = right
141- def of_expr ( { := , _ , [ left_expr , right_expr ] } = match , expected , expr , stack , context ) do
141+ def of_expr ( { := , meta , [ left_expr , right_expr ] } = match , expected , expr , stack , context ) do
142142 { left_expr , right_expr } = repack_match ( left_expr , right_expr )
143143
144144 case left_expr do
@@ -151,16 +151,16 @@ defmodule Module.Types.Expr do
151151 fn pattern_type , context ->
152152 # See if we can use the expected type to further refine the pattern type,
153153 # if we cannot, use the pattern type as that will fail later on.
154- { _ok_or_error , type } = compatible_intersection ( dynamic ( pattern_type ) , expected )
154+ type = intersection ( pattern_type , expected )
155+ type = if empty? ( type ) , do: pattern_type , else: type
155156 { result , context } = of_expr ( right_expr , type , expr , stack , context )
156157
157- # The function may still return a too broad type, so we refine once again
158- # to assign the most appropriate one for reverse arrows.
159- { _ok_or_error , result } = compatible_intersection ( result , expected )
160- { result , context }
158+ # The function may still return a too broad type,
159+ # so we refine once again to assign the most appropriate to the pattern.
160+ { intersection ( result , expected ) , context }
161161 end
162162
163- Pattern . of_match ( left_expr , type_fun , match , stack , context )
163+ Pattern . of_match ( left_expr , type_fun , match , meta , stack , context )
164164 end
165165 end
166166
@@ -412,7 +412,7 @@ defmodule Module.Types.Expr do
412412 { type , context } =
413413 if else_block do
414414 { type , context } = of_expr ( body , term ( ) , body , stack , original )
415- info = { :try_else , meta , body , type }
415+ info = { :try_else , type }
416416 of_clauses ( else_block , [ type ] , expected , info , stack , context , none ( ) )
417417 else
418418 of_expr ( body , expected , expr , stack , original )
@@ -500,14 +500,13 @@ defmodule Module.Types.Expr do
500500 case into_kind do
501501 :bitstring ->
502502 { block_type , context } = of_expr ( block , bitstring ( ) , block , stack , context )
503+ intersection = intersection ( block_type , bitstring ( ) )
503504
504- case compatible_intersection ( block_type , bitstring ( ) ) do
505- { :ok , intersection } ->
506- { union ( into_type , intersection ) , context }
507-
508- { :error , _ } ->
509- error = { :badbitbody , block_type , block , context }
510- { error_type ( ) , error ( __MODULE__ , error , meta , stack , context ) }
505+ if empty? ( intersection ) do
506+ error = { :badbitbody , block_type , block , context }
507+ { error_type ( ) , error ( __MODULE__ , error , meta , stack , context ) }
508+ else
509+ { union ( into_type , intersection ) , context }
511510 end
512511
513512 :non_empty_list ->
@@ -530,12 +529,27 @@ defmodule Module.Types.Expr do
530529 end
531530
532531 # TODO: with pat <- expr do expr end
533- def of_expr ( { :with , meta , [ _ | _ ] = clauses } , _expected , _expr , stack , original ) do
532+ def of_expr ( { :with , meta , [ _ | _ ] = clauses } , expected , _expr , stack , original ) do
534533 cache_result ( meta , stack , original , fn ->
535- { clauses , [ options ] } = Enum . split ( clauses , - 1 )
536- context = Enum . reduce ( clauses , original , & with_clause ( & 1 , stack , & 2 ) )
537- context = Enum . reduce ( options , context , & with_option ( & 1 , stack , & 2 , original ) )
538- { dynamic ( ) , context }
534+ { clauses , [ [ do: do_block ] ++ options ] } = Enum . split ( clauses , - 1 )
535+
536+ { else_types , context } =
537+ Enum . reduce ( clauses , { none ( ) , original } , & with_clause ( & 1 , stack , & 2 ) )
538+
539+ { do_result , context } = of_expr ( do_block , expected , do_block , stack , context )
540+ context = Of . reset_vars ( context , original )
541+
542+ { else_result , context } =
543+ case options do
544+ [ else: clauses ] ->
545+ info = { :with_else , else_types }
546+ of_clauses ( clauses , [ else_types ] , expected , info , stack , context , none ( ) )
547+
548+ [ ] ->
549+ { else_types , context }
550+ end
551+
552+ dynamic_unless_static ( { union ( do_result , else_result ) , context } , stack )
539553 end )
540554 end
541555
@@ -664,19 +678,25 @@ defmodule Module.Types.Expr do
664678 ## Comprehensions
665679
666680 defp for_clause ( { :<- , meta , [ left , right ] } , stack , context ) do
667- expr = { :<- , [ type_check: :generator ] ++ meta , [ left , right ] }
668- { pattern , guards } = extract_head ( [ left ] )
681+ meta = [ type_check: :generator ] ++ meta
682+ expr = { :<- , meta , [ left , right ] }
683+ { [ pattern ] , guards } = extract_head ( [ left ] )
669684
670685 # TODO: Extract the type from enumerable protocol
671686 { _type , context } =
672687 Apply . remote ( Enumerable , :count , [ right ] , term ( ) , expr , stack , context , & of_expr / 5 )
673688
674- Pattern . of_generator ( pattern , guards , dynamic ( ) , :for , expr , stack , context )
689+ { _tree , _precise , context } =
690+ Pattern . of_generator ( pattern , guards , dynamic ( ) , :for , expr , meta , stack , context )
691+
692+ context
675693 end
676694
677695 defp for_clause ( { :<<>> , _ , [ { :<- , meta , [ left , right ] } ] } = expr , stack , context ) do
678696 { right_type , context } = of_expr ( right , bitstring ( ) , expr , stack , context )
679- context = Pattern . of_generator ( left , [ ] , bitstring ( ) , :for , expr , stack , context )
697+
698+ { _tree , _precise? , context } =
699+ Pattern . of_generator ( left , [ ] , bitstring ( ) , :for , expr , meta , stack , context )
680700
681701 if compatible? ( right_type , bitstring ( ) ) do
682702 context
@@ -739,27 +759,31 @@ defmodule Module.Types.Expr do
739759
740760 ## With
741761
742- defp with_clause ( { :<- , _meta , [ left , right ] } = expr , stack , context ) do
743- { pattern , guards } = extract_head ( [ left ] )
744- { _type , context } = of_expr ( right , @ pending , right , stack , context )
745- Pattern . of_generator ( pattern , guards , dynamic ( ) , :with , expr , stack , context )
746- end
762+ defp with_clause ( { :<- , meta , [ left , right ] } = expr , stack , { else_types , context } ) do
763+ { [ pattern ] , guards } = extract_head ( [ left ] )
747764
748- defp with_clause ( expr , stack , context ) do
749- { _type , context } = of_expr ( expr , @ pending , expr , stack , context )
750- context
751- end
765+ { type , context } =
766+ of_expr ( right , term ( ) , right , % { stack | reverse_arrow: :cache } , context )
752767
753- defp with_option ( { :do , body } , stack , context , original ) do
754- { _type , context } = of_expr ( body , @ pending , body , stack , context )
755- Of . reset_vars ( context , original )
756- end
768+ { trees , precise? , context } =
769+ Pattern . of_generator ( pattern , guards , type , :with , expr , meta , stack , context )
757770
758- defp with_option ( { :else , clauses } , stack , context , _original ) do
759- { _ , context } =
760- of_clauses ( clauses , [ dynamic ( ) ] , @ pending , :with_else , stack , context , none ( ) )
771+ if precise? do
772+ [ pattern_type ] = Pattern . of_domain ( trees , stack , context )
761773
762- context
774+ { _ , refined_context } =
775+ of_expr ( right , pattern_type , right , % { stack | reverse_arrow: :use } , context )
776+
777+ { union ( difference ( type , pattern_type ) , else_types ) ,
778+ reset_warnings ( refined_context , context ) }
779+ else
780+ { union ( type , else_types ) , context }
781+ end
782+ end
783+
784+ defp with_clause ( expr , stack , { else_types , context } ) do
785+ { _type , context } = of_expr ( expr , term ( ) , expr , stack , context )
786+ { else_types , context }
763787 end
764788
765789 ## General helpers
0 commit comments