@@ -523,18 +523,21 @@ defmodule Module.Types.Apply do
523523
524524 { actual , context } = of_fun . ( arg , expected , expr , stack , context )
525525 result = if compatible? ( actual , expected ) , do: return , else: boolean ( )
526+
527+ # We can skip return compare because literal is always an integer,
528+ # so it cannot be a disjoint comparison
526529 { result , context }
527530 end
528531 end
529532
530533 defp custom_compare ( name , arg , literal , expected , expr , stack , context , of_fun ) do
531- { literal_type , context } = of_fun . ( literal , term ( ) , expr , stack , context )
532-
533534 case booleaness ( expected ) do
534535 booleaness when booleaness in [ :maybe_both , :none ] ->
535536 compare ( name , arg , literal , false , expr , stack , context , of_fun )
536537
537538 booleaness ->
539+ { literal_type , context } = of_fun . ( literal , term ( ) , expr , stack , context )
540+
538541 { polarity , return } =
539542 case booleaness do
540543 :maybe_true -> { name in [ :== , :"=:=" ] , @ atom_true }
@@ -544,9 +547,13 @@ defmodule Module.Types.Apply do
544547 # If it is a singleton, we can always be precise
545548 if singleton? ( literal_type ) do
546549 expected = if polarity , do: literal_type , else: negation ( literal_type )
547- { actual , context } = of_fun . ( arg , expected , expr , stack , context )
548- result = if compatible? ( actual , expected ) , do: return , else: boolean ( )
549- { result , context }
550+ { arg_type , context } = of_fun . ( arg , expected , expr , stack , context )
551+ result = if compatible? ( arg_type , expected ) , do: return , else: boolean ( )
552+
553+ # Because reverse polarity means we will infer negated types
554+ # (which are naturally disjoint), we skip checks in such cases
555+ skip_check? = not polarity
556+ return_compare ( name , arg_type , literal_type , result , skip_check? , expr , stack , context )
550557 else
551558 expected =
552559 cond do
@@ -558,19 +565,23 @@ defmodule Module.Types.Apply do
558565 true -> literal_type
559566 end
560567
561- { _ , context } = of_fun . ( arg , expected , expr , stack , context )
562- { boolean ( ) , context }
568+ { arg_type , context } = of_fun . ( arg , expected , expr , stack , context )
569+ return_compare ( name , arg_type , literal_type , boolean ( ) , false , expr , stack , context )
563570 end
564571 end
565572 end
566573
567- defp compare ( name , left , right , literal ?, expr , stack , context , of_fun ) do
574+ defp compare ( name , left , right , both_literal ?, expr , stack , context , of_fun ) do
568575 { left_type , context } = of_fun . ( left , term ( ) , expr , stack , context )
569576 { right_type , context } = of_fun . ( right , term ( ) , expr , stack , context )
570- result = return ( boolean ( ) , [ left_type , right_type ] , stack )
577+ return_compare ( name , left_type , right_type , boolean ( ) , both_literal? , expr , stack , context )
578+ end
579+
580+ defp return_compare ( name , left_type , right_type , result , skip_check? , expr , stack , context ) do
581+ result = return ( result , [ left_type , right_type ] , stack )
571582
572583 cond do
573- literal ? or not is_warning ( stack ) ->
584+ skip_check ? or not is_warning ( stack ) ->
574585 { result , context }
575586
576587 name in [ :== , :"/=" ] and number_type? ( left_type ) and number_type? ( right_type ) ->
0 commit comments