Skip to content

Commit 99eae95

Browse files
committed
Unify boolean checks into a single operation
1 parent 7fb01d3 commit 99eae95

4 files changed

Lines changed: 51 additions & 64 deletions

File tree

lib/elixir/lib/module/types/apply.ex

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -503,14 +503,14 @@ defmodule Module.Types.Apply do
503503
)
504504
when is_data_size(fun, literal) do
505505
case booleaness(expected) do
506-
:undefined ->
506+
booleaness when booleaness in [:maybe_both, :none] ->
507507
compare(name, left, literal, false, expr, stack, context, of_fun)
508508

509-
boolean ->
509+
booleaness ->
510510
{polarity, return} =
511-
case boolean do
512-
:always_true -> {name in [:==, :"=:="], @atom_true}
513-
:always_false -> {name in [:"/=", :"=/="], @atom_false}
511+
case booleaness do
512+
:maybe_true -> {name in [:==, :"=:="], @atom_true}
513+
:maybe_false -> {name in [:"/=", :"=/="], @atom_false}
514514
end
515515

516516
expected =
@@ -559,16 +559,16 @@ defmodule Module.Types.Apply do
559559
case {left, right} do
560560
{{{:., _, [:erlang, fun]}, _, [arg]}, size} when is_data_size(fun, size) ->
561561
case booleaness(expected) do
562-
:always_true -> sized_order(name, fun, size, arg, @atom_true)
563-
:always_false -> sized_order(invert_order(name), fun, size, arg, @atom_false)
564-
:undefined -> :none
562+
:maybe_true -> sized_order(name, fun, size, arg, @atom_true)
563+
:maybe_false -> sized_order(invert_order(name), fun, size, arg, @atom_false)
564+
_ -> :none
565565
end
566566

567567
{size, {{:., _, [:erlang, fun]}, _, [arg]}} when is_data_size(fun, size) ->
568568
case booleaness(expected) do
569-
:always_true -> sized_order(invert_order(name), fun, size, arg, @atom_true)
570-
:always_false -> sized_order(name, fun, size, arg, @atom_false)
571-
:undefined -> :none
569+
:maybe_true -> sized_order(invert_order(name), fun, size, arg, @atom_true)
570+
:maybe_false -> sized_order(name, fun, size, arg, @atom_false)
571+
_ -> :none
572572
end
573573

574574
_ ->

lib/elixir/lib/module/types/descr.ex

Lines changed: 22 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -913,57 +913,40 @@ defmodule Module.Types.Descr do
913913
# an empty list of atoms. It is simplified to `0` in set operations, and the key
914914
# is removed from the map.
915915

916-
@false_or_nil_atoms [
917-
:sets.from_list([false, nil], version: 2),
918-
:sets.from_list([nil], version: 2),
919-
:sets.from_list([false], version: 2)
920-
]
921-
922-
@false_atoms :sets.from_list([false], version: 2)
923-
@true_atoms :sets.from_list([true], version: 2)
924-
925-
@doc """
926-
Returns true if the type can never be true.
927-
"""
928-
def never_true?(:term), do: false
929-
930-
def never_true?(%{} = descr) do
931-
descr = Map.get(descr, :dynamic, descr)
932-
933-
case descr do
934-
:term -> false
935-
%{atom: {:union, %{true => _}}} -> false
936-
%{atom: {:union, _}} -> true
937-
%{atom: {:negation, %{true => _}}} -> true
938-
%{atom: {:negation, _}} -> false
939-
_ -> true
940-
end
941-
end
942-
943916
@doc """
944917
Compute the booleaness of an element.
945918
946-
It is either :undefined, :always_true, or :always_false.
919+
It is either `:none`, `:maybe_true` (therefore never false),
920+
`:maybe_false` (therefore never true), or `:maybe_both`.
921+
922+
This is an optimization against checking if a term is
923+
not disjoint on either true or false.
947924
"""
948-
def booleaness(:term), do: :undefined
925+
def booleaness(:term), do: :maybe_both
949926

950927
def booleaness(%{} = descr) do
951928
descr = Map.get(descr, :dynamic, descr)
952929

953930
case descr do
954-
%{atom: {:union, set}}
955-
when map_size(descr) == 1 and set == @false_atoms ->
956-
:always_false
957-
958-
%{atom: {:union, set}}
959-
when map_size(descr) == 1 and set == @true_atoms ->
960-
:always_true
961-
962-
_ ->
963-
:undefined
931+
:term -> :maybe_both
932+
%{atom: {:union, %{true: _, false: _}}} -> :maybe_both
933+
%{atom: {:union, %{true: _}}} -> :maybe_true
934+
%{atom: {:union, %{false: _}}} -> :maybe_false
935+
%{atom: {:union, _}} -> :none
936+
%{atom: {:negation, %{true: _, false: _}}} -> :none
937+
%{atom: {:negation, %{true: _}}} -> :maybe_false
938+
%{atom: {:negation, %{false: _}}} -> :maybe_true
939+
%{atom: {:negation, _}} -> :maybe_both
940+
_ -> :none
964941
end
965942
end
966943

944+
@false_or_nil_atoms [
945+
:sets.from_list([false, nil], version: 2),
946+
:sets.from_list([nil], version: 2),
947+
:sets.from_list([false], version: 2)
948+
]
949+
967950
@doc """
968951
Compute the truthiness of an element.
969952

lib/elixir/lib/module/types/pattern.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -786,7 +786,7 @@ defmodule Module.Types.Pattern do
786786
end
787787

788788
defp maybe_badguard(type, guard, stack, context) do
789-
if never_true?(type) do
789+
if booleaness(type) in [:maybe_false, :none] do
790790
error = {:badguard, type, guard, context}
791791
error(__MODULE__, error, error_meta(guard, stack), stack, context)
792792
else

lib/elixir/test/elixir/module/types/descr_test.exs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,21 +1225,25 @@ defmodule Module.Types.DescrTest do
12251225
end
12261226

12271227
describe "projections" do
1228-
test "never_true?" do
1229-
for type <- [
1230-
none(),
1231-
integer(),
1232-
atom([false]),
1233-
atom([:other, false]),
1234-
negation(atom([true]))
1235-
] do
1236-
assert never_true?(type)
1237-
assert never_true?(dynamic(type))
1228+
test "booleaness" do
1229+
for type <- [none(), open_map(), negation(boolean()), difference(atom(), boolean())] do
1230+
assert booleaness(type) == :none
1231+
assert booleaness(dynamic(type)) == :none
12381232
end
12391233

1240-
for type <- [atom([true]), boolean(), atom(), term(), negation(atom([false]))] do
1241-
refute never_true?(type)
1242-
refute never_true?(dynamic(type))
1234+
for type <- [term(), dynamic(), atom(), boolean()] do
1235+
assert booleaness(type) == :maybe_both
1236+
assert booleaness(dynamic(type)) == :maybe_both
1237+
end
1238+
1239+
for type <- [atom([false]), negation(atom([true]))] do
1240+
assert booleaness(type) == :maybe_false
1241+
assert booleaness(dynamic(type)) == :maybe_false
1242+
end
1243+
1244+
for type <- [atom([true]), negation(atom([false]))] do
1245+
assert booleaness(type) == :maybe_true
1246+
assert booleaness(dynamic(type)) == :maybe_true
12431247
end
12441248
end
12451249

0 commit comments

Comments
 (0)