@@ -133,19 +133,29 @@ defmodule Module.Types.Expr do
133133 end
134134
135135 # left = right
136- # TODO: here
137- def of_expr ( { := , _ , [ left_expr , right_expr ] } = expr , _expected , _expr , stack , context ) do
136+ def of_expr ( { := , _ , [ left_expr , right_expr ] } = match , expected , expr , stack , context ) do
138137 { left_expr , right_expr } = repack_match ( left_expr , right_expr )
139- { right_type , context } = of_expr ( right_expr , @ pending , expr , stack , context )
140138
141- # We do not raise on underscore in case someone writes _ = raise "omg"
142- context =
143- case left_expr do
144- { :_ , _ , ctx } when is_atom ( ctx ) -> context
145- _ -> Pattern . of_match ( left_expr , right_type , expr , { :match , right_type } , stack , context )
146- end
139+ case left_expr do
140+ # We do not raise on underscore in case someone writes _ = raise "omg"
141+ { :_ , _ , ctx } when is_atom ( ctx ) ->
142+ of_expr ( right_expr , expected , expr , stack , context )
143+
144+ _ ->
145+ type_fun = fn pattern_type , context ->
146+ # See if we can use the expected type to further refine the pattern type,
147+ # if we cannot, use the pattern type as that will fail later on.
148+ type =
149+ case compatible_intersection ( pattern_type , expected ) do
150+ { :ok , expected } -> expected
151+ :error -> pattern_type
152+ end
153+
154+ of_expr ( right_expr , type , expr , stack , context )
155+ end
147156
148- { right_type , context }
157+ Pattern . of_match ( left_expr , type_fun , match , stack , context )
158+ end
149159 end
150160
151161 # %{map | ...}
@@ -236,23 +246,23 @@ defmodule Module.Types.Expr do
236246 end
237247
238248 # (expr; expr)
239- def of_expr ( { :__block__ , _meta , exprs } , expected , expr , stack , context ) do
249+ def of_expr ( { :__block__ , _meta , exprs } , expected , _expr , stack , context ) do
240250 { pre , [ post ] } = Enum . split ( exprs , - 1 )
241251
242252 context =
243253 Enum . reduce ( pre , context , fn expr , context ->
244- { _ , context } = of_expr ( expr , @ term , :ok , stack , context )
254+ { _ , context } = of_expr ( expr , @ term , expr , stack , context )
245255 context
246256 end )
247257
248- of_expr ( post , expected , expr , stack , context )
258+ of_expr ( post , expected , post , stack , context )
249259 end
250260
251261 def of_expr ( { :cond , _meta , [ [ { :do , clauses } ] ] } , expected , expr , stack , original ) do
252262 clauses
253263 |> reduce_non_empty ( { none ( ) , original } , fn
254264 { :-> , meta , [ [ head ] , body ] } , { acc , context } , last? ->
255- { head_type , context } = of_expr ( head , @ pending , :ok , stack , context )
265+ { head_type , context } = of_expr ( head , @ pending , head , stack , context )
256266
257267 context =
258268 if stack . mode in [ :infer , :traversal ] do
@@ -280,7 +290,7 @@ defmodule Module.Types.Expr do
280290
281291 # TODO: here
282292 def of_expr ( { :case , meta , [ case_expr , [ { :do , clauses } ] ] } , expected , expr , stack , context ) do
283- { case_type , context } = of_expr ( case_expr , @ pending , :ok , stack , context )
293+ { case_type , context } = of_expr ( case_expr , @ pending , case_expr , stack , context )
284294
285295 # If we are only type checking the expression and the expression is a literal,
286296 # let's mark it as generated, as it is most likely a macro code. However, if
@@ -307,7 +317,7 @@ defmodule Module.Types.Expr do
307317 [ { :-> , _ , [ head , _ ] } | _ ] = clauses
308318 { patterns , _guards } = extract_head ( head )
309319 domain = Enum . map ( patterns , fn _ -> dynamic ( ) end )
310- { _acc , context } = of_clauses ( clauses , domain , @ pending , :ok , :fn , stack , { none ( ) , context } )
320+ { _acc , context } = of_clauses ( clauses , domain , @ pending , nil , :fn , stack , { none ( ) , context } )
311321 { fun ( ) , context }
312322 end
313323
@@ -318,7 +328,7 @@ defmodule Module.Types.Expr do
318328
319329 { type , context } =
320330 if else_block do
321- { type , context } = of_expr ( body , @ pending , :ok , stack , original )
331+ { type , context } = of_expr ( body , @ pending , body , stack , original )
322332
323333 of_clauses (
324334 else_block ,
@@ -362,7 +372,7 @@ defmodule Module.Types.Expr do
362372 |> dynamic_unless_static ( stack )
363373
364374 if after_block do
365- { _type , context } = of_expr ( after_block , @ term , :ok , stack , context )
375+ { _type , context } = of_expr ( after_block , @ term , after_block , stack , context )
366376 { type , context }
367377 else
368378 { type , context }
@@ -412,7 +422,7 @@ defmodule Module.Types.Expr do
412422 else
413423 into = Keyword . get ( opts , :into , [ ] )
414424 { into_wrapper , gradual? , context } = for_into ( into , meta , stack , context )
415- { block_type , context } = of_expr ( block , @ pending , :ok , stack , context )
425+ { block_type , context } = of_expr ( block , @ pending , block , stack , context )
416426
417427 for_type =
418428 for type <- into_wrapper do
@@ -443,7 +453,7 @@ defmodule Module.Types.Expr do
443453 { fun_type , context } = of_expr ( fun , fun ( ) , call , stack , context )
444454
445455 { _args_types , context } =
446- Enum . map_reduce ( args , context , & of_expr ( & 1 , @ pending , :ok , stack , & 2 ) )
456+ Enum . map_reduce ( args , context , & of_expr ( & 1 , @ pending , & 1 , stack , & 2 ) )
447457
448458 case fun_fetch ( fun_type , length ( args ) ) do
449459 :ok ->
@@ -455,7 +465,6 @@ defmodule Module.Types.Expr do
455465 end
456466 end
457467
458- # TODO: here
459468 def of_expr ( { { :. , _ , [ callee , key_or_fun ] } , meta , [ ] } = call , expected , expr , stack , context )
460469 when not is_atom ( callee ) and is_atom ( key_or_fun ) do
461470 if Keyword . get ( meta , :no_parens , false ) do
@@ -490,7 +499,7 @@ defmodule Module.Types.Expr do
490499 end
491500
492501 { args_types , context } =
493- Enum . map_reduce ( args , context , & of_expr ( & 1 , @ pending , :ok , stack , & 2 ) )
502+ Enum . map_reduce ( args , context , & of_expr ( & 1 , @ pending , & 1 , stack , & 2 ) )
494503
495504 { types , context } =
496505 Enum . map_reduce ( funs , context , fn fun , context ->
@@ -511,7 +520,7 @@ defmodule Module.Types.Expr do
511520 { remote_type , context } = of_expr ( remote , atom ( ) , call , stack , context )
512521
513522 { args_types , context } =
514- Enum . map_reduce ( args , context , & of_expr ( & 1 , @ pending , :ok , stack , & 2 ) )
523+ Enum . map_reduce ( args , context , & of_expr ( & 1 , @ pending , & 1 , stack , & 2 ) )
515524
516525 { mods , context } = Of . modules ( remote_type , name , length ( args ) , call , meta , stack , context )
517526 apply_many ( mods , name , args , args_types , call , stack , context )
@@ -542,7 +551,7 @@ defmodule Module.Types.Expr do
542551 { _kind , fun } = Keyword . fetch! ( meta , :super )
543552
544553 { args_types , context } =
545- Enum . map_reduce ( args , context , & of_expr ( & 1 , @ pending , :ok , stack , & 2 ) )
554+ Enum . map_reduce ( args , context , & of_expr ( & 1 , @ pending , & 1 , stack , & 2 ) )
546555
547556 Apply . local ( fun , args_types , expr , stack , context )
548557 end
@@ -552,7 +561,7 @@ defmodule Module.Types.Expr do
552561 def of_expr ( { fun , _meta , args } = expr , _expected , _expr , stack , context )
553562 when is_atom ( fun ) and is_list ( args ) do
554563 { args_types , context } =
555- Enum . map_reduce ( args , context , & of_expr ( & 1 , @ pending , :ok , stack , & 2 ) )
564+ Enum . map_reduce ( args , context , & of_expr ( & 1 , @ pending , & 1 , stack , & 2 ) )
556565
557566 Apply . local ( fun , args_types , expr , stack , context )
558567 end
@@ -602,7 +611,7 @@ defmodule Module.Types.Expr do
602611 context
603612 end
604613
605- { type , context } = of_expr ( body , @ pending , :ok , stack , context )
614+ { type , context } = of_expr ( body , @ pending , body , stack , context )
606615 { type , reset_vars ( context , original ) }
607616 end
608617
@@ -611,19 +620,14 @@ defmodule Module.Types.Expr do
611620 defp for_clause ( { :<- , meta , [ left , right ] } , stack , context ) do
612621 expr = { :<- , [ type_check: :generator ] ++ meta , [ left , right ] }
613622 { pattern , guards } = extract_head ( [ left ] )
614- { type , context } = of_expr ( right , @ pending , :ok , stack , context )
615-
616- context = Pattern . of_match ( pattern , guards , dynamic ( ) , expr , :for , stack , context )
617-
618- { _type , context } =
619- Apply . remote ( Enumerable , :count , [ right ] , [ type ] , expr , stack , context )
620-
621- context
623+ { type , context } = of_expr ( right , @ pending , expr , stack , context )
624+ { _type , context } = Apply . remote ( Enumerable , :count , [ right ] , [ type ] , expr , stack , context )
625+ Pattern . of_generator ( pattern , guards , dynamic ( ) , :for , expr , stack , context )
622626 end
623627
624628 defp for_clause ( { :<<>> , _ , [ { :<- , meta , [ left , right ] } ] } = expr , stack , context ) do
625629 { right_type , context } = of_expr ( right , binary ( ) , expr , stack , context )
626- context = Pattern . of_match ( left , binary ( ) , expr , :for , stack , context )
630+ context = Pattern . of_generator ( left , [ ] , binary ( ) , :for , expr , stack , context )
627631
628632 if compatible? ( right_type , binary ( ) ) do
629633 context
@@ -648,7 +652,7 @@ defmodule Module.Types.Expr do
648652
649653 # TODO: Use the collectable protocol for the output
650654 defp for_into ( into , meta , stack , context ) do
651- { type , context } = of_expr ( into , @ pending , :ok , stack , context )
655+ { type , context } = of_expr ( into , @ pending , into , stack , context )
652656
653657 # We use subtype? instead of compatible because we want to handle
654658 # only binary/list, even if a dynamic with something else is given.
@@ -675,24 +679,23 @@ defmodule Module.Types.Expr do
675679
676680 defp with_clause ( { :<- , _meta , [ left , right ] } = expr , stack , context ) do
677681 { pattern , guards } = extract_head ( [ left ] )
678- context = Pattern . of_match ( pattern , guards , dynamic ( ) , expr , :with , stack , context )
679- { _ , context } = of_expr ( right , @ pending , :ok , stack , context )
680- context
682+ { _type , context } = of_expr ( right , @ pending , right , stack , context )
683+ Pattern . of_generator ( pattern , guards , dynamic ( ) , :with , expr , stack , context )
681684 end
682685
683686 defp with_clause ( expr , stack , context ) do
684- { _type , context } = of_expr ( expr , @ pending , :ok , stack , context )
687+ { _type , context } = of_expr ( expr , @ pending , expr , stack , context )
685688 context
686689 end
687690
688691 defp with_option ( { :do , body } , stack , context , original ) do
689- { _type , context } = of_expr ( body , @ pending , :ok , stack , context )
692+ { _type , context } = of_expr ( body , @ pending , body , stack , context )
690693 reset_vars ( context , original )
691694 end
692695
693696 defp with_option ( { :else , clauses } , stack , context , _original ) do
694697 { _ , context } =
695- of_clauses ( clauses , [ dynamic ( ) ] , @ pending , :ok , :with_else , stack , { none ( ) , context } )
698+ of_clauses ( clauses , [ dynamic ( ) ] , @ pending , nil , :with_else , stack , { none ( ) , context } )
696699
697700 context
698701 end
@@ -733,7 +736,7 @@ defmodule Module.Types.Expr do
733736 { patterns , guards } = extract_head ( head )
734737 { _trees , context } = Pattern . of_head ( patterns , guards , domain , info , meta , stack , context )
735738
736- { body , context } = of_expr ( body , expected , expr , stack , context )
739+ { body , context } = of_expr ( body , expected , expr || body , stack , context )
737740 context = context |> set_failed ( failed? ) |> reset_vars ( original )
738741
739742 if mode == :traversal do
0 commit comments