Skip to content

Commit 15e8da4

Browse files
committed
Handle cons in :lists.member/2 types
1 parent 9cc6405 commit 15e8da4

1 file changed

Lines changed: 40 additions & 36 deletions

File tree

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

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -497,50 +497,54 @@ defmodule Module.Types.Apply do
497497
end
498498

499499
defp do_remote(:lists, :member, [arg, list] = args, expected, expr, stack, context, of_fun)
500-
when is_list(list) and list != [] do
501-
case booleaness(expected) do
502-
{polarity, _maybe_or_always} ->
503-
{return, acc} =
504-
case polarity do
505-
true -> {@atom_true, none()}
506-
false -> {@atom_false, term()}
507-
end
500+
when is_list(list) do
501+
if list == [] or Enum.any?(list, &match?({:|, _, [_, _]}, &1)) do
502+
remote_domain(:lists, :member, args, expected, elem(expr, 1), stack, context)
503+
else
504+
case booleaness(expected) do
505+
{polarity, _maybe_or_always} ->
506+
{return, acc} =
507+
case polarity do
508+
true -> {@atom_true, none()}
509+
false -> {@atom_false, term()}
510+
end
508511

509-
{expected, singleton?, context} =
510-
Enum.reduce(list, {acc, true, context}, fn literal, {acc, all_singleton?, context} ->
511-
{type, context} = of_fun.(literal, term(), expr, stack, context)
512+
{expected, singleton?, context} =
513+
Enum.reduce(list, {acc, true, context}, fn literal, {acc, all_singleton?, context} ->
514+
{type, context} = of_fun.(literal, term(), expr, stack, context)
512515

513-
if singleton?(type) do
514-
acc = if polarity, do: union(acc, type), else: intersection(acc, negation(type))
515-
{acc, all_singleton?, context}
516-
else
517-
acc = if polarity, do: union(acc, type), else: acc
518-
{acc, false, context}
519-
end
520-
end)
516+
if singleton?(type) do
517+
acc = if polarity, do: union(acc, type), else: intersection(acc, negation(type))
518+
{acc, all_singleton?, context}
519+
else
520+
acc = if polarity, do: union(acc, type), else: acc
521+
{acc, false, context}
522+
end
523+
end)
521524

522-
{arg_type, context} = of_fun.(arg, expected, expr, stack, context)
525+
{arg_type, context} = of_fun.(arg, expected, expr, stack, context)
523526

524-
cond do
525-
# Return a precise result
526-
singleton? and subtype?(arg_type, expected) ->
527-
{return(return, [arg_type, expected], stack), context}
527+
cond do
528+
# Return a precise result
529+
singleton? and subtype?(arg_type, expected) ->
530+
{return(return, [arg_type, expected], stack), context}
528531

529-
# Singleton types with reverse polarity are negated, so we don't check for disjoint
530-
(singleton? and not polarity) or not is_warning(stack) ->
531-
{return(boolean(), [arg_type, expected], stack), context}
532+
# Singleton types with reverse polarity are negated, so we don't check for disjoint
533+
(singleton? and not polarity) or not is_warning(stack) ->
534+
{return(boolean(), [arg_type, expected], stack), context}
532535

533-
# Nothing in common between left and right, emit a warning
534-
disjoint?(arg_type, expected) ->
535-
error = {:mismatched_comparison, arg_type, list(expected)}
536-
remote_error(error, :lists, :member, 2, expr, stack, context)
536+
# Nothing in common between left and right, emit a warning
537+
disjoint?(arg_type, expected) ->
538+
error = {:mismatched_comparison, arg_type, list(expected)}
539+
remote_error(error, :lists, :member, 2, expr, stack, context)
537540

538-
true ->
539-
{return(boolean(), [arg_type, expected], stack), context}
540-
end
541+
true ->
542+
{return(boolean(), [arg_type, expected], stack), context}
543+
end
541544

542-
_ ->
543-
remote_domain(:lists, :member, args, expected, elem(expr, 1), stack, context)
545+
_ ->
546+
remote_domain(:lists, :member, args, expected, elem(expr, 1), stack, context)
547+
end
544548
end
545549
end
546550

0 commit comments

Comments
 (0)