@@ -178,16 +178,34 @@ defmodule Module.Types.Expr do
178178    of_expr ( post ,  stack ,  context ) 
179179  end 
180180
181-   # TODO: cond do pat -> expr end 
182181  def  of_expr ( { :cond ,  _meta ,  [ [ { :do ,  clauses } ] ] } ,  stack ,  context )  do 
183-     context  = 
184-       Enum . reduce ( clauses ,  context ,  fn  { :-> ,  _meta ,  [ head ,  body ] } ,  context  -> 
185-         { _ ,  context }  =  of_expr ( head ,  stack ,  context ) 
186-         { _ ,  context }  =  of_expr ( body ,  stack ,  context ) 
187-         context 
188-       end ) 
182+     clauses 
183+     |>  reduce_non_empty ( { none ( ) ,  context } ,  fn 
184+       { :-> ,  meta ,  [ [ head ] ,  body ] } ,  { acc ,  context } ,  last?  -> 
185+         { head_type ,  context }  =  of_expr ( head ,  stack ,  context ) 
189186
190-     { dynamic ( ) ,  context } 
187+         context  = 
188+           if  stack . mode  ==  :infer  do 
189+             context 
190+           else 
191+             case  truthness ( head_type )  do 
192+               :always_true  when  not  last?  -> 
193+                 warning  =  { :badcond ,  "always match" ,  head_type ,  head ,  context } 
194+                 warn ( __MODULE__ ,  warning ,  meta ,  stack ,  context ) 
195+ 
196+               :always_false  -> 
197+                 warning  =  { :badcond ,  "never match" ,  head_type ,  head ,  context } 
198+                 warn ( __MODULE__ ,  warning ,  meta ,  stack ,  context ) 
199+ 
200+               _  -> 
201+                 context 
202+             end 
203+           end 
204+ 
205+         { body_type ,  context }  =  of_expr ( body ,  stack ,  context ) 
206+         { union ( body_type ,  acc ) ,  context } 
207+     end ) 
208+     |>  dynamic_unless_static ( stack ) 
191209  end 
192210
193211  # TODO: case expr do pat -> expr end 
@@ -459,6 +477,15 @@ defmodule Module.Types.Expr do
459477    { Enum . reduce ( returns ,  & union / 2 ) ,  context } 
460478  end 
461479
480+   defp  reduce_non_empty ( [ last ] ,  acc ,  fun ) , 
481+     do:  fun . ( last ,  acc ,  true ) 
482+ 
483+   defp  reduce_non_empty ( [ head  |  tail ] ,  acc ,  fun ) , 
484+     do:  reduce_non_empty ( tail ,  fun . ( head ,  acc ,  false ) ,  fun ) 
485+ 
486+   defp  dynamic_unless_static ( { _ ,  _ }  =  output ,  % { mode:  :static } ) ,  do:  output 
487+   defp  dynamic_unless_static ( { type ,  context } ,  % { mode:  _ } ) ,  do:  { dynamic ( type ) ,  context } 
488+ 
462489  defp  of_clauses ( clauses ,  stack ,  context )  do 
463490    Enum . reduce ( clauses ,  context ,  fn  { :-> ,  meta ,  [ head ,  body ] } ,  context  -> 
464491      { patterns ,  guards }  =  extract_head ( head ) 
@@ -480,13 +507,8 @@ defmodule Module.Types.Expr do
480507    { other ,  [ ] } 
481508  end 
482509
483-   defp  flatten_when ( { :when ,  _meta ,  [ left ,  right ] } )  do 
484-     [ left  |  flatten_when ( right ) ] 
485-   end 
486- 
487-   defp  flatten_when ( other )  do 
488-     [ other ] 
489-   end 
510+   defp  flatten_when ( { :when ,  _meta ,  [ left ,  right ] } ) ,  do:  [ left  |  flatten_when ( right ) ] 
511+   defp  flatten_when ( other ) ,  do:  [ other ] 
490512
491513  defp  of_expr_context ( expr ,  stack ,  context )  do 
492514    { _type ,  context }  =  of_expr ( expr ,  stack ,  context ) 
@@ -582,4 +604,25 @@ defmodule Module.Types.Expr do
582604        ] ) 
583605    } 
584606  end 
607+ 
608+   def  format_diagnostic ( { :badcond ,  explain ,  type ,  expr ,  context } )  do 
609+     traces  =  collect_traces ( expr ,  context ) 
610+ 
611+     % { 
612+       details:  % { typing_traces:  traces } , 
613+       message: 
614+          IO . iodata_to_binary ( [ 
615+           """ 
616+           this clause in cond will #{ explain }  : 
617+ 
618+               #{ expr_to_string ( expr )  |>  indent ( 4 ) }  
619+ 
620+           since it has type: 
621+ 
622+               #{ to_quoted_string ( type )  |>  indent ( 4 ) }  
623+           """ , 
624+           format_traces ( traces ) 
625+         ] ) 
626+     } 
627+   end 
585628end 
0 commit comments