Skip to content

Commit c603505

Browse files
samwgoldmanFacebook Github Bot
authored and
Facebook Github Bot
committed
Expose EmptyT as type annotation empty
Summary: A few people on GitHub have come up with hacky ways to mimic this type, like `string & number`, but they aren't quite the same. I think the utility here is pretty marginal, but I'm confident that exposing this type is at least neutral and should not have any negative effects. Until reachability lands, `empty` can verify that Flow is convinced of exhaustiveness. ``` function exhaust(x: number | string) { if (typeof x === "number") { // do stuff } else if (typeof x === "string") { // do different stuff } else { // only true if we handled all cases (x: empty); } } ``` I considered that `empty` might confound/confuse poly instantiation, for example by satisfying a generic type in a way that breaks parametricity. Well, kind of, but you need to use `declare var` ``` function f<T>(): T { declare var x: empty; return x; } ``` and of course the same trick would work with `declare var x: T`, so I think we're OK. Without `declare var`, we can devise a function that passes local inference, but is uncallable. ``` function f<T>(x: empty): T { return x; } f(); // nothing to pass... ``` Reviewed By: avikchaudhuri Differential Revision: D3979445 fbshipit-source-id: 911d70dbf7159968d70e7c56d55b9aba4df41e71
1 parent 0223ff2 commit c603505

File tree

7 files changed

+30
-20
lines changed

7 files changed

+30
-20
lines changed

Diff for: src/common/reason.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ let rec string_of_desc = function
346346
| RString -> "string"
347347
| RBoolean -> "boolean"
348348
| RMixed -> "mixed"
349-
| REmpty -> ""
349+
| REmpty -> "empty"
350350
| RAny -> "any"
351351
| RVoid -> "undefined"
352352
| RNull -> "null"

Diff for: src/parser/estree_translator.ml

+3
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,7 @@ end with type t = Impl.t) = struct
919919
match t with
920920
| Any -> any_type loc
921921
| Mixed -> mixed_type loc
922+
| Empty -> empty_type loc
922923
| Void -> void_type loc
923924
| Null -> null_type loc
924925
| Number -> number_type loc
@@ -943,6 +944,8 @@ end with type t = Impl.t) = struct
943944

944945
and mixed_type loc = node "MixedTypeAnnotation" loc [||]
945946

947+
and empty_type loc = node "EmptyTypeAnnotation" loc [||]
948+
946949
and void_type loc = node "VoidTypeAnnotation" loc [||]
947950

948951
and null_type loc = node "NullTypeAnnotation" loc [||]

Diff for: src/parser/lexer_flow.mll

+3
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ module Token = struct
136136
(* Type primitives *)
137137
| T_ANY_TYPE
138138
| T_MIXED_TYPE
139+
| T_EMPTY_TYPE
139140
| T_BOOLEAN_TYPE
140141
| T_NUMBER_TYPE
141142
| T_NUMBER_SINGLETON_TYPE of number_type * float
@@ -277,6 +278,7 @@ module Token = struct
277278
(* Type primitives *)
278279
| T_ANY_TYPE -> "T_ANY_TYPE"
279280
| T_MIXED_TYPE -> "T_MIXED_TYPE"
281+
| T_EMPTY_TYPE -> "T_EMPTY_TYPE"
280282
| T_BOOLEAN_TYPE -> "T_BOOLEAN_TYPE"
281283
| T_NUMBER_TYPE -> "T_NUMBER_TYPE"
282284
| T_NUMBER_SINGLETON_TYPE _ -> "T_NUMBER_SINGLETON_TYPE"
@@ -728,6 +730,7 @@ end
728730
"typeof", T_TYPEOF;
729731
"any", T_ANY_TYPE;
730732
"mixed", T_MIXED_TYPE;
733+
"empty", T_EMPTY_TYPE;
731734
"bool", T_BOOLEAN_TYPE;
732735
"boolean", T_BOOLEAN_TYPE;
733736
"true", T_TRUE;

Diff for: src/parser/parser_flow.ml

+1
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ end = struct
260260
and primitive = function
261261
| T_ANY_TYPE -> Some Type.Any
262262
| T_MIXED_TYPE -> Some Type.Mixed
263+
| T_EMPTY_TYPE -> Some Type.Empty
263264
| T_BOOLEAN_TYPE -> Some Type.Boolean
264265
| T_NUMBER_TYPE -> Some Type.Number
265266
| T_STRING_TYPE -> Some Type.String

Diff for: src/parser/spider_monkey_ast.ml

+1
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ and Type : sig
152152
and t' =
153153
| Any
154154
| Mixed
155+
| Empty
155156
| Void
156157
| Null
157158
| Number

Diff for: src/typing/type_annotation.ml

+2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ let rec convert cx tparams_map = Ast.Type.(function
5555

5656
| loc, Mixed -> MixedT.at loc
5757

58+
| loc, Empty -> EmptyT.at loc
59+
5860
| loc, Void -> VoidT.at loc
5961

6062
| loc, Null -> NullT.at loc

Diff for: tests/dump-types/dump-types.exp

+19-19
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@
225225
"end":18
226226
},
227227
{
228-
"type":"(x: ) => ",
228+
"type":"(x: empty) => empty",
229229
"reasons":[],
230230
"loc":{
231231
"source":"test.js",
@@ -240,7 +240,7 @@
240240
"end":20
241241
},
242242
{
243-
"type":"",
243+
"type":"empty",
244244
"reasons":[],
245245
"loc":{
246246
"source":"test.js",
@@ -255,7 +255,7 @@
255255
"end":22
256256
},
257257
{
258-
"type":"",
258+
"type":"empty",
259259
"reasons":[],
260260
"loc":{
261261
"source":"test.js",
@@ -555,7 +555,7 @@
555555
"end":50
556556
},
557557
{
558-
"desc":"",
558+
"desc":"empty",
559559
"loc":{
560560
"source":"test.js",
561561
"type":"SourceFile",
@@ -569,7 +569,7 @@
569569
"end":50
570570
},
571571
{
572-
"desc":"",
572+
"desc":"empty",
573573
"loc":{
574574
"source":"test.js",
575575
"type":"SourceFile",
@@ -583,7 +583,7 @@
583583
"end":50
584584
},
585585
{
586-
"desc":"",
586+
"desc":"empty",
587587
"loc":{
588588
"source":"test.js",
589589
"type":"SourceFile",
@@ -597,7 +597,7 @@
597597
"end":50
598598
},
599599
{
600-
"desc":"",
600+
"desc":"empty",
601601
"loc":{
602602
"source":"test.js",
603603
"type":"SourceFile",
@@ -754,7 +754,7 @@
754754
"end":34
755755
},
756756
{
757-
"desc":"",
757+
"desc":"empty",
758758
"loc":{
759759
"source":"test.js",
760760
"type":"SourceFile",
@@ -1838,8 +1838,8 @@
18381838
"end":18
18391839
},
18401840
{
1841-
"raw_type":"{\n \"reason\":{\n \"pos\":{\n \"source\":null,\n \"type\":null,\n \"start\":{\"line\":0,\"column\":1,\"offset\":0},\n \"end\":{\"line\":0,\"column\":0,\"offset\":0}\n },\n \"desc\":\"function\"\n },\n \"kind\":\"FunT\",\n \"static\":{\n \"reason\":{\n \"pos\":{\n \"source\":null,\n \"type\":null,\n \"start\":{\"line\":0,\"column\":1,\"offset\":0},\n \"end\":{\"line\":0,\"column\":0,\"offset\":0}\n },\n \"desc\":\"statics of function\"\n },\n \"kind\":\"AnyFunT\"\n },\n \"prototype\":{\n \"reason\":{\n \"pos\":{\n \"source\":null,\n \"type\":null,\n \"start\":{\"line\":0,\"column\":1,\"offset\":0},\n \"end\":{\"line\":0,\"column\":0,\"offset\":0}\n },\n \"desc\":\"empty prototype object\"\n },\n \"kind\":\"MixedT\"\n },\n \"funType\":{\n \"thisType\":{\n \"reason\":{\n \"pos\":{\n \"source\":null,\n \"type\":null,\n \"start\":{\"line\":0,\"column\":1,\"offset\":0},\n \"end\":{\"line\":0,\"column\":0,\"offset\":0}\n },\n \"desc\":\"global object\"\n },\n \"kind\":\"MixedT\"\n },\n \"paramTypes\":[\n {\n \"reason\":{\n \"pos\":{\n \"source\":null,\n \"type\":null,\n \"start\":{\"line\":0,\"column\":1,\"offset\":0},\n \"end\":{\"line\":0,\"column\":0,\"offset\":0}\n },\n \"desc\":\"\"\n },\n \"kind\":\"EmptyT\"\n }\n ],\n \"paramNames\":[\"x\"],\n \"returnType\":{\n \"reason\":{\n \"pos\":{\n \"source\":null,\n \"type\":null,\n \"start\":{\"line\":0,\"column\":1,\"offset\":0},\n \"end\":{\"line\":0,\"column\":0,\"offset\":0}\n },\n \"desc\":\"\"\n },\n \"kind\":\"EmptyT\"\n },\n \"isPredicate\":false,\n \"closureIndex\":0,\n \"changeset\":{\"vars\":[],\"refis\":[]}\n }\n}",
1842-
"type":"(x: ) => ",
1841+
"raw_type":"{\n \"reason\":{\n \"pos\":{\n \"source\":null,\n \"type\":null,\n \"start\":{\"line\":0,\"column\":1,\"offset\":0},\n \"end\":{\"line\":0,\"column\":0,\"offset\":0}\n },\n \"desc\":\"function\"\n },\n \"kind\":\"FunT\",\n \"static\":{\n \"reason\":{\n \"pos\":{\n \"source\":null,\n \"type\":null,\n \"start\":{\"line\":0,\"column\":1,\"offset\":0},\n \"end\":{\"line\":0,\"column\":0,\"offset\":0}\n },\n \"desc\":\"statics of function\"\n },\n \"kind\":\"AnyFunT\"\n },\n \"prototype\":{\n \"reason\":{\n \"pos\":{\n \"source\":null,\n \"type\":null,\n \"start\":{\"line\":0,\"column\":1,\"offset\":0},\n \"end\":{\"line\":0,\"column\":0,\"offset\":0}\n },\n \"desc\":\"empty prototype object\"\n },\n \"kind\":\"MixedT\"\n },\n \"funType\":{\n \"thisType\":{\n \"reason\":{\n \"pos\":{\n \"source\":null,\n \"type\":null,\n \"start\":{\"line\":0,\"column\":1,\"offset\":0},\n \"end\":{\"line\":0,\"column\":0,\"offset\":0}\n },\n \"desc\":\"global object\"\n },\n \"kind\":\"MixedT\"\n },\n \"paramTypes\":[\n {\n \"reason\":{\n \"pos\":{\n \"source\":null,\n \"type\":null,\n \"start\":{\"line\":0,\"column\":1,\"offset\":0},\n \"end\":{\"line\":0,\"column\":0,\"offset\":0}\n },\n \"desc\":\"empty\"\n },\n \"kind\":\"EmptyT\"\n }\n ],\n \"paramNames\":[\"x\"],\n \"returnType\":{\n \"reason\":{\n \"pos\":{\n \"source\":null,\n \"type\":null,\n \"start\":{\"line\":0,\"column\":1,\"offset\":0},\n \"end\":{\"line\":0,\"column\":0,\"offset\":0}\n },\n \"desc\":\"empty\"\n },\n \"kind\":\"EmptyT\"\n },\n \"isPredicate\":false,\n \"closureIndex\":0,\n \"changeset\":{\"vars\":[],\"refis\":[]}\n }\n}",
1842+
"type":"(x: empty) => empty",
18431843
"reasons":[],
18441844
"loc":{
18451845
"source":"test.js",
@@ -1854,8 +1854,8 @@
18541854
"end":20
18551855
},
18561856
{
1857-
"raw_type":"{\n \"reason\":{\n \"pos\":{\n \"source\":null,\n \"type\":null,\n \"start\":{\"line\":0,\"column\":1,\"offset\":0},\n \"end\":{\"line\":0,\"column\":0,\"offset\":0}\n },\n \"desc\":\"\"\n },\n \"kind\":\"EmptyT\"\n}",
1858-
"type":"",
1857+
"raw_type":"{\n \"reason\":{\n \"pos\":{\n \"source\":null,\n \"type\":null,\n \"start\":{\"line\":0,\"column\":1,\"offset\":0},\n \"end\":{\"line\":0,\"column\":0,\"offset\":0}\n },\n \"desc\":\"empty\"\n },\n \"kind\":\"EmptyT\"\n}",
1858+
"type":"empty",
18591859
"reasons":[],
18601860
"loc":{
18611861
"source":"test.js",
@@ -1870,8 +1870,8 @@
18701870
"end":22
18711871
},
18721872
{
1873-
"raw_type":"{\n \"reason\":{\n \"pos\":{\n \"source\":null,\n \"type\":null,\n \"start\":{\"line\":0,\"column\":1,\"offset\":0},\n \"end\":{\"line\":0,\"column\":0,\"offset\":0}\n },\n \"desc\":\"\"\n },\n \"kind\":\"EmptyT\"\n}",
1874-
"type":"",
1873+
"raw_type":"{\n \"reason\":{\n \"pos\":{\n \"source\":null,\n \"type\":null,\n \"start\":{\"line\":0,\"column\":1,\"offset\":0},\n \"end\":{\"line\":0,\"column\":0,\"offset\":0}\n },\n \"desc\":\"empty\"\n },\n \"kind\":\"EmptyT\"\n}",
1874+
"type":"empty",
18751875
"reasons":[],
18761876
"loc":{
18771877
"source":"test.js",
@@ -2173,7 +2173,7 @@
21732173
"end":50
21742174
},
21752175
{
2176-
"desc":"",
2176+
"desc":"empty",
21772177
"loc":{
21782178
"source":"test.js",
21792179
"type":"SourceFile",
@@ -2187,7 +2187,7 @@
21872187
"end":50
21882188
},
21892189
{
2190-
"desc":"",
2190+
"desc":"empty",
21912191
"loc":{
21922192
"source":"test.js",
21932193
"type":"SourceFile",
@@ -2201,7 +2201,7 @@
22012201
"end":50
22022202
},
22032203
{
2204-
"desc":"",
2204+
"desc":"empty",
22052205
"loc":{
22062206
"source":"test.js",
22072207
"type":"SourceFile",
@@ -2215,7 +2215,7 @@
22152215
"end":50
22162216
},
22172217
{
2218-
"desc":"",
2218+
"desc":"empty",
22192219
"loc":{
22202220
"source":"test.js",
22212221
"type":"SourceFile",
@@ -2374,7 +2374,7 @@
23742374
"end":34
23752375
},
23762376
{
2377-
"desc":"",
2377+
"desc":"empty",
23782378
"loc":{
23792379
"source":"test.js",
23802380
"type":"SourceFile",

0 commit comments

Comments
 (0)