Skip to content

Commit 9fb8fb1

Browse files
committed
Add comments justifying use of subtyping, closes #15273
1 parent 5a1fa35 commit 9fb8fb1

2 files changed

Lines changed: 15 additions & 10 deletions

File tree

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ defmodule Module.Types.Apply do
393393
case sized_order(name, left, right, expected) do
394394
{arg, expected, precise?, return} ->
395395
{actual, context} = of_fun.(arg, expected, expr, stack, context)
396+
# expected is a static type, so we can use subtype? rather than compatible?
396397
result = if precise? and subtype?(actual, expected), do: return, else: boolean()
397398
{result, context}
398399

@@ -525,9 +526,10 @@ defmodule Module.Types.Apply do
525526
{arg_type, context} = of_fun.(arg, expected, expr, stack, context)
526527

527528
cond do
528-
# Return a precise result
529-
singleton? and subtype?(arg_type, expected) ->
530-
{return(return, [arg_type, expected], stack), context}
529+
# expected can have dynamic terms but, since we have verified
530+
# them to be singletons, we can compute the upper bound.
531+
singleton? and subtype?(arg_type, upper_bound(expected)) ->
532+
{return, context}
531533

532534
# Singleton types with reverse polarity are negated, so we don't check for disjoint
533535
(singleton? and not polarity) or not is_warning(stack) ->
@@ -608,6 +610,8 @@ defmodule Module.Types.Apply do
608610
end
609611

610612
{actual, context} = of_fun.(arg, expected, expr, stack, context)
613+
614+
# expected here is a static type, so subtyping relation is fine
611615
result = if precise? and subtype?(actual, expected), do: return, else: boolean()
612616

613617
# We can skip return compare because literal is always an integer,
@@ -635,7 +639,7 @@ defmodule Module.Types.Apply do
635639
if singleton?(type) do
636640
expected = if polarity, do: type, else: negation(type)
637641
{arg_type, context} = of_fun.(arg, expected, expr, stack, context)
638-
result = if subtype?(arg_type, expected), do: return, else: boolean()
642+
result = if subtype?(arg_type, upper_bound(expected)), do: return, else: boolean()
639643

640644
# Because reverse polarity means we will infer negated types
641645
# (which are naturally disjoint), we skip checks in such cases

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ defmodule Module.Types.Pattern do
1818
defp empty_previous?({[], _}), do: true
1919
defp empty_previous?({[_ | _], _}), do: false
2020

21+
# Previous is always an upper bound (static), so we can use subtype?
2122
defp previous_subtype?(_, {[], _}), do: false
2223
defp previous_subtype?([], _), do: true
2324
defp previous_subtype?(args, {_, descr}), do: subtype?(args_to_previous(args), descr)
@@ -1258,12 +1259,12 @@ defmodule Module.Types.Pattern do
12581259

12591260
defp of_remote(fun, _args, call, expected, stack, context)
12601261
when fun in [:and, :or, :andalso, :orelse] do
1261-
{both_domain, abort_domain, always_rhs?} =
1262+
{boolean, abort_domain, always_rhs?} =
12621263
case fun do
1263-
:andalso -> {@atom_true, @atom_false, false}
1264-
:orelse -> {@atom_false, @atom_true, false}
1265-
:and -> {@atom_true, @atom_false, true}
1266-
:or -> {@atom_false, @atom_true, true}
1264+
:andalso -> {true, @atom_false, false}
1265+
:orelse -> {false, @atom_true, false}
1266+
:and -> {true, @atom_false, true}
1267+
:or -> {false, @atom_true, true}
12671268
end
12681269

12691270
# If we have multiple operations in a row,
@@ -1279,7 +1280,7 @@ defmodule Module.Types.Pattern do
12791280
# only be true if both clauses are executed, so we know the first
12801281
# argument has to be true and the second has to be expected.
12811282
cond do
1282-
is_nil(context.pattern_info) or subtype?(expected, both_domain) ->
1283+
is_nil(context.pattern_info) or booleaness(expected) == {boolean, :always} ->
12831284
of_logical_all([left | right], true, expected, abort_domain, stack, context)
12841285

12851286
right == [] ->

0 commit comments

Comments
 (0)