Skip to content

Commit f8cc99a

Browse files
committed
Clean up
1 parent 9335d89 commit f8cc99a

1 file changed

Lines changed: 93 additions & 63 deletions

File tree

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

Lines changed: 93 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -2469,8 +2469,8 @@ defmodule Module.Types.Descr do
24692469

24702470
defp list_leaf_intersection(bdd_leaf(list1, last1), bdd_leaf(list2, last2)) do
24712471
try do
2472-
list = non_empty_intersection!(list1, list2)
2473-
last = non_empty_intersection!(last1, last2)
2472+
list = non_empty_intersection!(list1, list2, &opt_intersection/2)
2473+
last = non_empty_intersection!(last1, last2, &opt_intersection/2)
24742474
bdd_leaf_new(list, last)
24752475
catch
24762476
:empty -> :bdd_bot
@@ -3029,18 +3029,18 @@ defmodule Module.Types.Descr do
30293029
defp map_union(bdd1, bdd2), do: bdd_union(bdd1, bdd2)
30303030

30313031
defp opt_map_union(bdd_leaf(tag1, fields1), bdd_leaf(tag2, fields2)) do
3032-
case maybe_optimize_map_union(tag1, fields1, tag2, fields2) do
3032+
case opt_map_union(tag1, fields1, tag2, fields2) do
30333033
{tag, fields} -> bdd_leaf_new(tag, fields)
30343034
nil -> bdd_union(bdd_leaf_new(tag1, fields1), bdd_leaf_new(tag2, fields2))
30353035
end
30363036
end
30373037

30383038
defp opt_map_union(bdd1, bdd2), do: map_union(bdd1, bdd2)
30393039

3040-
defp maybe_optimize_map_union(:open, [], _, _), do: {:open, @fields_new}
3041-
defp maybe_optimize_map_union(_, _, :open, []), do: {:open, @fields_new}
3040+
defp opt_map_union(:open, [], _, _), do: {:open, @fields_new}
3041+
defp opt_map_union(_, _, :open, []), do: {:open, @fields_new}
30423042

3043-
defp maybe_optimize_map_union(tag1, pos1, tag2, pos2)
3043+
defp opt_map_union(tag1, pos1, tag2, pos2)
30443044
when is_atom(tag1) and is_atom(tag2) do
30453045
case map_union_strategy(pos1, pos2, tag1, tag2, :all_equal) do
30463046
:all_equal when tag1 == :open -> {tag1, pos1}
@@ -3052,7 +3052,7 @@ defmodule Module.Types.Descr do
30523052
end
30533053
end
30543054

3055-
defp maybe_optimize_map_union(_, _, _, _), do: nil
3055+
defp opt_map_union(_, _, _, _), do: nil
30563056

30573057
defp map_union_strategy([{k1, _} | t1], [{k2, _} | _] = l2, tag1, tag2, status)
30583058
when k1 < k2 do
@@ -3198,7 +3198,7 @@ defmodule Module.Types.Descr do
31983198

31993199
defp map_leaf_intersection(bdd_leaf(tag1, fields1), bdd_leaf(tag2, fields2)) do
32003200
try do
3201-
{tag, fields} = map_literal_intersection(tag1, fields1, tag2, fields2)
3201+
{tag, fields} = map_literal_intersection(tag1, fields1, tag2, fields2, &opt_intersection/2)
32023202
bdd_leaf_new(tag, fields)
32033203
catch
32043204
:empty -> :bdd_bot
@@ -3285,10 +3285,12 @@ defmodule Module.Types.Descr do
32853285

32863286
# Intersects two map literals; throws if their intersection is empty.
32873287
# Both open: the result is open.
3288-
defp map_literal_intersection(:open, map1, :open, map2) do
3288+
defp map_literal_intersection(tag1, map1, tag2, map2, intersection_fun \\ &bare_intersection/2)
3289+
3290+
defp map_literal_intersection(:open, map1, :open, map2, intersection_fun) do
32893291
new_fields =
32903292
fields_merge(
3291-
fn _, type1, type2 -> non_empty_intersection!(type1, type2) end,
3293+
fn _, type1, type2 -> non_empty_intersection!(type1, type2, intersection_fun) end,
32923294
map1,
32933295
map2
32943296
)
@@ -3297,21 +3299,21 @@ defmodule Module.Types.Descr do
32973299
end
32983300

32993301
# Both closed: the result is closed.
3300-
defp map_literal_intersection(:closed, map1, :closed, map2) do
3301-
{:closed, map_literal_intersection_closed(map1, map2)}
3302+
defp map_literal_intersection(:closed, map1, :closed, map2, intersection_fun) do
3303+
{:closed, map_literal_intersection_closed(map1, map2, intersection_fun)}
33023304
end
33033305

33043306
# Open and closed: result is closed, all fields from open should be in closed, except not_set ones.
3305-
defp map_literal_intersection(:open, open, :closed, closed) do
3306-
{:closed, map_literal_intersection_open_closed(open, closed)}
3307+
defp map_literal_intersection(:open, open, :closed, closed, intersection_fun) do
3308+
{:closed, map_literal_intersection_open_closed(open, closed, intersection_fun)}
33073309
end
33083310

3309-
defp map_literal_intersection(:closed, closed, :open, open) do
3310-
{:closed, map_literal_intersection_open_closed(open, closed)}
3311+
defp map_literal_intersection(:closed, closed, :open, open, intersection_fun) do
3312+
{:closed, map_literal_intersection_open_closed(open, closed, intersection_fun)}
33113313
end
33123314

33133315
# At least one tag is a tag-domain pair.
3314-
defp map_literal_intersection(tag_or_domains1, map1, tag_or_domains2, map2) do
3316+
defp map_literal_intersection(tag_or_domains1, map1, tag_or_domains2, map2, intersection_fun) do
33153317
# For a closed map with domains intersected with an open map with domains:
33163318
# 1. The result is closed (more restrictive)
33173319
# 2. We need to check each domain in the open map against the closed map
@@ -3329,7 +3331,7 @@ defmodule Module.Types.Descr do
33293331
# using default values when a key is not present.
33303332
{tag_or_domains,
33313333
fields_merge_with_defaults(map1, default1, map2, default2, fn _key, v1, v2 ->
3332-
non_empty_intersection!(v1, v2)
3334+
non_empty_intersection!(v1, v2, intersection_fun)
33333335
end)}
33343336
end
33353337

@@ -3367,52 +3369,62 @@ defmodule Module.Types.Descr do
33673369

33683370
defp map_domain_intersection_fields(_, _), do: []
33693371

3370-
defp map_literal_intersection_open_closed([{k1, v1} | t1], [{k2, _} | _] = l2) when k1 < k2 do
3372+
defp map_literal_intersection_open_closed([{k1, v1} | t1], [{k2, _} | _] = l2, intersection_fun)
3373+
when k1 < k2 do
33713374
# If the type in the open map is optional, we continue
33723375
case v1 do
3373-
%{optional: 1} -> map_literal_intersection_open_closed(t1, l2)
3376+
%{optional: 1} -> map_literal_intersection_open_closed(t1, l2, intersection_fun)
33743377
_ -> throw(:empty)
33753378
end
33763379
end
33773380

3378-
defp map_literal_intersection_open_closed([{k1, _} | _] = l1, [{k2, v2} | t2]) when k1 > k2 do
3381+
defp map_literal_intersection_open_closed([{k1, _} | _] = l1, [{k2, v2} | t2], intersection_fun)
3382+
when k1 > k2 do
33793383
# Anything in the closed map not in open is preserved
3380-
[{k2, v2} | map_literal_intersection_open_closed(l1, t2)]
3384+
[{k2, v2} | map_literal_intersection_open_closed(l1, t2, intersection_fun)]
33813385
end
33823386

3383-
defp map_literal_intersection_open_closed([{key, v1} | t1], [{_, v2} | t2]) do
3384-
[{key, non_empty_intersection!(v1, v2)} | map_literal_intersection_open_closed(t1, t2)]
3387+
defp map_literal_intersection_open_closed([{key, v1} | t1], [{_, v2} | t2], intersection_fun) do
3388+
[
3389+
{key, non_empty_intersection!(v1, v2, intersection_fun)}
3390+
| map_literal_intersection_open_closed(t1, t2, intersection_fun)
3391+
]
33853392
end
33863393

3387-
defp map_literal_intersection_open_closed(t1, t2) do
3394+
defp map_literal_intersection_open_closed(t1, t2, _intersection_fun) do
33883395
if Enum.all?(t1, fn {_, v} -> match?(%{optional: 1}, v) end) do
33893396
t2
33903397
else
33913398
throw(:empty)
33923399
end
33933400
end
33943401

3395-
defp map_literal_intersection_closed([{k1, v1} | t1], [{k2, _} | _] = l2) when k1 < k2 do
3402+
defp map_literal_intersection_closed([{k1, v1} | t1], [{k2, _} | _] = l2, intersection_fun)
3403+
when k1 < k2 do
33963404
if is_optional_static(v1) do
3397-
map_literal_intersection_closed(t1, l2)
3405+
map_literal_intersection_closed(t1, l2, intersection_fun)
33983406
else
33993407
throw(:empty)
34003408
end
34013409
end
34023410

3403-
defp map_literal_intersection_closed([{k1, _} | _] = l1, [{k2, v2} | t2]) when k1 > k2 do
3411+
defp map_literal_intersection_closed([{k1, _} | _] = l1, [{k2, v2} | t2], intersection_fun)
3412+
when k1 > k2 do
34043413
if is_optional_static(v2) do
3405-
map_literal_intersection_closed(l1, t2)
3414+
map_literal_intersection_closed(l1, t2, intersection_fun)
34063415
else
34073416
throw(:empty)
34083417
end
34093418
end
34103419

3411-
defp map_literal_intersection_closed([{key, v1} | t1], [{_, v2} | t2]) do
3412-
[{key, non_empty_intersection!(v1, v2)} | map_literal_intersection_closed(t1, t2)]
3420+
defp map_literal_intersection_closed([{key, v1} | t1], [{_, v2} | t2], intersection_fun) do
3421+
[
3422+
{key, non_empty_intersection!(v1, v2, intersection_fun)}
3423+
| map_literal_intersection_closed(t1, t2, intersection_fun)
3424+
]
34133425
end
34143426

3415-
defp map_literal_intersection_closed(t1, t2) do
3427+
defp map_literal_intersection_closed(t1, t2, _intersection_fun) do
34163428
if Enum.any?(t1, fn {_, v} -> not is_optional_static(v) end) or
34173429
Enum.any?(t2, fn {_, v} -> not is_optional_static(v) end) do
34183430
throw(:empty)
@@ -3421,8 +3433,8 @@ defmodule Module.Types.Descr do
34213433
[]
34223434
end
34233435

3424-
defp non_empty_intersection!(type1, type2) do
3425-
type = opt_intersection(type1, type2)
3436+
defp non_empty_intersection!(type1, type2, intersection_fun) do
3437+
type = intersection_fun.(type1, type2)
34263438
if empty?(type), do: throw(:empty), else: type
34273439
end
34283440

@@ -4481,10 +4493,10 @@ defmodule Module.Types.Descr do
44814493
{[], [], nil, to_domain_keys(key_descr), []}
44824494
end
44834495

4484-
defp non_empty_map_literals_intersection(maps) do
4496+
defp non_empty_map_literals_intersection(maps, intersection_fun \\ &bare_intersection/2) do
44854497
try do
44864498
Enum.reduce(maps, {:open, []}, fn bdd_leaf(next_tag, next_fields), {tag, fields} ->
4487-
map_literal_intersection(tag, fields, next_tag, next_fields)
4499+
map_literal_intersection(tag, fields, next_tag, next_fields, intersection_fun)
44884500
end)
44894501
catch
44904502
:empty -> :empty
@@ -4589,8 +4601,8 @@ defmodule Module.Types.Descr do
45894601
end
45904602

45914603
defp map_line_meet_empty?(key, type, neg_type, t1, t2, tag, neg_tag, acc_meet, negs) do
4592-
diff = opt_difference(type, neg_type)
4593-
meet = opt_intersection(type, neg_type)
4604+
diff = bare_difference(type, neg_type)
4605+
meet = bare_intersection(type, neg_type)
45944606

45954607
(empty?(diff) or map_line_empty?(tag, Enum.reverse(acc_meet, [{key, diff} | t1]), negs)) and
45964608
(empty?(meet) or map_line_meet_empty?(t1, t2, tag, neg_tag, [{key, meet} | acc_meet], negs))
@@ -4646,7 +4658,7 @@ defmodule Module.Types.Descr do
46464658
end
46474659

46484660
defp map_line_fields_empty_recur?(key, v1, v2, tag, fields, negs) do
4649-
diff = opt_difference(v1, v2)
4661+
diff = bare_difference(v1, v2)
46504662
empty?(diff) or map_line_empty?(tag, fields_store(key, diff, fields), negs)
46514663
end
46524664

@@ -4877,7 +4889,7 @@ defmodule Module.Types.Descr do
48774889
{tag1, fields1, []} = map
48784890
{tag2, fields2, []} = candidate
48794891

4880-
case maybe_optimize_map_union(tag1, fields1, tag2, fields2) do
4892+
case opt_map_union(tag1, fields1, tag2, fields2) do
48814893
nil -> [candidate | map_fuse_with_first_fusible(map, rest)]
48824894
# we found a fusible candidate, we're done
48834895
{tag, fields} -> [{tag, fields, []} | rest]
@@ -5149,20 +5161,26 @@ defmodule Module.Types.Descr do
51495161
do: bdd_intersection(bdd1, bdd2, &tuple_leaf_intersection/2)
51505162

51515163
defp tuple_leaf_intersection(bdd_leaf(tag1, elements1), bdd_leaf(tag2, elements2)) do
5152-
case tuple_literal_intersection(tag1, elements1, tag2, elements2) do
5164+
case tuple_literal_intersection(tag1, elements1, tag2, elements2, &opt_intersection/2) do
51535165
{tag, elements} -> bdd_leaf_new(tag, elements)
51545166
:empty -> :bdd_bot
51555167
end
51565168
end
51575169

5158-
defp tuple_literal_intersection(tag1, elements1, tag2, elements2) do
5170+
defp tuple_literal_intersection(
5171+
tag1,
5172+
elements1,
5173+
tag2,
5174+
elements2,
5175+
intersection_fun
5176+
) do
51595177
case tuple_sizes_strategy(tag1, length(elements1), tag2, length(elements2)) do
51605178
:disjoint ->
51615179
:empty
51625180

51635181
_ ->
51645182
try do
5165-
zip_non_empty_intersection!(elements1, elements2, [])
5183+
zip_non_empty_intersection!(elements1, elements2, [], intersection_fun)
51665184
catch
51675185
:empty -> :empty
51685186
else
@@ -5173,18 +5191,26 @@ defmodule Module.Types.Descr do
51735191
end
51745192

51755193
# Intersects two lists of types, and _appends_ the extra elements to the result.
5176-
defp zip_non_empty_intersection!([], types2, acc), do: Enum.reverse(acc, types2)
5177-
defp zip_non_empty_intersection!(types1, [], acc), do: Enum.reverse(acc, types1)
5178-
5179-
defp zip_non_empty_intersection!([type1 | rest1], [type2 | rest2], acc) do
5180-
zip_non_empty_intersection!(rest1, rest2, [non_empty_intersection!(type1, type2) | acc])
5194+
defp zip_non_empty_intersection!([], types2, acc, _intersection_fun),
5195+
do: Enum.reverse(acc, types2)
5196+
5197+
defp zip_non_empty_intersection!(types1, [], acc, _intersection_fun),
5198+
do: Enum.reverse(acc, types1)
5199+
5200+
defp zip_non_empty_intersection!([type1 | rest1], [type2 | rest2], acc, intersection_fun) do
5201+
zip_non_empty_intersection!(
5202+
rest1,
5203+
rest2,
5204+
[non_empty_intersection!(type1, type2, intersection_fun) | acc],
5205+
intersection_fun
5206+
)
51815207
end
51825208

51835209
defp zip_empty_intersection?([], _types2), do: false
51845210
defp zip_empty_intersection?(_types1, []), do: false
51855211

51865212
defp zip_empty_intersection?([type1 | rest1], [type2 | rest2]) do
5187-
case empty?(opt_intersection(type1, type2)) do
5213+
case empty?(bare_intersection(type1, type2)) do
51885214
true -> true
51895215
false -> zip_empty_intersection?(rest1, rest2)
51905216
end
@@ -5234,7 +5260,7 @@ defmodule Module.Types.Descr do
52345260
if subtype?, do: :subtype, else: :none
52355261
end
52365262

5237-
defp non_empty_tuple_literals_intersection(tuples) do
5263+
defp non_empty_tuple_literals_intersection(tuples, intersection_fun \\ &bare_intersection/2) do
52385264
try do
52395265
Enum.reduce(tuples, {:open, []}, fn bdd_leaf(tag1, elements1), {tag2, elements2} ->
52405266
case tuple_sizes_strategy(tag1, length(elements1), tag2, length(elements2)) do
@@ -5243,7 +5269,7 @@ defmodule Module.Types.Descr do
52435269

52445270
_ ->
52455271
tag = if tag1 == :open and tag2 == :open, do: :open, else: :closed
5246-
{tag, zip_intersection(elements1, elements2, [])}
5272+
{tag, zip_intersection(elements1, elements2, [], intersection_fun)}
52475273
end
52485274
end)
52495275
catch
@@ -5258,11 +5284,11 @@ defmodule Module.Types.Descr do
52585284
end
52595285
end
52605286

5261-
defp zip_intersection([], types2, acc), do: Enum.reverse(acc, types2)
5262-
defp zip_intersection(types1, [], acc), do: Enum.reverse(acc, types1)
5287+
defp zip_intersection([], types2, acc, _intersection_fun), do: Enum.reverse(acc, types2)
5288+
defp zip_intersection(types1, [], acc, _intersection_fun), do: Enum.reverse(acc, types1)
52635289

5264-
defp zip_intersection([type1 | rest1], [type2 | rest2], acc) do
5265-
zip_intersection(rest1, rest2, [opt_intersection(type1, type2) | acc])
5290+
defp zip_intersection([type1 | rest1], [type2 | rest2], acc, intersection_fun) do
5291+
zip_intersection(rest1, rest2, [intersection_fun.(type1, type2) | acc], intersection_fun)
52665292
end
52675293

52685294
defp tuple_empty?(bdd) do
@@ -5306,8 +5332,8 @@ defmodule Module.Types.Descr do
53065332
defp tuple_elements_empty?(acc_meet, tag, elements, [neg_type | neg_elements], negs) do
53075333
# Handles the case where {tag, elements} is an open tuple, like {:open, []}
53085334
{ty, elements} = List.pop_at(elements, 0, term())
5309-
diff = opt_difference(ty, neg_type)
5310-
meet = opt_intersection(ty, neg_type)
5335+
diff = bare_difference(ty, neg_type)
5336+
meet = bare_intersection(ty, neg_type)
53115337

53125338
# In this case, there is no intersection between the positive and this negative.
53135339
# So we should just "go next"
@@ -5376,9 +5402,9 @@ defmodule Module.Types.Descr do
53765402
end
53775403

53785404
# ti \ ui (i.e., ti and not ui)
5379-
diff = opt_difference(ty, neg_type)
5405+
diff = bare_difference(ty, neg_type)
53805406
# ti /\ ui
5381-
meet = opt_intersection(ty, neg_type)
5407+
meet = bare_intersection(ty, neg_type)
53825408

53835409
# Branch where the earliest difference is *here*.
53845410
# Earlier positions are the accumulated matches in `acc`;
@@ -5430,13 +5456,17 @@ defmodule Module.Types.Descr do
54305456
defp tuple_union(_, bdd_leaf(:open, []) = leaf), do: leaf
54315457
defp tuple_union(bdd1, bdd2), do: bdd_union(bdd1, bdd2)
54325458

5459+
defp opt_tuple_union({tag1, elements1}, {tag2, elements2}) do
5460+
maybe_optimize_tuple_union({tag1, elements1}, {tag2, elements2})
5461+
end
5462+
54335463
defp opt_tuple_union(
5434-
bdd_leaf(tag1, elements1) = tuple1,
5435-
bdd_leaf(tag2, elements2) = tuple2
5464+
bdd_leaf(tag1, elements1),
5465+
bdd_leaf(tag2, elements2)
54365466
) do
54375467
case maybe_optimize_tuple_union({tag1, elements1}, {tag2, elements2}) do
54385468
{tag, elements} -> bdd_leaf_new(tag, elements)
5439-
nil -> bdd_union(tuple1, tuple2)
5469+
nil -> bdd_union(bdd_leaf_new(tag1, elements1), bdd_leaf_new(tag2, elements2))
54405470
end
54415471
end
54425472

@@ -5590,7 +5620,7 @@ defmodule Module.Types.Descr do
55905620
defp tuple_fuse_with_first_fusible(tuple, []), do: [tuple]
55915621

55925622
defp tuple_fuse_with_first_fusible(tuple, [candidate | rest]) do
5593-
if fused = maybe_optimize_tuple_union(tuple, candidate) do
5623+
if fused = opt_tuple_union(tuple, candidate) do
55945624
# we found a fusible candidate, we're done
55955625
[fused | rest]
55965626
else

0 commit comments

Comments
 (0)