@@ -369,19 +369,41 @@ defmodule Module.Types.Expr do
369369 of_expr ( body , expected , body , stack , reset_warnings ( refined_context , context ) )
370370 end
371371
372- result_context =
373- cache_arrows ( meta , stack , fn ->
374- of_clauses_fun ( clauses , [ case_type ] , info , stack , context , of_body , [ ] , fn
375- trees , body_type , context , acc ->
376- [ arg_type ] = Pattern . of_domain ( trees , stack , context )
377- [ { arg_type , body_type } | acc ]
378- end )
379- end ) ||
380- of_clauses_fun ( clauses , [ case_type ] , info , stack , context , of_body , none ( ) , fn
381- _trees , body_type , _context , acc -> union ( acc , body_type )
382- end )
372+ { { head_type , body_type } , _ , context } =
373+ cache_arrows ( meta , stack , fn cache? ->
374+ acc = { none ( ) , none ( ) , [ ] }
375+
376+ { { head_acc , body_acc , clauses_acc } , context } =
377+ of_clauses_fun ( clauses , [ case_type ] , info , stack , context , of_body , acc , fn
378+ trees , precise? , body_type , context , { head_acc , body_acc , clauses_acc } ->
379+ cond do
380+ precise? and empty? ( body_type ) ->
381+ [ arg_type ] = Pattern . of_domain ( trees , stack , context )
382+ { union ( negation ( arg_type ) , head_acc ) , body_acc , clauses_acc }
383+
384+ cache? ->
385+ [ arg_type ] = Pattern . of_domain ( trees , stack , context )
386+ { head_acc , union ( body_type , body_acc ) , [ { arg_type , body_type } | clauses_acc ] }
387+
388+ true ->
389+ { head_acc , union ( body_type , body_acc ) , clauses_acc }
390+ end
391+ end )
392+
393+ { { head_acc , body_acc } , clauses_acc , context }
394+ end )
395+
396+ context =
397+ if head_type == none ( ) do
398+ context
399+ else
400+ { _ , refined_context } =
401+ of_expr ( case_expr , head_type , case_expr , % { stack | reverse_arrow: :use } , context )
383402
384- dynamic_unless_static ( result_context , stack )
403+ reset_warnings ( refined_context , context )
404+ end
405+
406+ dynamic_unless_static ( { body_type , context } , stack )
385407 end
386408
387409 # fn pat -> expr end
@@ -395,7 +417,7 @@ defmodule Module.Types.Expr do
395417
396418 { acc , context } =
397419 of_clauses_fun ( clauses , domain , :fn , stack , context , of_body , [ ] , fn
398- trees , body_type , context , acc ->
420+ trees , _precise? , body_type , context , acc ->
399421 args_types = Pattern . of_domain ( trees , stack , context )
400422 add_inferred ( acc , args_types , body_type )
401423 end )
@@ -828,19 +850,18 @@ defmodule Module.Types.Expr do
828850 end
829851 end
830852
831- defp cache_arrows ( _meta , % { reverse_arrow: nil } , _fun ) , do: nil
853+ defp cache_arrows ( _meta , % { reverse_arrow: nil } , fun ) , do: fun . ( false )
832854
833855 defp cache_arrows ( meta , % { reverse_arrow: :cache } , fun ) do
834- { clauses , context } = fun . ( )
856+ { result , cache , context } = fun . ( true )
835857 version = Keyword . fetch! ( meta , :version )
836- context = put_in ( context . reverse_arrows [ version ] , clauses )
837- result = Enum . reduce ( clauses , none ( ) , & union ( elem ( & 1 , 1 ) , & 2 ) )
838- { result , context }
858+ context = put_in ( context . reverse_arrows [ version ] , cache )
859+ { result , cache , context }
839860 end
840861
841862 defp of_clauses ( clauses , domain , expected , base_info , stack , context , acc ) do
842863 of_body = fn _args_types , body , context -> of_expr ( body , expected , body , stack , context ) end
843- of_acc = fn _args_types , body_type , _context , acc -> union ( acc , body_type ) end
864+ of_acc = fn _args_types , _precise? , body_type , _context , acc -> union ( acc , body_type ) end
844865 of_clauses_fun ( clauses , domain , base_info , stack , context , of_body , acc , of_acc )
845866 end
846867
@@ -854,12 +875,12 @@ defmodule Module.Types.Expr do
854875 { patterns , guards } = extract_head ( head )
855876 info = { base_info , head }
856877
857- { trees , _ , previous , context } =
878+ { trees , precise? , _ , previous , context } =
858879 Pattern . of_head ( patterns , guards , domain , previous , info , meta , stack , context )
859880
860881 { result , context } = of_body . ( trees , body , context )
861882
862- { of_acc . ( trees , result , context , acc ) , previous ,
883+ { of_acc . ( trees , precise? , result , context , acc ) , previous ,
863884 context |> set_failed ( failed? ) |> Of . reset_vars ( original ) }
864885 end )
865886
0 commit comments