Skip to content

Commit 2d8eb17

Browse files
michalmuskalameta-codesync[bot]
authored andcommitted
Flatten remote unions too
Summary: This changes how unions are flattened, to also eagerly flatten remote unions. This already was done for local unions, but remote unions weren't considered, making the operation inconsistent This impacts 2 places: * How "unit" lists are typed - this allows `[X]` where `X :: boolean()` to typecheck with `[true] | [false]`. * How some errors with unions are reported - as you can see in changed tests While the error reporting with expanded unions for types like boolean looks a bit silly, in general I think it's more useful since you don't need to go look up type alias definitions when debugging the errors. We also simplify the flatten operation - since D85340363, by construction, unions can't contain `NoneType` and they won't ever be empty. Reviewed By: TD5 Differential Revision: D85669551 fbshipit-source-id: 4f88ae72dc8746c6cac8558e59c265378f647ab3
1 parent 4fe43a6 commit 2d8eb17

File tree

6 files changed

+214
-171
lines changed

6 files changed

+214
-171
lines changed

crates/elp/src/resources/test/eqwalizer_tests/check/custom-OTP-26.pretty

Lines changed: 61 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,7 @@ Context expected type: fun((number()) -> boolean() | {'true', term()})
811811
Because in the expression's type:
812812
fun((binary()) ->
813813
Here the type is: [number()]
814-
Context expects type: boolean() | {'true', term()}
814+
Context expects type: 'false' | 'true' | {'true', term()}
815815
No candidate matches in the expected union.
816816
)
817817

@@ -821,7 +821,7 @@ Because in the expression's type:
821821
because
822822
[number()] is not compatible with boolean() | {'true', term()}
823823
because
824-
[number()] is not compatible with boolean()
824+
[number()] is not compatible with 'false'
825825

826826
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
827827
┌─ check/src/custom.erl:739:20
@@ -834,9 +834,16 @@ Expression has type: 'wrong_ret'
834834
Context expected type: boolean() | {'true', term()}
835835
836836

837+
Because in the expression's type:
838+
Here the type is: 'wrong_ret'
839+
Context expects type: 'false' | 'true' | {'true', term()}
840+
No candidate matches in the expected union.
841+
842+
------------------------------ Detailed message ------------------------------
843+
837844
'wrong_ret' is not compatible with boolean() | {'true', term()}
838845
because
839-
'wrong_ret' is not compatible with boolean()
846+
'wrong_ret' is not compatible with 'false'
840847

841848
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
842849
┌─ check/src/custom.erl:749:9
@@ -860,15 +867,15 @@ Context expected type: boolean() | {'true', term()}
860867
Because in the expression's type:
861868
Here the type is a union type with some valid candidates: {'true', 'a'}
862869
However the following candidate: 'wrong_ret'
863-
Differs from the expected type: boolean() | {'true', term()}
870+
Differs from the expected type: 'false' | 'true' | {'true', term()}
864871

865872
------------------------------ Detailed message ------------------------------
866873

867874
{'true', 'a'} | 'wrong_ret' is not compatible with boolean() | {'true', term()}
868875
because
869876
'wrong_ret' is not compatible with boolean() | {'true', term()}
870877
because
871-
'wrong_ret' is not compatible with boolean()
878+
'wrong_ret' is not compatible with 'false'
872879

873880
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
874881
┌─ check/src/custom.erl:827:9
@@ -885,7 +892,7 @@ Because in the expression's type:
885892
fun(('a' | 'b') ->
886893
Here the type is a union type with some valid candidates: ['a'] | 'true'
887894
However the following candidate: 'wrong_ret'
888-
Differs from the expected type: boolean() | ['a' | 'b']
895+
Differs from the expected type: 'false' | 'true' | ['a' | 'b']
889896
)
890897

891898
------------------------------ Detailed message ------------------------------
@@ -896,7 +903,7 @@ Because in the expression's type:
896903
because
897904
'wrong_ret' is not compatible with boolean() | ['a' | 'b']
898905
because
899-
'wrong_ret' is not compatible with boolean()
906+
'wrong_ret' is not compatible with 'false'
900907

901908
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
902909
┌─ check/src/custom.erl:829:20
@@ -909,9 +916,16 @@ Expression has type: 'wrong_ret'
909916
Context expected type: boolean() | ['a' | 'b']
910917
911918

919+
Because in the expression's type:
920+
Here the type is: 'wrong_ret'
921+
Context expects type: 'false' | 'true' | ['a' | 'b']
922+
No candidate matches in the expected union.
923+
924+
------------------------------ Detailed message ------------------------------
925+
912926
'wrong_ret' is not compatible with boolean() | ['a' | 'b']
913927
because
914-
'wrong_ret' is not compatible with boolean()
928+
'wrong_ret' is not compatible with 'false'
915929

916930
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
917931
┌─ check/src/custom.erl:837:9
@@ -927,7 +941,7 @@ Because in the expression's type:
927941
fun((dynamic()) ->
928942
Here the type is a union type with some valid candidates: 'true'
929943
However the following candidate: {'true', 'a'}
930-
Differs from the expected type: boolean() | [Item]
944+
Differs from the expected type: 'false' | 'true' | [Item]
931945
)
932946

933947
------------------------------ Detailed message ------------------------------
@@ -937,8 +951,7 @@ Because in the expression's type:
937951
{'true', 'a'} | 'true' is not compatible with boolean() | [Item]
938952
because
939953
{'true', 'a'} is not compatible with boolean() | [Item]
940-
because
941-
{'true', 'a'} is not compatible with boolean()
954+
expected union does not contain any tuple type of size 2
942955

943956
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
944957
┌─ check/src/custom.erl:837:20
@@ -951,9 +964,14 @@ Expression has type: {'true', 'a'}
951964
Context expected type: boolean() | [dynamic()]
952965
953966

954-
{'true', 'a'} is not compatible with boolean() | [dynamic()]
955-
because
956-
{'true', 'a'} is not compatible with boolean()
967+
Because in the expression's type:
968+
Here the type is: {'true', 'a'}
969+
Context expects type: 'false' | 'true' | [dynamic()]
970+
No candidate matches in the expected union.
971+
972+
------------------------------ Detailed message ------------------------------
973+
974+
expected union does not contain any tuple type of size 2
957975

958976
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
959977
┌─ check/src/custom.erl:839:9
@@ -1025,7 +1043,7 @@ Because in the expression's type:
10251043
fun(('a' | 'b') ->
10261044
Here the type is a union type with some valid candidates: ['a'] | 'false'
10271045
However the following candidate: {'true', 'a'}
1028-
Differs from the expected type: boolean() | ['a' | 'b']
1046+
Differs from the expected type: 'false' | 'true' | ['a' | 'b']
10291047
)
10301048

10311049
------------------------------ Detailed message ------------------------------
@@ -1035,8 +1053,7 @@ Because in the expression's type:
10351053
['a'] | 'false' | {'true', 'a'} is not compatible with boolean() | ['a' | 'b']
10361054
because
10371055
{'true', 'a'} is not compatible with boolean() | ['a' | 'b']
1038-
because
1039-
{'true', 'a'} is not compatible with boolean()
1056+
expected union does not contain any tuple type of size 2
10401057

10411058
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
10421059
┌─ check/src/custom.erl:857:20
@@ -1049,9 +1066,14 @@ Expression has type: {'true', 'a'}
10491066
Context expected type: boolean() | ['a' | 'b']
10501067
10511068

1052-
{'true', 'a'} is not compatible with boolean() | ['a' | 'b']
1053-
because
1054-
{'true', 'a'} is not compatible with boolean()
1069+
Because in the expression's type:
1070+
Here the type is: {'true', 'a'}
1071+
Context expects type: 'false' | 'true' | ['a' | 'b']
1072+
No candidate matches in the expected union.
1073+
1074+
------------------------------ Detailed message ------------------------------
1075+
1076+
expected union does not contain any tuple type of size 2
10551077

10561078
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
10571079
┌─ check/src/custom.erl:873:9
@@ -1072,7 +1094,7 @@ Because in the expression's type:
10721094
fun(('a' | 'b') ->
10731095
Here the type is a union type with some valid candidates: ['a']
10741096
However the following candidate: 'wrong_ret'
1075-
Differs from the expected type: boolean() | ['a' | 'b']
1097+
Differs from the expected type: 'false' | 'true' | ['a' | 'b']
10761098
)
10771099

10781100
------------------------------ Detailed message ------------------------------
@@ -1083,7 +1105,7 @@ Because in the expression's type:
10831105
because
10841106
'wrong_ret' is not compatible with boolean() | ['a' | 'b']
10851107
because
1086-
'wrong_ret' is not compatible with boolean()
1108+
'wrong_ret' is not compatible with 'false'
10871109

10881110
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
10891111
┌─ check/src/custom.erl:881:17
@@ -1099,15 +1121,15 @@ Context expected type: boolean() | ['a' | 'b']
10991121
Because in the expression's type:
11001122
Here the type is a union type with some valid candidates: ['a']
11011123
However the following candidate: 'wrong_ret'
1102-
Differs from the expected type: boolean() | ['a' | 'b']
1124+
Differs from the expected type: 'false' | 'true' | ['a' | 'b']
11031125

11041126
------------------------------ Detailed message ------------------------------
11051127

11061128
['a'] | 'wrong_ret' is not compatible with boolean() | ['a' | 'b']
11071129
because
11081130
'wrong_ret' is not compatible with boolean() | ['a' | 'b']
11091131
because
1110-
'wrong_ret' is not compatible with boolean()
1132+
'wrong_ret' is not compatible with 'false'
11111133

11121134
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
11131135
┌─ check/src/custom.erl:891:9
@@ -1123,7 +1145,7 @@ Context expected type: fun((dynamic()) -> boolean() | [dynamic()])
11231145
Because in the expression's type:
11241146
fun((string()) ->
11251147
Here the type is: atom()
1126-
Context expects type: boolean() | [dynamic()]
1148+
Context expects type: 'false' | 'true' | [dynamic()]
11271149
No candidate matches in the expected union.
11281150
)
11291151

@@ -1133,7 +1155,7 @@ Because in the expression's type:
11331155
because
11341156
atom() is not compatible with boolean() | [dynamic()]
11351157
because
1136-
atom() is not compatible with boolean()
1158+
atom() is not compatible with 'false'
11371159

11381160
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
11391161
┌─ check/src/custom.erl:891:9
@@ -1149,7 +1171,7 @@ Context expected type: fun(('a' | 'b') -> boolean() | ['a' | 'b'])
11491171
Because in the expression's type:
11501172
fun((string()) ->
11511173
Here the type is: atom()
1152-
Context expects type: boolean() | ['a' | 'b']
1174+
Context expects type: 'false' | 'true' | ['a' | 'b']
11531175
No candidate matches in the expected union.
11541176
)
11551177

@@ -1159,7 +1181,7 @@ Because in the expression's type:
11591181
because
11601182
atom() is not compatible with boolean() | ['a' | 'b']
11611183
because
1162-
atom() is not compatible with boolean()
1184+
atom() is not compatible with 'false'
11631185

11641186
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
11651187
┌─ check/src/custom.erl:900:9
@@ -2921,9 +2943,16 @@ Expression has type: 'err'
29212943
Context expected type: boolean() | {'true', term()}
29222944
29232945

2946+
Because in the expression's type:
2947+
Here the type is: 'err'
2948+
Context expects type: 'false' | 'true' | {'true', term()}
2949+
No candidate matches in the expected union.
2950+
2951+
------------------------------ Detailed message ------------------------------
2952+
29242953
'err' is not compatible with boolean() | {'true', term()}
29252954
because
2926-
'err' is not compatible with boolean()
2955+
'err' is not compatible with 'false'
29272956

29282957
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
29292958
┌─ check/src/custom.erl:2362:5
@@ -2987,13 +3016,14 @@ Context expected type: iodata() | unicode:charlist()
29873016

29883017
Because in the expression's type:
29893018
Here the type is: atom()
2990-
Context expects type: iodata()
3019+
Context expects type: iolist() | binary()
3020+
No candidate matches in the expected union.
29913021

29923022
------------------------------ Detailed message ------------------------------
29933023

29943024
atom() is not compatible with iodata() | unicode:charlist()
29953025
because
2996-
atom() is not compatible with iodata()
3026+
atom() is not compatible with iolist()
29973027

29983028
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
29993029
┌─ check/src/custom.erl:2386:5

0 commit comments

Comments
 (0)