-
Notifications
You must be signed in to change notification settings - Fork 1.8k
/
type_sig_merge.ml
1667 lines (1600 loc) · 65.7 KB
/
type_sig_merge.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
(*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open Type_sig
open Type_sig_collections
module Pack = Type_sig_pack
module Option = Base.Option
module Fn = Base.Fn
module Component : sig
type 'a t
type index = private int
val make : 'a Nel.t -> (index -> 'a -> 'b) -> 'b t
val leader : 'a t -> 'a
val get : 'a t -> index -> 'a
val map : ('a -> 'b) -> 'a t -> 'b t
val iter : ('a -> unit) -> 'a t -> unit
val iteri : (index -> 'a -> unit) -> 'a t -> unit
end = struct
type 'a t = 'a array
type index = int
let make (x, xs) f =
let len = 1 + List.length xs in
let component = Array.make len (f 0 x) in
List.iteri (fun i x -> component.(i + 1) <- f (i + 1) x) xs;
component
external get : 'a t -> index -> 'a = "%array_unsafe_get"
let leader xs = get xs 0
let map = Array.map
let iter = Array.iter
let iteri = Array.iteri
end
type file = {
key: File_key.t;
cx: Context.t;
dependencies: (string * (ALoc.t -> Type.t)) Module_refs.t;
exports: unit -> Type.t;
export_def: Type.t Lazy.t option;
local_defs: (unit -> ALoc.t * string * Type.t) Local_defs.t;
remote_refs: (unit -> ALoc.t * string * Type.t) Remote_refs.t;
patterns: Type.t Lazy.t Patterns.t;
pattern_defs: Type.t Lazy.t Pattern_defs.t;
}
let visit f = f ()
let def_reason = function
| TypeAlias { id_loc; name; _ }
| OpaqueType { id_loc; name; _ } ->
Type.DescFormat.type_reason (Reason.OrdinaryName name) id_loc
| Interface { id_loc; name; _ }
| ClassBinding { id_loc; name; _ }
| DeclareClassBinding { id_loc; name; _ } ->
Type.DescFormat.instance_reason (Reason.OrdinaryName name) id_loc
| FunBinding { fn_loc; _ } ->
(* RFunctionType should be Reason.func_reason instead, but this matches the
* behavior of types-first where function bindings are converted to declared
* functions, which are given a RFunctionType reason.
*
* TODO Fix once T71257430 is closed. *)
Reason.(mk_reason RFunctionType fn_loc)
| DeclareFun { id_loc; _ } -> Reason.(mk_reason RFunctionType id_loc)
| Variable { id_loc; name; _ } -> Reason.(mk_reason (RIdentifier (OrdinaryName name)) id_loc)
| DisabledEnumBinding { id_loc; name; _ }
| EnumBinding { id_loc; name; _ } ->
Reason.(mk_reason (REnum name) id_loc)
let remote_ref_reason = function
| Pack.Import { id_loc; name; _ }
| Pack.ImportNs { id_loc; name; _ } ->
Reason.(mk_reason (RIdentifier (OrdinaryName name)) id_loc)
| Pack.ImportType { id_loc; name; _ }
| Pack.ImportTypeof { id_loc; name; _ }
| Pack.ImportTypeofNs { id_loc; name; _ } ->
Type.DescFormat.type_reason (Reason.OrdinaryName name) id_loc
let obj_lit_reason ~frozen loc =
let open Reason in
let desc =
if frozen then
RFrozen RObjectLit
else
RObjectLit
in
mk_reason desc loc
let trust = Trust.bogus_trust ()
let specialize file t =
let open Type in
let open TypeUtil in
let reason = reason_of_t t in
Tvar.mk_derivable_where file.cx reason (fun tout ->
Flow_js.flow file.cx (t, SpecializeT (unknown_use, reason, reason, None, None, tout)))
let eval_unary file loc t =
let module U = Flow_ast.Expression.Unary in
function
| U.Minus ->
let reason = Reason.mk_reason (TypeUtil.desc_of_t t) loc in
Tvar.mk_where file.cx reason (fun tout ->
Flow_js.flow file.cx (t, Type.UnaryMinusT (reason, tout)))
| U.Plus -> Type.NumT.at loc trust
| U.Not ->
let reason = Reason.(mk_reason (RUnaryOperator ("not", TypeUtil.desc_of_t t)) loc) in
Tvar.mk_no_wrap_where file.cx reason (fun tout ->
Flow_js.flow file.cx (t, Type.NotT (reason, tout)))
| U.BitNot -> Type.NumT.at loc trust
| U.Typeof -> Type.StrT.at loc trust
| U.Void -> Type.VoidT.at loc trust
| U.Delete -> Type.BoolT.at loc trust
| U.Await ->
let reason = Reason.(mk_reason (RCustom "await") loc) in
let await = Flow_js.get_builtin file.cx (Reason.OrdinaryName "$await") reason in
(* TODO: use_op *)
let use_op = Type.unknown_use in
Tvar.mk_no_wrap_where file.cx reason (fun tout ->
Flow_js.flow
file.cx
( await,
Type.CallT (use_op, reason, Type.mk_functioncalltype reason None [Type.Arg t] tout) ))
let eval file loc t = function
| Unary op -> eval_unary file loc t op
| GetProp name ->
let reason = Reason.(mk_reason (RProperty (Some (OrdinaryName name))) loc) in
(* TODO: use_op *)
let use_op = Type.unknown_use in
Tvar.mk_no_wrap_where file.cx reason (fun tout ->
Flow_js.flow
file.cx
(t, Type.GetPropT (use_op, reason, Type.Named (reason, Reason.OrdinaryName name), tout)))
| GetElem index ->
let reason = Reason.(mk_reason (RProperty None) loc) in
(* TODO: use_op *)
let use_op = Type.unknown_use in
Tvar.mk_no_wrap_where file.cx reason (fun tout ->
Flow_js.flow file.cx (t, Type.GetElemT (use_op, reason, index, tout)))
let async_void_return file loc =
let t = Type.VoidT.at loc trust in
let reason = Reason.(mk_reason (RCustom "async return") loc) in
Flow_js.get_builtin_typeapp
file.cx
reason
(Reason.OrdinaryName "Promise")
[
Tvar.mk_derivable_where file.cx reason (fun tvar ->
let funt = Flow_js.get_builtin file.cx (Reason.OrdinaryName "$await") reason in
let callt = Type.mk_functioncalltype reason None [Type.Arg t] (Type.open_tvar tvar) in
let reason =
Reason.repos_reason (Reason.aloc_of_reason (TypeUtil.reason_of_t t)) reason
in
Flow_js.flow file.cx (funt, Type.CallT (Type.unknown_use, reason, callt)));
]
let add_default_constructor reason extends props =
match extends with
| ClassExplicitExtends _
| ClassExplicitExtendsApp _ ->
props
| ClassImplicitExtends
| ObjectPrototypeExtendsNull ->
SMap.update
"constructor"
(function
| None ->
let reason = Reason.(replace_desc_reason RDefaultConstructor reason) in
let return = Type.VoidT.why reason trust in
let statics = Type.dummy_static reason in
let proto = Type.dummy_prototype in
let funtype = Type.mk_boundfunctiontype [] return ~rest_param:None ~def_reason:reason in
Some Type.(Method (None, DefT (reason, trust, FunT (statics, proto, funtype))))
| prop -> prop)
props
let add_name_field reason =
let f = function
| Some _ as p -> p
| None ->
let open Type in
Some (Field (None, StrT.why reason trust, Polarity.Neutral))
in
SMap.update "name" f
let require file loc index =
let (mref, mk_module_t) = Module_refs.get file.dependencies index in
let reason = Reason.(mk_reason (RCommonJSExports mref) loc) in
Tvar.mk_where file.cx reason (fun tout ->
Flow_js.flow file.cx (mk_module_t loc, Type.CJSRequireT (reason, tout, false)))
let import file reason id_loc index kind ~remote ~local =
let (mref, mk_module_t) = Module_refs.get file.dependencies index in
Tvar.mk_where file.cx reason (fun tout ->
Flow_js.flow
file.cx
( mk_module_t id_loc,
if remote = "default" then
Type.ImportDefaultT (reason, kind, (local, mref), tout, false)
else
Type.ImportNamedT (reason, kind, remote, mref, tout, false) ))
let import_ns file reason id_loc index =
let (_, mk_module_t) = Module_refs.get file.dependencies index in
Tvar.mk_where file.cx reason (fun tout ->
Flow_js.flow file.cx (mk_module_t id_loc, Type.ImportModuleNsT (reason, tout, false)))
let import_typeof_ns file reason id_loc index =
let (_, mk_module_t) = Module_refs.get file.dependencies index in
let ns_t =
Tvar.mk_where file.cx reason (fun tout ->
Flow_js.flow file.cx (mk_module_t id_loc, Type.ImportModuleNsT (reason, tout, false)))
in
Tvar.mk_where file.cx reason (fun tout ->
Flow_js.flow file.cx (ns_t, Type.ImportTypeofT (reason, "*", tout)))
let merge_enum file reason id_loc enum_name rep members has_unknown_members =
let rep_reason desc = Reason.(mk_reason (REnumRepresentation desc) id_loc) in
let rep_t desc def_t = Type.DefT (rep_reason desc, trust, def_t) in
let representation_t =
let open Type in
match rep with
| BoolRep lit -> rep_t Reason.RBoolean (BoolT lit)
| NumberRep { truthy } ->
let lit =
if truthy then
Truthy
else
AnyLiteral
in
rep_t Reason.RNumber (NumT lit)
| StringRep { truthy } ->
let lit =
if truthy then
Truthy
else
AnyLiteral
in
rep_t Reason.RString (StrT lit)
| SymbolRep -> rep_t Reason.RSymbol SymbolT
in
let enum_id = Context.make_aloc_id file.cx id_loc in
Type.(
DefT
( reason,
trust,
EnumObjectT { enum_id; enum_name; members; representation_t; has_unknown_members } ))
let merge_pattern file = function
| Pack.PDef i -> Lazy.force (Pattern_defs.get file.pattern_defs i)
| Pack.PropP { id_loc; name; def } ->
let t = Lazy.force (Patterns.get file.patterns def) in
let reason = Reason.(mk_reason (RProperty (Some (Reason.OrdinaryName name))) id_loc) in
(* TODO: use_op *)
let use_op = Type.unknown_use in
Tvar.mk_no_wrap_where file.cx reason (fun tout ->
Flow_js.flow
file.cx
(t, Type.GetPropT (use_op, reason, Type.Named (reason, Reason.OrdinaryName name), tout)))
| Pack.ComputedP { elem; def } ->
let elem = Lazy.force (Pattern_defs.get file.pattern_defs elem) in
let t = Lazy.force (Patterns.get file.patterns def) in
let loc = TypeUtil.loc_of_t elem in
let reason = Reason.(mk_reason (RProperty None) loc) in
(* TODO: use_op *)
let use_op = Type.unknown_use in
Tvar.mk_no_wrap_where file.cx reason (fun tout ->
Flow_js.flow file.cx (t, Type.GetElemT (use_op, reason, elem, tout)))
| Pack.UnsupportedLiteralP loc -> Type.(AnyT.at (AnyError None) loc)
| Pack.ObjRestP { loc; xs; def } ->
let t = Lazy.force (Patterns.get file.patterns def) in
let reason = Reason.(mk_reason RObjectPatternRestProp loc) in
Tvar.mk_where file.cx reason (fun tout ->
Flow_js.flow file.cx (t, Type.ObjRestT (reason, xs, tout, Reason.mk_id ())))
| Pack.IndexP { loc; i; def } ->
let t = Lazy.force (Patterns.get file.patterns def) in
let reason = Reason.(mk_reason (RCustom (Utils_js.spf "element %d" i)) loc) in
let i =
let reason = Reason.(mk_reason RNumber loc) in
Type.(DefT (reason, trust, NumT (Literal (None, (float i, string_of_int i)))))
in
(* TODO: use_op *)
let use_op = Type.unknown_use in
Tvar.mk_no_wrap_where file.cx reason (fun tout ->
Flow_js.flow file.cx (t, Type.GetElemT (use_op, reason, i, tout)))
| Pack.ArrRestP { loc; i; def } ->
let t = Lazy.force (Patterns.get file.patterns def) in
let reason = Reason.(mk_reason RArrayPatternRestProp loc) in
(* TODO: use_op *)
let use_op = Type.unknown_use in
Tvar.mk_where file.cx reason (fun tout ->
Flow_js.flow file.cx (t, Type.ArrRestT (use_op, reason, i, tout)))
let merge_remote_ref file reason = function
| Pack.Import { id_loc; name; index; remote } ->
import file reason id_loc index Type.ImportValue ~remote ~local:name
| Pack.ImportType { id_loc; name; index; remote } ->
import file reason id_loc index Type.ImportType ~remote ~local:name
| Pack.ImportTypeof { id_loc; name; index; remote } ->
import file reason id_loc index Type.ImportTypeof ~remote ~local:name
| Pack.ImportNs { id_loc; name = _; index } -> import_ns file reason id_loc index
| Pack.ImportTypeofNs { id_loc; name = _; index } -> import_typeof_ns file reason id_loc index
let merge_ref : 'a. _ -> (_ -> _ -> _ -> 'a) -> _ -> 'a =
fun file f ref ->
match ref with
| Pack.LocalRef { ref_loc; index } ->
let (_loc, name, t) = visit (Local_defs.get file.local_defs index) in
let t = Flow_js.reposition file.cx ref_loc t in
f t ref_loc name
| Pack.RemoteRef { ref_loc; index } ->
let (_loc, name, t) = visit (Remote_refs.get file.remote_refs index) in
let t = Flow_js.reposition file.cx ref_loc t in
f t ref_loc name
| Pack.BuiltinRef { ref_loc; name } ->
let reason = Reason.(mk_reason (RIdentifier (Reason.OrdinaryName name)) ref_loc) in
let t = Flow_js.get_builtin file.cx (Reason.OrdinaryName name) reason in
f t ref_loc name
let rec merge_tyref file f = function
| Pack.Unqualified ref ->
let f t loc name = f t loc (Nel.one name) in
merge_ref file f ref
| Pack.Qualified { loc; id_loc; name; qualification } ->
let f t _ names =
let names = Nel.cons name names in
let qname = String.concat "." (List.rev (Nel.to_list names)) in
let id_reason = Reason.(mk_reason (RType (OrdinaryName name)) id_loc) in
let reason_op = Reason.(mk_reason (RType (OrdinaryName qname)) loc) in
let use_op = Type.(Op (GetProperty reason_op)) in
let t =
Tvar.mk_no_wrap_where file.cx reason_op (fun tout ->
Flow_js.flow
file.cx
( t,
Type.(
GetPropT (use_op, reason_op, Named (id_reason, Reason.OrdinaryName name), tout))
))
in
f t loc names
in
merge_tyref file f qualification
let merge_export file = function
| Pack.ExportRef ref -> merge_ref file (fun t ref_loc _ -> (Some ref_loc, t)) ref
| Pack.ExportBinding index ->
let (loc, _name, t) = visit (Local_defs.get file.local_defs index) in
(Some loc, t)
| Pack.ExportDefault { default_loc } ->
let (lazy t) = Option.value_exn file.export_def in
(Some default_loc, t)
| Pack.ExportDefaultBinding { default_loc; index } ->
let (_loc, _name, t) = visit (Local_defs.get file.local_defs index) in
(Some default_loc, t)
| Pack.ExportFrom index ->
let (loc, _name, t) = visit (Remote_refs.get file.remote_refs index) in
(Some loc, t)
let merge_export_type file = function
| Pack.ExportTypeRef ref -> merge_ref file (fun t ref_loc _ -> (Some ref_loc, t)) ref
| Pack.ExportTypeBinding index ->
let (loc, _name, t) = visit (Local_defs.get file.local_defs index) in
(Some loc, t)
| Pack.ExportTypeFrom index ->
let (loc, _name, t) = visit (Remote_refs.get file.remote_refs index) in
(Some loc, t)
let merge_exports =
let merge_star file (loc, index) =
let (_, mk_module_t) = Module_refs.get file.dependencies index in
(loc, mk_module_t loc)
in
let mk_es_module_t file reason is_strict =
let open Type in
let exportstype =
{
exports_tmap = Context.make_export_map file.cx NameUtils.Map.empty;
cjs_export = None;
has_every_named_export = false;
}
in
ModuleT (reason, exportstype, is_strict)
in
let mk_commonjs_module_t file reason is_strict t =
let open Type in
let exporttypes =
{
exports_tmap = Context.make_export_map file.cx NameUtils.Map.empty;
cjs_export = Some t;
has_every_named_export = false;
}
in
Tvar.mk_where file.cx reason (fun tout ->
Flow_js.flow
file.cx
(t, CJSExtractNamedExportsT (reason, (reason, exporttypes, is_strict), tout)))
in
let export_named file reason kind named module_t =
Tvar.mk_where file.cx reason (fun tout ->
Flow_js.flow file.cx (module_t, Type.ExportNamedT (reason, named, kind, tout)))
in
let copy_named_exports file reason module_t (loc, from_ns) =
let reason = Reason.repos_reason loc reason in
Tvar.mk_where file.cx reason (fun tout ->
Flow_js.flow file.cx (from_ns, Type.CopyNamedExportsT (reason, module_t, tout)))
in
let copy_type_exports file reason module_t (loc, from_ns) =
let reason = Reason.repos_reason loc reason in
Tvar.mk_where file.cx reason (fun tout ->
Flow_js.flow file.cx (from_ns, Type.CopyTypeExportsT (reason, module_t, tout)))
in
let copy_star_exports =
let rec loop file reason acc = function
| ([], []) -> acc
| (xs, []) -> List.fold_left (copy_named_exports file reason) acc xs
| ([], ys) -> List.fold_left (copy_type_exports file reason) acc ys
| ((x :: xs' as xs), (y :: ys' as ys)) ->
if ALoc.compare (fst x) (fst y) > 0 then
loop file reason (copy_named_exports file reason acc x) (xs', ys)
else
loop file reason (copy_type_exports file reason acc y) (xs, ys')
in
(fun file reason stars acc -> loop file reason acc stars)
in
fun file reason -> function
| Pack.CJSExports { types; type_stars; strict } ->
let value =
match file.export_def with
| Some (lazy t) -> t
| None -> Obj_type.mk_unsealed file.cx reason
in
let types = SMap.map (merge_export_type file) types |> NameUtils.namemap_of_smap in
let type_stars = List.map (merge_star file) type_stars in
mk_commonjs_module_t file reason strict value
|> export_named file reason Type.ExportType types
|> copy_star_exports file reason ([], type_stars)
| Pack.ESExports { names; types; stars; type_stars; strict } ->
let names = SMap.map (merge_export file) names |> NameUtils.namemap_of_smap in
let types = SMap.map (merge_export_type file) types |> NameUtils.namemap_of_smap in
let stars = List.map (merge_star file) stars in
let type_stars = List.map (merge_star file) type_stars in
mk_es_module_t file reason strict
|> export_named file reason Type.ExportValue names
|> export_named file reason Type.ExportType types
|> copy_star_exports file reason (stars, type_stars)
let rec merge file = function
| Pack.Annot t -> merge_annot file t
| Pack.Value t -> merge_value file t
| Pack.Ref ref -> merge_ref file (fun t _ _ -> t) ref
| Pack.TyRef name ->
let f t ref_loc (name, _) =
let reason = Reason.(mk_annot_reason (RType (Reason.OrdinaryName name)) ref_loc) in
Flow_js.mk_instance file.cx reason t
in
merge_tyref file f name
| Pack.TyRefApp { loc; name; targs } ->
let targs = List.map (merge file) targs in
let f t _ _ = TypeUtil.typeapp_annot loc t targs in
merge_tyref file f name
| Pack.AsyncVoidReturn loc -> async_void_return file loc
| Pack.Pattern i -> Lazy.force (Patterns.get file.patterns i)
| Pack.Err loc -> Type.(AnyT.at (AnyError None) loc)
| Pack.Eval (loc, t, op) ->
let t = merge file t in
let op = merge_op file op in
eval file loc t op
| Pack.Require { loc; index } -> require file loc index
| Pack.ImportDynamic { loc; index } ->
let (mref, _) = Module_refs.get file.dependencies index in
let ns_reason = Reason.(mk_reason (RModule (OrdinaryName mref)) loc) in
let ns_t = import_ns file ns_reason loc index in
let reason = Reason.(mk_annot_reason RAsyncImport loc) in
Flow_js.get_builtin_typeapp file.cx reason (Reason.OrdinaryName "Promise") [ns_t]
| Pack.ModuleRef { loc; index } ->
let t = require file loc index in
let reason = Reason.(mk_reason (RCustom "module reference") loc) in
Flow_js.get_builtin_typeapp file.cx reason (Reason.OrdinaryName "$Flow$ModuleRef") [t]
and merge_annot file = function
| Any loc -> Type.AnyT.at Type.AnnotatedAny loc
| Mixed loc -> Type.MixedT.at loc trust
| Empty loc -> Type.EmptyT.at loc trust
| Void loc -> Type.VoidT.at loc trust
| Null loc -> Type.NullT.at loc trust
| Symbol loc -> Type.SymbolT.at loc trust
| Number loc -> Type.NumT.at loc trust
| BigInt loc ->
let reason = Reason.(mk_annot_reason RBigInt loc) in
Type.(AnyT.error reason)
| String loc -> Type.StrT.at loc trust
| Boolean loc -> Type.BoolT.at loc trust
| Exists { loc; force } ->
let reason = Reason.(mk_annot_reason RExistential loc) in
if force then
Tvar.mk file.cx reason
else
Type.ExistsT reason
| Optional t -> TypeUtil.optional (merge file t)
| Maybe (loc, t) ->
let t = merge file t in
let desc = TypeUtil.desc_of_t t in
let reason = Reason.(mk_annot_reason (RMaybe desc) loc) in
Type.MaybeT (reason, t)
| Union { loc; t0; t1; ts } ->
let reason = Reason.(mk_annot_reason RUnionType loc) in
let t0 = merge file t0 in
let t1 = merge file t1 in
(* NB: tail-recursive map in case of very large types *)
let ts = Base.List.map ~f:(merge file) ts in
let open Type in
let rep = UnionRep.make t0 t1 ts in
UnionRep.optimize
rep
~reasonless_eq:TypeUtil.reasonless_eq
~flatten:(Type_mapper.union_flatten file.cx)
~find_resolved:(Context.find_resolved file.cx)
~find_props:(Context.find_props file.cx);
UnionT (reason, rep)
| Intersection { loc; t0; t1; ts } ->
let reason = Reason.(mk_annot_reason RIntersectionType loc) in
let t0 = merge file t0 in
let t1 = merge file t1 in
(* NB: tail-recursive map in case of very large types *)
let ts = Base.List.map ~f:(merge file) ts in
Type.(IntersectionT (reason, InterRep.make t0 t1 ts))
| Tuple { loc; ts } ->
let reason = Reason.(mk_annot_reason RTupleType loc) in
let elem_reason = Reason.(mk_annot_reason RTupleElement loc) in
(* NB: tail-recursive map in case of very large types *)
let ts = Base.List.map ~f:(merge file) ts in
let elem_t =
match ts with
| [] -> Type.EmptyT.why elem_reason trust
| [t] -> t
| t0 :: t1 :: ts ->
let rep = Type.UnionRep.make t0 t1 ts in
Type.UnionT (elem_reason, rep)
in
Type.(DefT (reason, trust, ArrT (TupleAT (elem_t, ts))))
| Array (loc, t) ->
let reason = Reason.(mk_annot_reason RArrayType loc) in
let t = merge file t in
Type.(DefT (reason, trust, ArrT (ArrayAT (t, None))))
| ReadOnlyArray (loc, t) ->
let reason = Reason.(mk_annot_reason RROArrayType loc) in
let t = merge file t in
Type.(DefT (reason, trust, ArrT (ROArrayAT t)))
| SingletonString (loc, str) ->
let reason = Reason.(mk_annot_reason (RStringLit (OrdinaryName str)) loc) in
Type.(DefT (reason, trust, SingletonStrT (Reason.OrdinaryName str)))
| SingletonNumber (loc, num, raw) ->
let reason = Reason.(mk_annot_reason (RNumberLit raw) loc) in
Type.(DefT (reason, trust, SingletonNumT (num, raw)))
| SingletonBigInt (loc, raw) ->
let reason = Reason.(mk_annot_reason (RBigIntLit raw) loc) in
Type.(AnyT.error reason)
| SingletonBoolean (loc, b) ->
let reason = Reason.(mk_annot_reason (RBooleanLit b) loc) in
Type.(DefT (reason, trust, SingletonBoolT b))
| Typeof { loc; qname; t } ->
let qname = String.concat "." qname in
let reason = Reason.(mk_reason (RTypeof qname) loc) in
let t = merge file t in
Flow_js.mk_typeof_annotation file.cx reason t
| Bound { ref_loc; name } ->
let reason = Reason.(mk_annot_reason (RType (OrdinaryName name)) ref_loc) in
Type.BoundT (reason, name)
| TEMPORARY_Number (loc, num, raw) ->
let reason = Reason.(mk_annot_reason RNumber loc) in
Type.(DefT (reason, trust, NumT (Literal (None, (num, raw)))))
| TEMPORARY_String (loc, str) ->
let reason = Reason.(mk_annot_reason RString loc) in
Type.(DefT (reason, trust, StrT (Literal (None, Reason.OrdinaryName str))))
| TEMPORARY_LongString loc ->
let len = Context.max_literal_length file.cx in
let reason = Reason.(mk_annot_reason (RLongStringLit len) loc) in
Type.(DefT (reason, trust, StrT AnyLiteral))
| TEMPORARY_Boolean (loc, b) ->
let reason = Reason.(mk_annot_reason RBoolean loc) in
Type.(DefT (reason, trust, BoolT (Some b)))
| TEMPORARY_Object t ->
let t = merge file t in
let open Type in
(match t with
| ExactT (_, DefT (r, trust, ObjT o))
| DefT (r, trust, ObjT o) ->
let r = Reason.(replace_desc_reason RObjectLit r) in
let obj_kind =
match o.flags.obj_kind with
| Indexed _ -> o.flags.obj_kind
| _ -> Type.Exact
in
DefT (r, trust, ObjT { o with flags = { o.flags with obj_kind } })
| EvalT (l, TypeDestructorT (use_op, r, SpreadType (target, ts, head_slice)), id) ->
let r = Reason.(replace_desc_reason RObjectLit r) in
EvalT (l, TypeDestructorT (use_op, r, SpreadType (target, ts, head_slice)), id)
| _ -> t)
| TEMPORARY_Array (loc, t) ->
let reason = Reason.(mk_annot_reason RArrayLit loc) in
let t = merge file t in
Type.(DefT (reason, trust, ArrT (ArrayAT (t, None))))
| AnyWithLowerBound (_loc, t) ->
let t = merge file t in
Type.AnyT.annot (TypeUtil.reason_of_t t)
| AnyWithUpperBound (_loc, t) ->
let t = merge file t in
Type.AnyT.annot (TypeUtil.reason_of_t t)
| PropertyType { loc; obj; prop } ->
let reason = Reason.(mk_reason (RType (OrdinaryName "$PropertyType")) loc) in
let use_op = Type.Op (Type.TypeApplication { type' = reason }) in
let obj = merge file obj in
let id = Type.Eval.id_of_aloc_id (Context.make_aloc_id file.cx loc) in
Type.(
EvalT (obj, TypeDestructorT (use_op, reason, Type.PropertyType (Reason.OrdinaryName prop)), id))
| ElementType { loc; obj; elem } ->
let reason = Reason.(mk_reason (RType (OrdinaryName "$ElementType")) loc) in
let use_op = Type.Op (Type.TypeApplication { type' = reason }) in
let obj = merge file obj in
let elem = merge file elem in
let id = Type.Eval.id_of_aloc_id (Context.make_aloc_id file.cx loc) in
Type.(
EvalT
( obj,
TypeDestructorT
(use_op, reason, Type.ElementType { index_type = elem; is_indexed_access = false }),
id ))
| NonMaybeType (loc, t) ->
let reason = Reason.(mk_reason (RType (OrdinaryName "$NonMaybeType")) loc) in
let use_op = Type.Op (Type.TypeApplication { type' = reason }) in
let t = merge file t in
let id = Type.Eval.id_of_aloc_id (Context.make_aloc_id file.cx loc) in
Type.(EvalT (t, TypeDestructorT (use_op, reason, Type.NonMaybeType), id))
| Shape (_loc, t) ->
let t = merge file t in
let desc = TypeUtil.desc_of_t t in
let loc = TypeUtil.loc_of_t t in
let reason = Reason.(mk_reason (RShapeOf desc) loc) in
Type.ShapeT (reason, t)
| Diff (loc, t1, t2) ->
let reason = Reason.(mk_reason (RType (OrdinaryName "$Diff")) loc) in
let use_op = Type.Op (Type.TypeApplication { type' = reason }) in
let t1 = merge file t1 in
let t2 = merge file t2 in
let id = Type.Eval.id_of_aloc_id (Context.make_aloc_id file.cx loc) in
Type.(
EvalT (t1, TypeDestructorT (use_op, reason, RestType (Object.Rest.IgnoreExactAndOwn, t2)), id))
| ReadOnly (loc, t) ->
let reason = Reason.(mk_reason (RType (OrdinaryName "$ReadOnly")) loc) in
let use_op = Type.Op (Type.TypeApplication { type' = reason }) in
let t = merge file t in
let id = Type.Eval.id_of_aloc_id (Context.make_aloc_id file.cx loc) in
Type.(EvalT (t, TypeDestructorT (use_op, reason, ReadOnlyType), id))
| Keys (loc, t) ->
let reason = Reason.(mk_reason RKeySet loc) in
let t = merge file t in
Type.KeysT (reason, t)
| Values (loc, t) ->
let reason = Reason.(mk_reason (RType (OrdinaryName "$Values")) loc) in
let use_op = Type.Op (Type.TypeApplication { type' = reason }) in
let t = merge file t in
let id = Type.Eval.id_of_aloc_id (Context.make_aloc_id file.cx loc) in
Type.(EvalT (t, TypeDestructorT (use_op, reason, ValuesType), id))
| Exact (loc, t) ->
let t = merge file t in
let desc = TypeUtil.desc_of_t t in
let reason = Reason.(mk_annot_reason (RExactType desc) loc) in
Type.ExactT (reason, t)
| Rest (loc, t1, t2) ->
let reason = Reason.(mk_reason (RType (OrdinaryName "$Rest")) loc) in
let use_op = Type.Op (Type.TypeApplication { type' = reason }) in
let t1 = merge file t1 in
let t2 = merge file t2 in
let id = Type.Eval.id_of_aloc_id (Context.make_aloc_id file.cx loc) in
Type.(EvalT (t1, TypeDestructorT (use_op, reason, RestType (Object.Rest.Sound, t2)), id))
| ExportsT (loc, ref) ->
let reason = Reason.(mk_annot_reason (RModule (OrdinaryName ref)) loc) in
let m_name = Reason.internal_module_name ref in
let module_t =
Tvar.mk_no_wrap_where file.cx reason (fun tout ->
Flow_js.lookup_builtin file.cx m_name reason (Type.Strict reason) tout)
in
Tvar.mk_where file.cx reason (fun tout ->
Flow_js.flow file.cx (module_t, Type.CJSRequireT (reason, tout, false)))
| Call { loc; fn; args } ->
let reason = Reason.(mk_reason RFunctionCallType loc) in
let use_op = Type.Op (Type.TypeApplication { type' = reason }) in
let fn = merge file fn in
let args = List.map (merge file) args in
let id = Type.Eval.id_of_aloc_id (Context.make_aloc_id file.cx loc) in
Type.(EvalT (fn, TypeDestructorT (use_op, reason, CallType args), id))
| TupleMap { loc; tup; fn } ->
let reason = Reason.(mk_reason RTupleMap loc) in
let use_op = Type.Op (Type.TypeApplication { type' = reason }) in
let tup = merge file tup in
let fn = merge file fn in
let id = Type.Eval.id_of_aloc_id (Context.make_aloc_id file.cx loc) in
Type.(EvalT (tup, TypeDestructorT (use_op, reason, TypeMap (Type.TupleMap fn)), id))
| ObjMap { loc; obj; fn } ->
let reason = Reason.(mk_reason RObjectMap loc) in
let use_op = Type.Op (Type.TypeApplication { type' = reason }) in
let obj = merge file obj in
let fn = merge file fn in
let id = Type.Eval.id_of_aloc_id (Context.make_aloc_id file.cx loc) in
Type.(EvalT (obj, TypeDestructorT (use_op, reason, TypeMap (ObjectMap fn)), id))
| ObjMapi { loc; obj; fn } ->
let reason = Reason.(mk_reason RObjectMapi loc) in
let use_op = Type.Op (Type.TypeApplication { type' = reason }) in
let obj = merge file obj in
let fn = merge file fn in
let id = Type.Eval.id_of_aloc_id (Context.make_aloc_id file.cx loc) in
Type.(EvalT (obj, TypeDestructorT (use_op, reason, TypeMap (ObjectMapi fn)), id))
| CharSet (loc, str) ->
let chars = String_utils.CharSet.of_string str in
let char_str = String_utils.CharSet.to_string chars in
let reason_str = Utils_js.spf "character set `%s`" char_str in
let reason = Reason.(mk_annot_reason (RCustom reason_str) loc) in
Type.(DefT (reason, trust, CharSetT chars))
| ClassT (loc, t) ->
let t = merge file t in
let desc = TypeUtil.desc_of_t t in
let reason = Reason.(mk_reason (RStatics desc) loc) in
Type.DefT (reason, trust, Type.ClassT t)
| Function_apply loc ->
let reason = Reason.(mk_annot_reason RFunctionType loc) in
Type.FunProtoApplyT reason
| Function_bind loc ->
let reason = Reason.(mk_annot_reason RFunctionType loc) in
Type.FunProtoBindT reason
| Function_call loc ->
let reason = Reason.(mk_annot_reason RFunctionType loc) in
Type.FunProtoCallT reason
| Object_assign loc ->
let reason = Reason.(mk_reason RFunctionType loc) in
Type.CustomFunT (reason, Type.ObjectAssign)
| Object_getPrototypeOf loc ->
let reason = Reason.(mk_reason RFunctionType loc) in
Type.CustomFunT (reason, Type.ObjectGetPrototypeOf)
| Object_setPrototypeOf loc ->
let reason = Reason.(mk_reason RFunctionType loc) in
Type.CustomFunT (reason, Type.ObjectSetPrototypeOf)
| Compose loc ->
let reason = Reason.(mk_reason RFunctionType loc) in
Type.CustomFunT (reason, Type.Compose false)
| ComposeReverse loc ->
let reason = Reason.(mk_reason RFunctionType loc) in
Type.CustomFunT (reason, Type.Compose true)
| ReactAbstractComponent { loc; config; instance } ->
let reason = Reason.(mk_reason (RCustom "AbstractComponent") loc) in
let config = merge file config in
let instance = merge file instance in
Type.(DefT (reason, trust, ReactAbstractComponentT { config; instance }))
| ReactConfig { loc; props; default } ->
let reason = Reason.(mk_reason RReactConfig loc) in
let use_op = Type.Op (Type.TypeApplication { type' = reason }) in
let props = merge file props in
let default = merge file default in
let id = Type.Eval.id_of_aloc_id (Context.make_aloc_id file.cx loc) in
Type.(EvalT (props, TypeDestructorT (use_op, reason, ReactConfigType default), id))
| ReactPropTypePrimitive (loc, t) ->
let reason = Reason.(mk_reason RFunctionType loc) in
let t = merge file t in
Type.(CustomFunT (reason, ReactPropType (React.PropType.Primitive (false, t))))
| ReactPropTypePrimitiveRequired (loc, t) ->
let reason = Reason.(mk_reason RFunctionType loc) in
let t = merge file t in
Type.(CustomFunT (reason, ReactPropType (React.PropType.Primitive (true, t))))
| ReactPropTypeArrayOf loc ->
let reason = Reason.(mk_reason RFunctionType loc) in
Type.(CustomFunT (reason, ReactPropType React.PropType.(Complex ArrayOf)))
| ReactPropTypeInstanceOf loc ->
let reason = Reason.(mk_reason RFunctionType loc) in
Type.(CustomFunT (reason, ReactPropType React.PropType.(Complex InstanceOf)))
| ReactPropTypeObjectOf loc ->
let reason = Reason.(mk_reason RFunctionType loc) in
Type.(CustomFunT (reason, ReactPropType React.PropType.(Complex ObjectOf)))
| ReactPropTypeOneOf loc ->
let reason = Reason.(mk_reason RFunctionType loc) in
Type.(CustomFunT (reason, ReactPropType React.PropType.(Complex OneOf)))
| ReactPropTypeOneOfType loc ->
let reason = Reason.(mk_reason RFunctionType loc) in
Type.(CustomFunT (reason, ReactPropType React.PropType.(Complex OneOfType)))
| ReactPropTypeShape loc ->
let reason = Reason.(mk_reason RFunctionType loc) in
Type.(CustomFunT (reason, ReactPropType React.(PropType.Complex PropType.Shape)))
| ReactCreateClass loc ->
let reason = Reason.(mk_reason RFunctionType loc) in
Type.CustomFunT (reason, Type.ReactCreateClass)
| ReactCreateElement loc ->
let reason = Reason.(mk_reason RFunctionType loc) in
Type.CustomFunT (reason, Type.ReactCreateElement)
| ReactCloneElement loc ->
let reason = Reason.(mk_reason RFunctionType loc) in
Type.CustomFunT (reason, Type.ReactCloneElement)
| ReactElementFactory (loc, t) ->
let reason = Reason.(mk_reason RFunctionType loc) in
let t = merge file t in
Type.CustomFunT (reason, Type.ReactElementFactory t)
| ReactElementProps (loc, t) ->
let reason = Reason.(mk_reason (RType (OrdinaryName "React$ElementProps")) loc) in
let use_op = Type.Op (Type.TypeApplication { type' = reason }) in
let t = merge file t in
let id = Type.Eval.id_of_aloc_id (Context.make_aloc_id file.cx loc) in
Type.(EvalT (t, TypeDestructorT (use_op, reason, ReactElementPropsType), id))
| ReactElementConfig (loc, t) ->
let reason = Reason.(mk_reason (RType (OrdinaryName "React$ElementConfig")) loc) in
let use_op = Type.Op (Type.TypeApplication { type' = reason }) in
let t = merge file t in
let id = Type.Eval.id_of_aloc_id (Context.make_aloc_id file.cx loc) in
Type.(EvalT (t, TypeDestructorT (use_op, reason, ReactElementConfigType), id))
| ReactElementRef (loc, t) ->
let reason = Reason.(mk_reason (RType (OrdinaryName "React$ElementRef")) loc) in
let use_op = Type.Op (Type.TypeApplication { type' = reason }) in
let t = merge file t in
let id = Type.Eval.id_of_aloc_id (Context.make_aloc_id file.cx loc) in
Type.(EvalT (t, TypeDestructorT (use_op, reason, ReactElementRefType), id))
| FacebookismIdx loc ->
let reason = Reason.(mk_reason RFunctionType loc) in
Type.CustomFunT (reason, Type.Idx)
| FacebookismTypeAssertIs loc ->
let reason = Reason.(mk_reason RFunctionType loc) in
Type.CustomFunT (reason, Type.TypeAssertIs)
| FacebookismTypeAssertThrows loc ->
let reason = Reason.(mk_reason RFunctionType loc) in
Type.CustomFunT (reason, Type.TypeAssertThrows)
| FacebookismTypeAssertWraps loc ->
let reason = Reason.(mk_reason RFunctionType loc) in
Type.CustomFunT (reason, Type.TypeAssertWraps)
| FlowDebugPrint loc ->
let reason = Reason.(mk_reason RFunctionType loc) in
Type.CustomFunT (reason, Type.DebugPrint)
| FlowDebugThrow loc ->
let reason = Reason.(mk_reason RFunctionType loc) in
Type.CustomFunT (reason, Type.DebugThrow)
| FlowDebugSleep loc ->
let reason = Reason.(mk_reason RFunctionType loc) in
Type.CustomFunT (reason, Type.DebugSleep)
| Pred (loc, n) ->
let open Type in
let fun_reason = Reason.(mk_annot_reason (RCustom "abstract predicate function") loc) in
let static_reason = Reason.(mk_reason (RCustom "abstract predicate static") loc) in
let out_reason = Reason.(mk_reason (RCustom "open predicate") loc) in
let key_strs = ListUtils.range 0 n |> List.map (fun i -> Some ("x_" ^ Base.Int.to_string i)) in
let emp = Key_map.empty in
let tins = Unsoundness.at FunctionPrototype loc |> ListUtils.repeat n in
let tout =
OpenPredT { reason = out_reason; base_t = MixedT.at loc trust; m_pos = emp; m_neg = emp }
in
let statics = dummy_static static_reason in
let proto = Unsoundness.function_proto_any Reason.(mk_reason RPrototype loc) in
let functiontype =
mk_functiontype
fun_reason
tins
tout
~rest_param:None
~def_reason:fun_reason
~params_names:key_strs
~is_predicate:true
in
DefT (fun_reason, trust, FunT (statics, proto, functiontype))
| Refine { loc; base; fn_pred; index } ->
let reason = Reason.(mk_reason (RCustom "refined type") loc) in
let base = merge file base in
let fn_pred = merge file fn_pred in
let id = Type.Eval.id_of_aloc_id (Context.make_aloc_id file.cx loc) in
Type.(EvalT (base, LatentPredT (reason, Type.LatentP (fn_pred, index)), id))
| Trusted (loc, t) ->
begin
match merge file t with
| Type.DefT (r, trust, def_t) ->
let reason = Reason.(mk_annot_reason (RTrusted (desc_of_reason r)) loc) in
Type.(DefT (reason, trust, def_t))
| _ -> Type.(AnyT.at (AnyError None) loc)
end
| Private (loc, t) ->
begin
match merge file t with
| Type.DefT (r, trust, def_t) ->
let reason = Reason.(mk_annot_reason (RPrivate (desc_of_reason r)) loc) in
Type.(DefT (reason, trust, def_t))
| _ -> Type.(AnyT.at (AnyError None) loc)
end
| FunAnnot (loc, def) ->
let reason = Reason.(mk_annot_reason RFunctionType loc) in
let statics = merge_fun_statics file reason SMap.empty in
merge_fun file reason def statics
| ObjAnnot { loc; props; proto; obj_kind } ->
let reason = Reason.(mk_annot_reason RObjectType loc) in
let obj_kind =
match obj_kind with
| ExactObj -> Type.Exact
| InexactObj -> Type.Inexact
| IndexedObj dict -> Type.Indexed ((merge_dict file) dict)
in
let props = SMap.map (merge_obj_annot_prop file) props |> NameUtils.namemap_of_smap in
let mk_object call proto =
let t = Obj_type.mk_with_proto file.cx reason proto ?call ~props ~obj_kind ~loc in
if obj_kind = Type.Exact then
let exact_reason = Reason.(mk_annot_reason (RExactType RObjectType) loc) in
Type.ExactT (exact_reason, t)
else
t
in
begin
match proto with
| ObjAnnotImplicitProto -> mk_object None (Type.ObjProtoT reason)
| ObjAnnotExplicitProto (loc, t) ->
let reason = Reason.(mk_reason RPrototype loc) in
let proto = Tvar.mk file.cx reason in
Flow_js.flow file.cx (merge file t, Type.ObjTestProtoT (reason, proto));
let proto = Flow_js.mk_typeof_annotation file.cx reason proto in
mk_object None proto
| ObjAnnotCallable { ts_rev } ->
let proto = Type.FunProtoT reason in
let ts =
Nel.rev_map
(fun t ->
let t = merge file t in
mk_object (Some t) proto)
ts_rev
in
(match ts with
| (t, []) -> t
| (t0, t1 :: ts) ->
let reason = Reason.(mk_annot_reason (RCustom "callable object type") loc) in
Type.(IntersectionT (reason, InterRep.make t0 t1 ts)))
end
| ObjSpreadAnnot { loc; exact; elems_rev } ->
let reason = Reason.(mk_annot_reason RObjectType loc) in
let target = Type.Object.Spread.Annot { make_exact = exact } in
let merge_slice dict props =
let dict = Option.map ~f:(merge_dict file) dict in
let prop_map = SMap.map (merge_obj_annot_prop file) props |> NameUtils.namemap_of_smap in
{ Type.Object.Spread.reason; prop_map; dict; generics = Generic.spread_empty }
in
let merge_elem = function
| ObjSpreadAnnotElem t -> Type.Object.Spread.Type (merge file t)
| ObjSpreadAnnotSlice { dict; props } -> Type.Object.Spread.Slice (merge_slice dict props)
in
let (t, todo_rev, head_slice) =
let open Type.Object.Spread in
match Nel.map merge_elem elems_rev with
| (Type t, elems) -> (t, elems, None)
| (Slice slice, Type t :: elems) -> (t, elems, Some slice)
| (Slice _, Slice _ :: _) -> failwith "unexpected adjacent slices"
| (Slice _, []) -> failwith "unexpected solo slice"
in
let id = Type.Eval.id_of_aloc_id (Context.make_aloc_id file.cx loc) in
Type.(
EvalT (t, TypeDestructorT (unknown_use, reason, SpreadType (target, todo_rev, head_slice)), id))
| InlineInterface (loc, def) ->
let reason = Reason.(mk_annot_reason RInterfaceType loc) in
let id = ALoc.id_none in
merge_interface ~inline:true file reason id def []
and merge_value file = function
| ClassExpr (loc, def) ->
let name = "<<anonymous class>>" in
let reason = Type.DescFormat.instance_reason (Reason.OrdinaryName name) loc in
let id = Context.make_aloc_id file.cx loc in
merge_class file reason id def
| FunExpr { loc; async = _; generator = _; def; statics } ->
(* RFunctionType should be Reason.func_reason instead, but this matches the
* behavior of types-first where function bindings are converted to declared
* functions, which are given a RFunctionType reason.
*
* TODO Fix once T71257430 is closed. *)
let reason = Reason.(mk_reason RFunctionType loc) in
let statics = merge_fun_statics file reason statics in
merge_fun file reason def statics
| StringVal loc ->
let reason = Reason.(mk_reason RString loc) in
Type.(DefT (reason, trust, StrT AnyLiteral))
| StringLit (loc, lit) ->
let reason = Reason.(mk_reason RString loc) in
Type.(DefT (reason, trust, StrT (Literal (None, Reason.OrdinaryName lit))))
| LongStringLit loc ->
let len = Context.max_literal_length file.cx in
let reason = Reason.(mk_annot_reason (RLongStringLit len) loc) in
Type.(DefT (reason, trust, StrT AnyLiteral))