@@ -196,7 +196,6 @@ defmodule Module.Types.Descr do
196
196
# We emit `{common, union(return, acc_return)}` for the shared part,
197
197
# keep `{left, acc_return}` (if any), and continue inserting `diff`
198
198
# into the remainder of the list to handle further overlaps.
199
-
200
199
defp pivot_overlapping_clause ( domain , return , [ { acc_domain , acc_return } | acc ] ) do
201
200
common = intersection ( domain , acc_domain )
202
201
@@ -1314,7 +1313,7 @@ defmodule Module.Types.Descr do
1314
1313
defp fun_normalize ( % { fun: bdd } , arity , mode ) do
1315
1314
{ domain , arrows , bad_arities } =
1316
1315
Enum . reduce ( fun_get ( bdd ) , { term ( ) , [ ] , [ ] } , fn
1317
- { pos_funs , neg_funs } , { domain , arrows , bad_arities } ->
1316
+ { pos_funs , _neg_funs } , { domain , arrows , bad_arities } ->
1318
1317
arrow_arity =
1319
1318
case pos_funs do
1320
1319
[ { args , _ } | _ ] -> length ( args )
@@ -1325,9 +1324,6 @@ defmodule Module.Types.Descr do
1325
1324
arrow_arity != arity ->
1326
1325
{ domain , arrows , [ arrow_arity | bad_arities ] }
1327
1326
1328
- fun_empty? ( pos_funs , neg_funs ) ->
1329
- { domain , arrows , bad_arities }
1330
-
1331
1327
true ->
1332
1328
# Calculate domain from all positive functions
1333
1329
path_domain =
@@ -1363,13 +1359,13 @@ defmodule Module.Types.Descr do
1363
1359
end )
1364
1360
end
1365
1361
1366
- defp apply_disjoint ( arguments , arrows ) do
1367
- type_args = args_to_domain ( arguments )
1362
+ # A fast way to do function application when the arguments of the function are disjoint.
1363
+ # Just build the union of all the return types of arrows that match the input.
1364
+ defp apply_disjoint ( input_arguments , arrows ) do
1365
+ type_input = args_to_domain ( input_arguments )
1368
1366
1369
1367
Enum . reduce ( arrows , none ( ) , fn { args , ret } , acc_return ->
1370
- dom = args_to_domain ( args )
1371
-
1372
- if empty? ( intersection ( dom , type_args ) ) do
1368
+ if empty? ( intersection ( args_to_domain ( args ) , type_input ) ) do
1373
1369
acc_return
1374
1370
else
1375
1371
union ( acc_return , ret )
@@ -1399,6 +1395,9 @@ defmodule Module.Types.Descr do
1399
1395
# Calculate the part of the input not covered by this arrow's domain
1400
1396
dom_subtract = difference ( input , args_to_domain ( args ) )
1401
1397
1398
+ # Refine the return type by intersecting with this arrow's return type
1399
+ ret_refine = intersection ( returns_reached , ret )
1400
+
1402
1401
# Phase 1: Domain partitioning
1403
1402
# If the input is not fully covered by the arrow's domain, then the result type should be
1404
1403
# _augmented_ with the outputs obtained by applying the remaining arrows to the non-covered
@@ -1418,9 +1417,6 @@ defmodule Module.Types.Descr do
1418
1417
# the same part of the input, then the result type is an intersection of the return types of
1419
1418
# those arrows.
1420
1419
1421
- # Refine the return type by intersecting with this arrow's return type
1422
- ret_refine = intersection ( returns_reached , ret )
1423
-
1424
1420
# e.g. (integer()->atom()) and (integer()->pid()) when applied to integer()
1425
1421
# should result in (atom() ∩ pid()), which is none().
1426
1422
aux_apply ( result , input , ret_refine , arrow_intersections )
@@ -1434,7 +1430,7 @@ defmodule Module.Types.Descr do
1434
1430
defp fun_get ( acc , pos , neg , bdd ) do
1435
1431
case bdd do
1436
1432
:bdd_bot -> acc
1437
- :bdd_top -> [ { pos , neg } | acc ]
1433
+ :bdd_top -> if fun_empty? ( pos , neg ) , do: acc , else: [ { pos , neg } | acc ]
1438
1434
{ fun , left , right } -> fun_get ( fun_get ( acc , [ fun | pos ] , neg , left ) , pos , [ fun | neg ] , right )
1439
1435
end
1440
1436
end
@@ -1451,13 +1447,7 @@ defmodule Module.Types.Descr do
1451
1447
# - `fun(1) and not fun(1)` is empty
1452
1448
# - `fun(integer() -> atom()) and not fun(none() -> term())` is empty
1453
1449
# - `fun(integer() -> atom()) and not fun(atom() -> integer())` is not empty
1454
- defp fun_empty? ( bdd ) do
1455
- case bdd do
1456
- :bdd_bot -> true
1457
- :bdd_top -> false
1458
- bdd -> fun_get ( bdd ) |> Enum . all? ( fn { posits , negats } -> fun_empty? ( posits , negats ) end )
1459
- end
1460
- end
1450
+ defp fun_empty? ( bdd ) , do: fun_get ( bdd ) == [ ]
1461
1451
1462
1452
# Checks if a function type represented by positive and negative function literals is empty.
1463
1453
@@ -1660,6 +1650,8 @@ defmodule Module.Types.Descr do
1660
1650
end
1661
1651
end
1662
1652
1653
+ # Note: using this for functions instead of bdd_intersection because the printing
1654
+ # fun_denormalize relies on the order of functions in the bdd.
1663
1655
defp fun_bdd_intersection ( bdd1 , bdd2 ) do
1664
1656
case { bdd1 , bdd2 } do
1665
1657
# Base cases
@@ -1817,7 +1809,7 @@ defmodule Module.Types.Descr do
1817
1809
end
1818
1810
1819
1811
defp fun_get_pos ( bdd ) do
1820
- for { pos , negs } <- fun_get ( bdd ) , not fun_empty? ( pos , negs ) do
1812
+ for { pos , _negs } <- fun_get ( bdd ) do
1821
1813
fun_filter_subset ( pos , [ ] )
1822
1814
end
1823
1815
end
0 commit comments