-
Notifications
You must be signed in to change notification settings - Fork 790
/
TypedTreeOps.fs
10799 lines (8804 loc) · 481 KB
/
TypedTreeOps.fs
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) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
/// Defines derived expression manipulation and construction functions.
module internal FSharp.Compiler.TypedTreeOps
open System
open System.CodeDom.Compiler
open System.Collections.Generic
open System.Collections.Immutable
open Internal.Utilities
open Internal.Utilities.Collections
open Internal.Utilities.Library
open Internal.Utilities.Library.Extras
open Internal.Utilities.Rational
open FSharp.Compiler.IO
open FSharp.Compiler.AbstractIL.IL
open FSharp.Compiler.CompilerGlobalState
open FSharp.Compiler.DiagnosticsLogger
open FSharp.Compiler.Features
open FSharp.Compiler.Syntax
open FSharp.Compiler.Syntax.PrettyNaming
open FSharp.Compiler.SyntaxTreeOps
open FSharp.Compiler.TcGlobals
open FSharp.Compiler.Text
open FSharp.Compiler.Text.Range
open FSharp.Compiler.Text.Layout
open FSharp.Compiler.Text.LayoutRender
open FSharp.Compiler.Text.TaggedText
open FSharp.Compiler.Xml
open FSharp.Compiler.TypedTree
open FSharp.Compiler.TypedTreeBasics
#if !NO_TYPEPROVIDERS
open FSharp.Compiler.TypeProviders
#endif
let AccFreeVarsStackGuardDepth = GetEnvInteger "FSHARP_AccFreeVars" 100
let RemapExprStackGuardDepth = GetEnvInteger "FSHARP_RemapExpr" 50
let FoldExprStackGuardDepth = GetEnvInteger "FSHARP_FoldExpr" 50
//---------------------------------------------------------------------------
// Basic data structures
//---------------------------------------------------------------------------
[<NoEquality; NoComparison>]
type TyparMap<'T> =
| TPMap of StampMap<'T>
member tm.Item
with get (tp: Typar) =
let (TPMap m) = tm
m[tp.Stamp]
member tm.ContainsKey (tp: Typar) =
let (TPMap m) = tm
m.ContainsKey(tp.Stamp)
member tm.TryGetValue (tp: Typar) =
let (TPMap m) = tm
m.TryGetValue(tp.Stamp)
member tm.TryFind (tp: Typar) =
let (TPMap m) = tm
m.TryFind(tp.Stamp)
member tm.Add (tp: Typar, x) =
let (TPMap m) = tm
TPMap (m.Add(tp.Stamp, x))
static member Empty: TyparMap<'T> = TPMap Map.empty
[<NoEquality; NoComparison; Sealed>]
type TyconRefMap<'T>(imap: StampMap<'T>) =
member _.Item with get (tcref: TyconRef) = imap[tcref.Stamp]
member _.TryFind (tcref: TyconRef) = imap.TryFind tcref.Stamp
member _.ContainsKey (tcref: TyconRef) = imap.ContainsKey tcref.Stamp
member _.Add (tcref: TyconRef) x = TyconRefMap (imap.Add (tcref.Stamp, x))
member _.Remove (tcref: TyconRef) = TyconRefMap (imap.Remove tcref.Stamp)
member _.IsEmpty = imap.IsEmpty
member _.TryGetValue (tcref: TyconRef) = imap.TryGetValue tcref.Stamp
static member Empty: TyconRefMap<'T> = TyconRefMap Map.empty
static member OfList vs = (vs, TyconRefMap<'T>.Empty) ||> List.foldBack (fun (x, y) acc -> acc.Add x y)
[<Struct>]
[<NoEquality; NoComparison>]
type ValMap<'T>(imap: StampMap<'T>) =
member _.Contents = imap
member _.Item with get (v: Val) = imap[v.Stamp]
member _.TryFind (v: Val) = imap.TryFind v.Stamp
member _.ContainsVal (v: Val) = imap.ContainsKey v.Stamp
member _.Add (v: Val) x = ValMap (imap.Add(v.Stamp, x))
member _.Remove (v: Val) = ValMap (imap.Remove(v.Stamp))
static member Empty = ValMap<'T> Map.empty
member _.IsEmpty = imap.IsEmpty
static member OfList vs = (vs, ValMap<'T>.Empty) ||> List.foldBack (fun (x, y) acc -> acc.Add x y)
//--------------------------------------------------------------------------
// renamings
//--------------------------------------------------------------------------
type TyparInstantiation = (Typar * TType) list
type TyconRefRemap = TyconRefMap<TyconRef>
type ValRemap = ValMap<ValRef>
let emptyTyconRefRemap: TyconRefRemap = TyconRefMap<_>.Empty
let emptyTyparInst = ([]: TyparInstantiation)
[<NoEquality; NoComparison>]
type Remap =
{ tpinst: TyparInstantiation
/// Values to remap
valRemap: ValRemap
/// TyconRefs to remap
tyconRefRemap: TyconRefRemap
/// Remove existing trait solutions?
removeTraitSolutions: bool }
let emptyRemap =
{ tpinst = emptyTyparInst
tyconRefRemap = emptyTyconRefRemap
valRemap = ValMap.Empty
removeTraitSolutions = false }
type Remap with
static member Empty = emptyRemap
//--------------------------------------------------------------------------
// Substitute for type variables and remap type constructors
//--------------------------------------------------------------------------
let addTyconRefRemap tcref1 tcref2 tmenv =
{ tmenv with tyconRefRemap = tmenv.tyconRefRemap.Add tcref1 tcref2 }
let isRemapEmpty remap =
isNil remap.tpinst &&
remap.tyconRefRemap.IsEmpty &&
remap.valRemap.IsEmpty
let rec instTyparRef tpinst ty tp =
match tpinst with
| [] -> ty
| (tpR, tyR) :: t ->
if typarEq tp tpR then tyR
else instTyparRef t ty tp
let remapTyconRef (tcmap: TyconRefMap<_>) tcref =
match tcmap.TryFind tcref with
| Some tcref -> tcref
| None -> tcref
let remapUnionCaseRef tcmap (UnionCaseRef(tcref, nm)) = UnionCaseRef(remapTyconRef tcmap tcref, nm)
let remapRecdFieldRef tcmap (RecdFieldRef(tcref, nm)) = RecdFieldRef(remapTyconRef tcmap tcref, nm)
let mkTyparInst (typars: Typars) tyargs =
(List.zip typars tyargs: TyparInstantiation)
let generalizeTypar tp = mkTyparTy tp
let generalizeTypars tps = List.map generalizeTypar tps
let rec remapTypeAux (tyenv: Remap) (ty: TType) =
let ty = stripTyparEqns ty
match ty with
| TType_var (tp, _) as ty ->
instTyparRef tyenv.tpinst ty tp
| TType_app (tcref, tinst, flags) as ty ->
match tyenv.tyconRefRemap.TryFind tcref with
| Some tcrefR -> TType_app (tcrefR, remapTypesAux tyenv tinst, flags)
| None ->
match tinst with
| [] -> ty // optimization to avoid re-allocation of TType_app node in the common case
| _ ->
// avoid reallocation on idempotent
let tinstR = remapTypesAux tyenv tinst
if tinst === tinstR then ty else
TType_app (tcref, tinstR, flags)
| TType_ucase (UnionCaseRef(tcref, n), tinst) ->
match tyenv.tyconRefRemap.TryFind tcref with
| Some tcrefR -> TType_ucase (UnionCaseRef(tcrefR, n), remapTypesAux tyenv tinst)
| None -> TType_ucase (UnionCaseRef(tcref, n), remapTypesAux tyenv tinst)
| TType_anon (anonInfo, l) as ty ->
let tupInfoR = remapTupInfoAux tyenv anonInfo.TupInfo
let lR = remapTypesAux tyenv l
if anonInfo.TupInfo === tupInfoR && l === lR then ty else
TType_anon (AnonRecdTypeInfo.Create(anonInfo.Assembly, tupInfoR, anonInfo.SortedIds), lR)
| TType_tuple (tupInfo, l) as ty ->
let tupInfoR = remapTupInfoAux tyenv tupInfo
let lR = remapTypesAux tyenv l
if tupInfo === tupInfoR && l === lR then ty else
TType_tuple (tupInfoR, lR)
| TType_fun (domainTy, rangeTy, flags) as ty ->
let domainTyR = remapTypeAux tyenv domainTy
let retTyR = remapTypeAux tyenv rangeTy
if domainTy === domainTyR && rangeTy === retTyR then ty else
TType_fun (domainTyR, retTyR, flags)
| TType_forall (tps, ty) ->
let tpsR, tyenv = copyAndRemapAndBindTypars tyenv tps
TType_forall (tpsR, remapTypeAux tyenv ty)
| TType_measure unt ->
TType_measure (remapMeasureAux tyenv unt)
and remapMeasureAux tyenv unt =
match unt with
| Measure.One -> unt
| Measure.Const tcref ->
match tyenv.tyconRefRemap.TryFind tcref with
| Some tcref -> Measure.Const tcref
| None -> unt
| Measure.Prod(u1, u2) -> Measure.Prod(remapMeasureAux tyenv u1, remapMeasureAux tyenv u2)
| Measure.RationalPower(u, q) -> Measure.RationalPower(remapMeasureAux tyenv u, q)
| Measure.Inv u -> Measure.Inv(remapMeasureAux tyenv u)
| Measure.Var tp as unt ->
match tp.Solution with
| None ->
match ListAssoc.tryFind typarEq tp tyenv.tpinst with
| Some tpTy ->
match tpTy with
| TType_measure unt -> unt
| _ -> failwith "remapMeasureAux: incorrect kinds"
| None -> unt
| Some (TType_measure unt) -> remapMeasureAux tyenv unt
| Some ty -> failwithf "incorrect kinds: %A" ty
and remapTupInfoAux _tyenv unt =
match unt with
| TupInfo.Const _ -> unt
and remapTypesAux tyenv types = List.mapq (remapTypeAux tyenv) types
and remapTyparConstraintsAux tyenv cs =
cs |> List.choose (fun x ->
match x with
| TyparConstraint.CoercesTo(ty, m) ->
Some(TyparConstraint.CoercesTo (remapTypeAux tyenv ty, m))
| TyparConstraint.MayResolveMember(traitInfo, m) ->
Some(TyparConstraint.MayResolveMember (remapTraitInfo tyenv traitInfo, m))
| TyparConstraint.DefaultsTo(priority, ty, m) ->
Some(TyparConstraint.DefaultsTo(priority, remapTypeAux tyenv ty, m))
| TyparConstraint.IsEnum(underlyingTy, m) ->
Some(TyparConstraint.IsEnum(remapTypeAux tyenv underlyingTy, m))
| TyparConstraint.IsDelegate(argTys, retTy, m) ->
Some(TyparConstraint.IsDelegate(remapTypeAux tyenv argTys, remapTypeAux tyenv retTy, m))
| TyparConstraint.SimpleChoice(tys, m) ->
Some(TyparConstraint.SimpleChoice(remapTypesAux tyenv tys, m))
| TyparConstraint.SupportsComparison _
| TyparConstraint.SupportsEquality _
| TyparConstraint.SupportsNull _
| TyparConstraint.IsUnmanaged _
| TyparConstraint.IsNonNullableStruct _
| TyparConstraint.IsReferenceType _
| TyparConstraint.RequiresDefaultConstructor _ -> Some x)
and remapTraitInfo tyenv (TTrait(tys, nm, flags, argTys, retTy, source, slnCell)) =
let slnCell =
match slnCell.Value with
| None -> None
| _ when tyenv.removeTraitSolutions -> None
| Some sln ->
let sln =
match sln with
| ILMethSln(ty, extOpt, ilMethRef, minst, staticTyOpt) ->
ILMethSln(remapTypeAux tyenv ty, extOpt, ilMethRef, remapTypesAux tyenv minst, Option.map (remapTypeAux tyenv) staticTyOpt)
| FSMethSln(ty, vref, minst, staticTyOpt) ->
FSMethSln(remapTypeAux tyenv ty, remapValRef tyenv vref, remapTypesAux tyenv minst, Option.map (remapTypeAux tyenv) staticTyOpt)
| FSRecdFieldSln(tinst, rfref, isSet) ->
FSRecdFieldSln(remapTypesAux tyenv tinst, remapRecdFieldRef tyenv.tyconRefRemap rfref, isSet)
| FSAnonRecdFieldSln(anonInfo, tinst, n) ->
FSAnonRecdFieldSln(anonInfo, remapTypesAux tyenv tinst, n)
| BuiltInSln ->
BuiltInSln
| ClosedExprSln e ->
ClosedExprSln e // no need to remap because it is a closed expression, referring only to external types
Some sln
let tysR = remapTypesAux tyenv tys
let argTysR = remapTypesAux tyenv argTys
let retTyR = Option.map (remapTypeAux tyenv) retTy
// Note: we reallocate a new solution cell on every traversal of a trait constraint
// This feels incorrect for trait constraints that are quantified: it seems we should have
// formal binders for trait constraints when they are quantified, just as
// we have formal binders for type variables.
//
// The danger here is that a solution for one syntactic occurrence of a trait constraint won't
// be propagated to other, "linked" solutions. However trait constraints don't appear in any algebra
// in the same way as types
let newSlnCell = ref slnCell
TTrait(tysR, nm, flags, argTysR, retTyR, source, newSlnCell)
and bindTypars tps tyargs tpinst =
match tps with
| [] -> tpinst
| _ -> List.map2 (fun tp tyarg -> (tp, tyarg)) tps tyargs @ tpinst
// This version is used to remap most type parameters, e.g. ones bound at tycons, vals, records
// See notes below on remapTypeFull for why we have a function that accepts remapAttribs as an argument
and copyAndRemapAndBindTyparsFull remapAttrib tyenv tps =
match tps with
| [] -> tps, tyenv
| _ ->
let tpsR = copyTypars false tps
let tyenv = { tyenv with tpinst = bindTypars tps (generalizeTypars tpsR) tyenv.tpinst }
(tps, tpsR) ||> List.iter2 (fun tporig tp ->
tp.SetConstraints (remapTyparConstraintsAux tyenv tporig.Constraints)
tp.SetAttribs (tporig.Attribs |> remapAttrib))
tpsR, tyenv
// copies bound typars, extends tpinst
and copyAndRemapAndBindTypars tyenv tps =
copyAndRemapAndBindTyparsFull (fun _ -> []) tyenv tps
and remapValLinkage tyenv (vlink: ValLinkageFullKey) =
let tyOpt = vlink.TypeForLinkage
let tyOptR =
match tyOpt with
| None -> tyOpt
| Some ty ->
let tyR = remapTypeAux tyenv ty
if ty === tyR then tyOpt else
Some tyR
if tyOpt === tyOptR then vlink else
ValLinkageFullKey(vlink.PartialKey, tyOptR)
and remapNonLocalValRef tyenv (nlvref: NonLocalValOrMemberRef) =
let eref = nlvref.EnclosingEntity
let erefR = remapTyconRef tyenv.tyconRefRemap eref
let vlink = nlvref.ItemKey
let vlinkR = remapValLinkage tyenv vlink
if eref === erefR && vlink === vlinkR then nlvref else
{ EnclosingEntity = erefR
ItemKey = vlinkR }
and remapValRef tmenv (vref: ValRef) =
match tmenv.valRemap.TryFind vref.Deref with
| None ->
if vref.IsLocalRef then vref else
let nlvref = vref.nlr
let nlvrefR = remapNonLocalValRef tmenv nlvref
if nlvref === nlvrefR then vref else
VRefNonLocal nlvrefR
| Some res ->
res
let remapType tyenv x =
if isRemapEmpty tyenv then x else
remapTypeAux tyenv x
let remapTypes tyenv x =
if isRemapEmpty tyenv then x else
remapTypesAux tyenv x
/// Use this one for any type that may be a forall type where the type variables may contain attributes
/// Logically speaking this is mutually recursive with remapAttribImpl defined much later in this file,
/// because types may contain forall types that contain attributes, which need to be remapped.
/// We currently break the recursion by passing in remapAttribImpl as a function parameter.
/// Use this one for any type that may be a forall type where the type variables may contain attributes
let remapTypeFull remapAttrib tyenv ty =
if isRemapEmpty tyenv then ty else
match stripTyparEqns ty with
| TType_forall(tps, tau) ->
let tpsR, tyenvinner = copyAndRemapAndBindTyparsFull remapAttrib tyenv tps
TType_forall(tpsR, remapType tyenvinner tau)
| _ ->
remapType tyenv ty
let remapParam tyenv (TSlotParam(nm, ty, fl1, fl2, fl3, attribs) as x) =
if isRemapEmpty tyenv then x else
TSlotParam(nm, remapTypeAux tyenv ty, fl1, fl2, fl3, attribs)
let remapSlotSig remapAttrib tyenv (TSlotSig(nm, ty, ctps, methTypars, paraml, retTy) as x) =
if isRemapEmpty tyenv then x else
let tyR = remapTypeAux tyenv ty
let ctpsR, tyenvinner = copyAndRemapAndBindTyparsFull remapAttrib tyenv ctps
let methTyparsR, tyenvinner = copyAndRemapAndBindTyparsFull remapAttrib tyenvinner methTypars
TSlotSig(nm, tyR, ctpsR, methTyparsR, List.mapSquared (remapParam tyenvinner) paraml, Option.map (remapTypeAux tyenvinner) retTy)
let mkInstRemap tpinst =
{ tyconRefRemap = emptyTyconRefRemap
tpinst = tpinst
valRemap = ValMap.Empty
removeTraitSolutions = false }
// entry points for "typar -> TType" instantiation
let instType tpinst x = if isNil tpinst then x else remapTypeAux (mkInstRemap tpinst) x
let instTypes tpinst x = if isNil tpinst then x else remapTypesAux (mkInstRemap tpinst) x
let instTrait tpinst x = if isNil tpinst then x else remapTraitInfo (mkInstRemap tpinst) x
let instTyparConstraints tpinst x = if isNil tpinst then x else remapTyparConstraintsAux (mkInstRemap tpinst) x
let instSlotSig tpinst ss = remapSlotSig (fun _ -> []) (mkInstRemap tpinst) ss
let copySlotSig ss = remapSlotSig (fun _ -> []) Remap.Empty ss
let mkTyparToTyparRenaming tpsorig tps =
let tinst = generalizeTypars tps
mkTyparInst tpsorig tinst, tinst
let mkTyconInst (tycon: Tycon) tinst = mkTyparInst tycon.TyparsNoRange tinst
let mkTyconRefInst (tcref: TyconRef) tinst = mkTyconInst tcref.Deref tinst
//---------------------------------------------------------------------------
// Basic equalities
//---------------------------------------------------------------------------
let tyconRefEq (g: TcGlobals) tcref1 tcref2 = primEntityRefEq g.compilingFSharpCore g.fslibCcu tcref1 tcref2
let valRefEq (g: TcGlobals) vref1 vref2 = primValRefEq g.compilingFSharpCore g.fslibCcu vref1 vref2
//---------------------------------------------------------------------------
// Remove inference equations and abbreviations from units
//---------------------------------------------------------------------------
let reduceTyconRefAbbrevMeasureable (tcref: TyconRef) =
let abbrev = tcref.TypeAbbrev
match abbrev with
| Some (TType_measure ms) -> ms
| _ -> invalidArg "tcref" "not a measure abbreviation, or incorrect kind"
let rec stripUnitEqnsFromMeasureAux canShortcut unt =
match stripUnitEqnsAux canShortcut unt with
| Measure.Const tcref when tcref.IsTypeAbbrev ->
stripUnitEqnsFromMeasureAux canShortcut (reduceTyconRefAbbrevMeasureable tcref)
| m -> m
let stripUnitEqnsFromMeasure m = stripUnitEqnsFromMeasureAux false m
//---------------------------------------------------------------------------
// Basic unit stuff
//---------------------------------------------------------------------------
/// What is the contribution of unit-of-measure constant ucref to unit-of-measure expression measure?
let rec MeasureExprConExponent g abbrev ucref unt =
match (if abbrev then stripUnitEqnsFromMeasure unt else stripUnitEqns unt) with
| Measure.Const ucrefR -> if tyconRefEq g ucrefR ucref then OneRational else ZeroRational
| Measure.Inv untR -> NegRational(MeasureExprConExponent g abbrev ucref untR)
| Measure.Prod(unt1, unt2) -> AddRational(MeasureExprConExponent g abbrev ucref unt1) (MeasureExprConExponent g abbrev ucref unt2)
| Measure.RationalPower(untR, q) -> MulRational (MeasureExprConExponent g abbrev ucref untR) q
| _ -> ZeroRational
/// What is the contribution of unit-of-measure constant ucref to unit-of-measure expression measure
/// after remapping tycons?
let rec MeasureConExponentAfterRemapping g r ucref unt =
match stripUnitEqnsFromMeasure unt with
| Measure.Const ucrefR -> if tyconRefEq g (r ucrefR) ucref then OneRational else ZeroRational
| Measure.Inv untR -> NegRational(MeasureConExponentAfterRemapping g r ucref untR)
| Measure.Prod(unt1, unt2) -> AddRational(MeasureConExponentAfterRemapping g r ucref unt1) (MeasureConExponentAfterRemapping g r ucref unt2)
| Measure.RationalPower(untR, q) -> MulRational (MeasureConExponentAfterRemapping g r ucref untR) q
| _ -> ZeroRational
/// What is the contribution of unit-of-measure variable tp to unit-of-measure expression unt?
let rec MeasureVarExponent tp unt =
match stripUnitEqnsFromMeasure unt with
| Measure.Var tpR -> if typarEq tp tpR then OneRational else ZeroRational
| Measure.Inv untR -> NegRational(MeasureVarExponent tp untR)
| Measure.Prod(unt1, unt2) -> AddRational(MeasureVarExponent tp unt1) (MeasureVarExponent tp unt2)
| Measure.RationalPower(untR, q) -> MulRational (MeasureVarExponent tp untR) q
| _ -> ZeroRational
/// List the *literal* occurrences of unit variables in a unit expression, without repeats
let ListMeasureVarOccs unt =
let rec gather acc unt =
match stripUnitEqnsFromMeasure unt with
| Measure.Var tp -> if List.exists (typarEq tp) acc then acc else tp :: acc
| Measure.Prod(unt1, unt2) -> gather (gather acc unt1) unt2
| Measure.RationalPower(untR, _) -> gather acc untR
| Measure.Inv untR -> gather acc untR
| _ -> acc
gather [] unt
/// List the *observable* occurrences of unit variables in a unit expression, without repeats, paired with their non-zero exponents
let ListMeasureVarOccsWithNonZeroExponents untexpr =
let rec gather acc unt =
match stripUnitEqnsFromMeasure unt with
| Measure.Var tp ->
if List.exists (fun (tpR, _) -> typarEq tp tpR) acc then acc
else
let e = MeasureVarExponent tp untexpr
if e = ZeroRational then acc else (tp, e) :: acc
| Measure.Prod(unt1, unt2) -> gather (gather acc unt1) unt2
| Measure.Inv untR -> gather acc untR
| Measure.RationalPower(untR, _) -> gather acc untR
| _ -> acc
gather [] untexpr
/// List the *observable* occurrences of unit constants in a unit expression, without repeats, paired with their non-zero exponents
let ListMeasureConOccsWithNonZeroExponents g eraseAbbrevs untexpr =
let rec gather acc unt =
match (if eraseAbbrevs then stripUnitEqnsFromMeasure unt else stripUnitEqns unt) with
| Measure.Const c ->
if List.exists (fun (cR, _) -> tyconRefEq g c cR) acc then acc else
let e = MeasureExprConExponent g eraseAbbrevs c untexpr
if e = ZeroRational then acc else (c, e) :: acc
| Measure.Prod(unt1, unt2) -> gather (gather acc unt1) unt2
| Measure.Inv untR -> gather acc untR
| Measure.RationalPower(untR, _) -> gather acc untR
| _ -> acc
gather [] untexpr
/// List the *literal* occurrences of unit constants in a unit expression, without repeats,
/// and after applying a remapping function r to tycons
let ListMeasureConOccsAfterRemapping g r unt =
let rec gather acc unt =
match stripUnitEqnsFromMeasure unt with
| Measure.Const c -> if List.exists (tyconRefEq g (r c)) acc then acc else r c :: acc
| Measure.Prod(unt1, unt2) -> gather (gather acc unt1) unt2
| Measure.RationalPower(untR, _) -> gather acc untR
| Measure.Inv untR -> gather acc untR
| _ -> acc
gather [] unt
/// Construct a measure expression representing the n'th power of a measure
let MeasurePower u n =
if n = 1 then u
elif n = 0 then Measure.One
else Measure.RationalPower (u, intToRational n)
let MeasureProdOpt m1 m2 =
match m1, m2 with
| Measure.One, _ -> m2
| _, Measure.One -> m1
| _, _ -> Measure.Prod (m1, m2)
/// Construct a measure expression representing the product of a list of measures
let ProdMeasures ms =
match ms with
| [] -> Measure.One
| m :: ms -> List.foldBack MeasureProdOpt ms m
let isDimensionless g ty =
match stripTyparEqns ty with
| TType_measure unt ->
isNil (ListMeasureVarOccsWithNonZeroExponents unt) &&
isNil (ListMeasureConOccsWithNonZeroExponents g true unt)
| _ -> false
let destUnitParMeasure g unt =
let vs = ListMeasureVarOccsWithNonZeroExponents unt
let cs = ListMeasureConOccsWithNonZeroExponents g true unt
match vs, cs with
| [(v, e)], [] when e = OneRational -> v
| _, _ -> failwith "destUnitParMeasure: not a unit-of-measure parameter"
let isUnitParMeasure g unt =
let vs = ListMeasureVarOccsWithNonZeroExponents unt
let cs = ListMeasureConOccsWithNonZeroExponents g true unt
match vs, cs with
| [(_, e)], [] when e = OneRational -> true
| _, _ -> false
let normalizeMeasure g ms =
let vs = ListMeasureVarOccsWithNonZeroExponents ms
let cs = ListMeasureConOccsWithNonZeroExponents g false ms
match vs, cs with
| [], [] -> Measure.One
| [(v, e)], [] when e = OneRational -> Measure.Var v
| vs, cs -> List.foldBack (fun (v, e) -> fun m -> Measure.Prod (Measure.RationalPower (Measure.Var v, e), m)) vs (List.foldBack (fun (c, e) -> fun m -> Measure.Prod (Measure.RationalPower (Measure.Const c, e), m)) cs Measure.One)
let tryNormalizeMeasureInType g ty =
match ty with
| TType_measure (Measure.Var v) ->
match v.Solution with
| Some (TType_measure ms) ->
v.typar_solution <- Some (TType_measure (normalizeMeasure g ms))
ty
| _ -> ty
| _ -> ty
//---------------------------------------------------------------------------
// Some basic type builders
//---------------------------------------------------------------------------
let mkNativePtrTy (g: TcGlobals) ty =
assert g.nativeptr_tcr.CanDeref // this should always be available, but check anyway
TType_app (g.nativeptr_tcr, [ty], g.knownWithoutNull)
let mkByrefTy (g: TcGlobals) ty =
assert g.byref_tcr.CanDeref // this should always be available, but check anyway
TType_app (g.byref_tcr, [ty], g.knownWithoutNull)
let mkInByrefTy (g: TcGlobals) ty =
if g.inref_tcr.CanDeref then // If not using sufficient FSharp.Core, then inref<T> = byref<T>, see RFC FS-1053.md
TType_app (g.inref_tcr, [ty], g.knownWithoutNull)
else
mkByrefTy g ty
let mkOutByrefTy (g: TcGlobals) ty =
if g.outref_tcr.CanDeref then // If not using sufficient FSharp.Core, then outref<T> = byref<T>, see RFC FS-1053.md
TType_app (g.outref_tcr, [ty], g.knownWithoutNull)
else
mkByrefTy g ty
let mkByrefTyWithFlag g readonly ty =
if readonly then
mkInByrefTy g ty
else
mkByrefTy g ty
let mkByref2Ty (g: TcGlobals) ty1 ty2 =
assert g.byref2_tcr.CanDeref // check we are using sufficient FSharp.Core, caller should check this
TType_app (g.byref2_tcr, [ty1; ty2], g.knownWithoutNull)
let mkVoidPtrTy (g: TcGlobals) =
assert g.voidptr_tcr.CanDeref // check we are using sufficient FSharp.Core, caller should check this
TType_app (g.voidptr_tcr, [], g.knownWithoutNull)
let mkByrefTyWithInference (g: TcGlobals) ty1 ty2 =
if g.byref2_tcr.CanDeref then // If not using sufficient FSharp.Core, then inref<T> = byref<T>, see RFC FS-1053.md
TType_app (g.byref2_tcr, [ty1; ty2], g.knownWithoutNull)
else
TType_app (g.byref_tcr, [ty1], g.knownWithoutNull)
let mkArrayTy (g: TcGlobals) rank ty m =
if rank < 1 || rank > 32 then
errorR(Error(FSComp.SR.tastopsMaxArrayThirtyTwo rank, m))
TType_app (g.il_arr_tcr_map[3], [ty], g.knownWithoutNull)
else
TType_app (g.il_arr_tcr_map[rank - 1], [ty], g.knownWithoutNull)
//--------------------------------------------------------------------------
// Tuple compilation (types)
//------------------------------------------------------------------------
let maxTuple = 8
let goodTupleFields = maxTuple-1
let isCompiledTupleTyconRef g tcref =
tyconRefEq g g.ref_tuple1_tcr tcref ||
tyconRefEq g g.ref_tuple2_tcr tcref ||
tyconRefEq g g.ref_tuple3_tcr tcref ||
tyconRefEq g g.ref_tuple4_tcr tcref ||
tyconRefEq g g.ref_tuple5_tcr tcref ||
tyconRefEq g g.ref_tuple6_tcr tcref ||
tyconRefEq g g.ref_tuple7_tcr tcref ||
tyconRefEq g g.ref_tuple8_tcr tcref ||
tyconRefEq g g.struct_tuple1_tcr tcref ||
tyconRefEq g g.struct_tuple2_tcr tcref ||
tyconRefEq g g.struct_tuple3_tcr tcref ||
tyconRefEq g g.struct_tuple4_tcr tcref ||
tyconRefEq g g.struct_tuple5_tcr tcref ||
tyconRefEq g g.struct_tuple6_tcr tcref ||
tyconRefEq g g.struct_tuple7_tcr tcref ||
tyconRefEq g g.struct_tuple8_tcr tcref
let mkCompiledTupleTyconRef (g: TcGlobals) isStruct n =
if n = 1 then (if isStruct then g.struct_tuple1_tcr else g.ref_tuple1_tcr)
elif n = 2 then (if isStruct then g.struct_tuple2_tcr else g.ref_tuple2_tcr)
elif n = 3 then (if isStruct then g.struct_tuple3_tcr else g.ref_tuple3_tcr)
elif n = 4 then (if isStruct then g.struct_tuple4_tcr else g.ref_tuple4_tcr)
elif n = 5 then (if isStruct then g.struct_tuple5_tcr else g.ref_tuple5_tcr)
elif n = 6 then (if isStruct then g.struct_tuple6_tcr else g.ref_tuple6_tcr)
elif n = 7 then (if isStruct then g.struct_tuple7_tcr else g.ref_tuple7_tcr)
elif n = 8 then (if isStruct then g.struct_tuple8_tcr else g.ref_tuple8_tcr)
else failwithf "mkCompiledTupleTyconRef, n = %d" n
/// Convert from F# tuple types to .NET tuple types
let rec mkCompiledTupleTy g isStruct tupElemTys =
let n = List.length tupElemTys
if n < maxTuple then
TType_app (mkCompiledTupleTyconRef g isStruct n, tupElemTys, g.knownWithoutNull)
else
let tysA, tysB = List.splitAfter goodTupleFields tupElemTys
TType_app ((if isStruct then g.struct_tuple8_tcr else g.ref_tuple8_tcr), tysA@[mkCompiledTupleTy g isStruct tysB], g.knownWithoutNull)
/// Convert from F# tuple types to .NET tuple types, but only the outermost level
let mkOuterCompiledTupleTy g isStruct tupElemTys =
let n = List.length tupElemTys
if n < maxTuple then
TType_app (mkCompiledTupleTyconRef g isStruct n, tupElemTys, g.knownWithoutNull)
else
let tysA, tysB = List.splitAfter goodTupleFields tupElemTys
let tcref = (if isStruct then g.struct_tuple8_tcr else g.ref_tuple8_tcr)
// In the case of an 8-tuple we add the Tuple<_> marker. For other sizes we keep the type
// as a regular F# tuple type.
match tysB with
| [ tyB ] ->
let marker = TType_app (mkCompiledTupleTyconRef g isStruct 1, [tyB], g.knownWithoutNull)
TType_app (tcref, tysA@[marker], g.knownWithoutNull)
| _ ->
TType_app (tcref, tysA@[TType_tuple (mkTupInfo isStruct, tysB)], g.knownWithoutNull)
//---------------------------------------------------------------------------
// Remove inference equations and abbreviations from types
//---------------------------------------------------------------------------
let applyTyconAbbrev abbrevTy tycon tyargs =
if isNil tyargs then abbrevTy
else instType (mkTyconInst tycon tyargs) abbrevTy
let reduceTyconAbbrev (tycon: Tycon) tyargs =
let abbrev = tycon.TypeAbbrev
match abbrev with
| None -> invalidArg "tycon" "this type definition is not an abbreviation"
| Some abbrevTy ->
applyTyconAbbrev abbrevTy tycon tyargs
let reduceTyconRefAbbrev (tcref: TyconRef) tyargs =
reduceTyconAbbrev tcref.Deref tyargs
let reduceTyconMeasureableOrProvided (g: TcGlobals) (tycon: Tycon) tyargs =
#if NO_TYPEPROVIDERS
ignore g // otherwise g would be unused
#endif
let repr = tycon.TypeReprInfo
match repr with
| TMeasureableRepr ty ->
if isNil tyargs then ty else instType (mkTyconInst tycon tyargs) ty
#if !NO_TYPEPROVIDERS
| TProvidedTypeRepr info when info.IsErased -> info.BaseTypeForErased (range0, g.obj_ty)
#endif
| _ -> invalidArg "tc" "this type definition is not a refinement"
let reduceTyconRefMeasureableOrProvided (g: TcGlobals) (tcref: TyconRef) tyargs =
reduceTyconMeasureableOrProvided g tcref.Deref tyargs
let rec stripTyEqnsA g canShortcut ty =
let ty = stripTyparEqnsAux canShortcut ty
match ty with
| TType_app (tcref, tinst, _) ->
let tycon = tcref.Deref
match tycon.TypeAbbrev with
| Some abbrevTy ->
stripTyEqnsA g canShortcut (applyTyconAbbrev abbrevTy tycon tinst)
| None ->
// This is the point where we get to add additional conditional normalizing equations
// into the type system. Such power!
//
// Add the equation byref<'T> = byref<'T, ByRefKinds.InOut> for when using sufficient FSharp.Core
// See RFC FS-1053.md
if tyconRefEq g tcref g.byref_tcr && g.byref2_tcr.CanDeref && g.byrefkind_InOut_tcr.CanDeref then
mkByref2Ty g tinst[0] (TType_app(g.byrefkind_InOut_tcr, [], g.knownWithoutNull))
// Add the equation double<1> = double for units of measure.
elif tycon.IsMeasureableReprTycon && List.forall (isDimensionless g) tinst then
stripTyEqnsA g canShortcut (reduceTyconMeasureableOrProvided g tycon tinst)
else
ty
| ty -> ty
let stripTyEqns g ty = stripTyEqnsA g false ty
let evalTupInfoIsStruct aexpr =
match aexpr with
| TupInfo.Const b -> b
let evalAnonInfoIsStruct (anonInfo: AnonRecdTypeInfo) =
evalTupInfoIsStruct anonInfo.TupInfo
/// This erases outermost occurrences of inference equations, type abbreviations, non-generated provided types
/// and measureable types (float<_>).
/// It also optionally erases all "compilation representations", i.e. function and
/// tuple types, and also "nativeptr<'T> --> System.IntPtr"
let rec stripTyEqnsAndErase eraseFuncAndTuple (g: TcGlobals) ty =
let ty = stripTyEqns g ty
match ty with
| TType_app (tcref, args, _) ->
let tycon = tcref.Deref
if tycon.IsErased then
stripTyEqnsAndErase eraseFuncAndTuple g (reduceTyconMeasureableOrProvided g tycon args)
elif tyconRefEq g tcref g.nativeptr_tcr && eraseFuncAndTuple then
stripTyEqnsAndErase eraseFuncAndTuple g g.nativeint_ty
else
ty
| TType_fun(domainTy, rangeTy, flags) when eraseFuncAndTuple ->
TType_app(g.fastFunc_tcr, [ domainTy; rangeTy ], flags)
| TType_tuple(tupInfo, l) when eraseFuncAndTuple ->
mkCompiledTupleTy g (evalTupInfoIsStruct tupInfo) l
| ty -> ty
let stripTyEqnsAndMeasureEqns g ty =
stripTyEqnsAndErase false g ty
type Erasure = EraseAll | EraseMeasures | EraseNone
let stripTyEqnsWrtErasure erasureFlag g ty =
match erasureFlag with
| EraseAll -> stripTyEqnsAndErase true g ty
| EraseMeasures -> stripTyEqnsAndErase false g ty
| _ -> stripTyEqns g ty
let rec stripExnEqns (eref: TyconRef) =
let exnc = eref.Deref
match exnc.ExceptionInfo with
| TExnAbbrevRepr eref -> stripExnEqns eref
| _ -> exnc
let primDestForallTy g ty = ty |> stripTyEqns g |> (function TType_forall (tyvs, tau) -> (tyvs, tau) | _ -> failwith "primDestForallTy: not a forall type")
let destFunTy g ty = ty |> stripTyEqns g |> (function TType_fun (domainTy, rangeTy, _) -> (domainTy, rangeTy) | _ -> failwith "destFunTy: not a function type")
let destAnyTupleTy g ty = ty |> stripTyEqns g |> (function TType_tuple (tupInfo, l) -> tupInfo, l | _ -> failwith "destAnyTupleTy: not a tuple type")
let destRefTupleTy g ty = ty |> stripTyEqns g |> (function TType_tuple (tupInfo, l) when not (evalTupInfoIsStruct tupInfo) -> l | _ -> failwith "destRefTupleTy: not a reference tuple type")
let destStructTupleTy g ty = ty |> stripTyEqns g |> (function TType_tuple (tupInfo, l) when evalTupInfoIsStruct tupInfo -> l | _ -> failwith "destStructTupleTy: not a struct tuple type")
let destTyparTy g ty = ty |> stripTyEqns g |> (function TType_var (v, _) -> v | _ -> failwith "destTyparTy: not a typar type")
let destAnyParTy g ty = ty |> stripTyEqns g |> (function TType_var (v, _) -> v | TType_measure unt -> destUnitParMeasure g unt | _ -> failwith "destAnyParTy: not a typar or unpar type")
let destMeasureTy g ty = ty |> stripTyEqns g |> (function TType_measure m -> m | _ -> failwith "destMeasureTy: not a unit-of-measure type")
let destAnonRecdTy g ty = ty |> stripTyEqns g |> (function TType_anon (anonInfo, tys) -> anonInfo, tys | _ -> failwith "destAnonRecdTy: not an anonymous record type")
let destStructAnonRecdTy g ty = ty |> stripTyEqns g |> (function TType_anon (anonInfo, tys) when evalAnonInfoIsStruct anonInfo -> tys | _ -> failwith "destAnonRecdTy: not a struct anonymous record type")
let isFunTy g ty = ty |> stripTyEqns g |> (function TType_fun _ -> true | _ -> false)
let isForallTy g ty = ty |> stripTyEqns g |> (function TType_forall _ -> true | _ -> false)
let isAnyTupleTy g ty = ty |> stripTyEqns g |> (function TType_tuple _ -> true | _ -> false)
let isRefTupleTy g ty = ty |> stripTyEqns g |> (function TType_tuple (tupInfo, _) -> not (evalTupInfoIsStruct tupInfo) | _ -> false)
let isStructTupleTy g ty = ty |> stripTyEqns g |> (function TType_tuple (tupInfo, _) -> evalTupInfoIsStruct tupInfo | _ -> false)
let isAnonRecdTy g ty = ty |> stripTyEqns g |> (function TType_anon _ -> true | _ -> false)
let isStructAnonRecdTy g ty = ty |> stripTyEqns g |> (function TType_anon (anonInfo, _) -> evalAnonInfoIsStruct anonInfo | _ -> false)
let isUnionTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _, _) -> tcref.IsUnionTycon | _ -> false)
let isStructUnionTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _, _) -> tcref.IsUnionTycon && tcref.Deref.entity_flags.IsStructRecordOrUnionType | _ -> false)
let isReprHiddenTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _, _) -> tcref.IsHiddenReprTycon | _ -> false)
let isFSharpObjModelTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _, _) -> tcref.IsFSharpObjectModelTycon | _ -> false)
let isRecdTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _, _) -> tcref.IsRecordTycon | _ -> false)
let isFSharpStructOrEnumTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _, _) -> tcref.IsFSharpStructOrEnumTycon | _ -> false)
let isFSharpEnumTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _, _) -> tcref.IsFSharpEnumTycon | _ -> false)
let isTyparTy g ty = ty |> stripTyEqns g |> (function TType_var _ -> true | _ -> false)
let isAnyParTy g ty = ty |> stripTyEqns g |> (function TType_var _ -> true | TType_measure unt -> isUnitParMeasure g unt | _ -> false)
let isMeasureTy g ty = ty |> stripTyEqns g |> (function TType_measure _ -> true | _ -> false)
let isProvenUnionCaseTy ty = match ty with TType_ucase _ -> true | _ -> false
let mkAppTy tcref tyargs = TType_app(tcref, tyargs, 0uy)
let mkProvenUnionCaseTy ucref tyargs = TType_ucase(ucref, tyargs)
let isAppTy g ty = ty |> stripTyEqns g |> (function TType_app _ -> true | _ -> false)
let tryAppTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, tinst, _) -> ValueSome (tcref, tinst) | _ -> ValueNone)
let destAppTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, tinst, _) -> tcref, tinst | _ -> failwith "destAppTy")
let tcrefOfAppTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _, _) -> tcref | _ -> failwith "tcrefOfAppTy")
let argsOfAppTy g ty = ty |> stripTyEqns g |> (function TType_app(_, tinst, _) -> tinst | _ -> [])
let tryDestTyparTy g ty = ty |> stripTyEqns g |> (function TType_var (v, _) -> ValueSome v | _ -> ValueNone)
let tryDestFunTy g ty = ty |> stripTyEqns g |> (function TType_fun (domainTy, rangeTy, _) -> ValueSome(domainTy, rangeTy) | _ -> ValueNone)
let tryTcrefOfAppTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _, _) -> ValueSome tcref | _ -> ValueNone)
let tryDestAnonRecdTy g ty = ty |> stripTyEqns g |> (function TType_anon (anonInfo, tys) -> ValueSome (anonInfo, tys) | _ -> ValueNone)
let tryAnyParTy g ty = ty |> stripTyEqns g |> (function TType_var (v, _) -> ValueSome v | TType_measure unt when isUnitParMeasure g unt -> ValueSome(destUnitParMeasure g unt) | _ -> ValueNone)
let tryAnyParTyOption g ty = ty |> stripTyEqns g |> (function TType_var (v, _) -> Some v | TType_measure unt when isUnitParMeasure g unt -> Some(destUnitParMeasure g unt) | _ -> None)
let (|AppTy|_|) g ty = ty |> stripTyEqns g |> (function TType_app(tcref, tinst, _) -> Some (tcref, tinst) | _ -> None)
let (|RefTupleTy|_|) g ty = ty |> stripTyEqns g |> (function TType_tuple(tupInfo, tys) when not (evalTupInfoIsStruct tupInfo) -> Some tys | _ -> None)
let (|FunTy|_|) g ty = ty |> stripTyEqns g |> (function TType_fun(domainTy, rangeTy, _) -> Some (domainTy, rangeTy) | _ -> None)
let tryNiceEntityRefOfTy ty =
let ty = stripTyparEqnsAux false ty
match ty with
| TType_app (tcref, _, _) -> ValueSome tcref
| TType_measure (Measure.Const tcref) -> ValueSome tcref
| _ -> ValueNone
let tryNiceEntityRefOfTyOption ty =
let ty = stripTyparEqnsAux false ty
match ty with
| TType_app (tcref, _, _) -> Some tcref
| TType_measure (Measure.Const tcref) -> Some tcref
| _ -> None
let mkInstForAppTy g ty =
match tryAppTy g ty with
| ValueSome (tcref, tinst) -> mkTyconRefInst tcref tinst
| _ -> []
let domainOfFunTy g ty = fst (destFunTy g ty)
let rangeOfFunTy g ty = snd (destFunTy g ty)
let convertToTypeWithMetadataIfPossible g ty =
if isAnyTupleTy g ty then
let tupInfo, tupElemTys = destAnyTupleTy g ty
mkOuterCompiledTupleTy g (evalTupInfoIsStruct tupInfo) tupElemTys
elif isFunTy g ty then
let a,b = destFunTy g ty
mkAppTy g.fastFunc_tcr [a; b]
else ty
//---------------------------------------------------------------------------
// TType modifications
//---------------------------------------------------------------------------
let stripMeasuresFromTy g ty =
match ty with
| TType_app(tcref, tinst, flags) ->
let tinstR = tinst |> List.filter (isMeasureTy g >> not)
TType_app(tcref, tinstR, flags)
| _ -> ty
//---------------------------------------------------------------------------
// Equivalence of types up to alpha-equivalence
//---------------------------------------------------------------------------
[<NoEquality; NoComparison>]
type TypeEquivEnv =
{ EquivTypars: TyparMap<TType>
EquivTycons: TyconRefRemap}
// allocate a singleton
let typeEquivEnvEmpty =
{ EquivTypars = TyparMap.Empty
EquivTycons = emptyTyconRefRemap }
type TypeEquivEnv with
static member Empty = typeEquivEnvEmpty
member aenv.BindTyparsToTypes tps1 tys2 =
{ aenv with EquivTypars = (tps1, tys2, aenv.EquivTypars) |||> List.foldBack2 (fun tp ty tpmap -> tpmap.Add(tp, ty)) }
member aenv.BindEquivTypars tps1 tps2 =
aenv.BindTyparsToTypes tps1 (List.map mkTyparTy tps2)
static member FromTyparInst tpinst =
let tps, tys = List.unzip tpinst
TypeEquivEnv.Empty.BindTyparsToTypes tps tys
static member FromEquivTypars tps1 tps2 =
TypeEquivEnv.Empty.BindEquivTypars tps1 tps2
let rec traitsAEquivAux erasureFlag g aenv traitInfo1 traitInfo2 =
let (TTrait(tys1, nm, mf1, argTys, retTy, _, _)) = traitInfo1
let (TTrait(tys2, nm2, mf2, argTys2, retTy2, _, _)) = traitInfo2
mf1.IsInstance = mf2.IsInstance &&
nm = nm2 &&
ListSet.equals (typeAEquivAux erasureFlag g aenv) tys1 tys2 &&
returnTypesAEquivAux erasureFlag g aenv retTy retTy2 &&
List.lengthsEqAndForall2 (typeAEquivAux erasureFlag g aenv) argTys argTys2
and traitKeysAEquivAux erasureFlag g aenv witnessInfo1 witnessInfo2 =
let (TraitWitnessInfo(tys1, nm, mf1, argTys, retTy)) = witnessInfo1
let (TraitWitnessInfo(tys2, nm2, mf2, argTys2, retTy2)) = witnessInfo2
mf1.IsInstance = mf2.IsInstance &&
nm = nm2 &&
ListSet.equals (typeAEquivAux erasureFlag g aenv) tys1 tys2 &&
returnTypesAEquivAux erasureFlag g aenv retTy retTy2 &&
List.lengthsEqAndForall2 (typeAEquivAux erasureFlag g aenv) argTys argTys2
and returnTypesAEquivAux erasureFlag g aenv retTy retTy2 =
match retTy, retTy2 with
| None, None -> true
| Some ty1, Some ty2 -> typeAEquivAux erasureFlag g aenv ty1 ty2
| _ -> false
and typarConstraintsAEquivAux erasureFlag g aenv tpc1 tpc2 =
match tpc1, tpc2 with
| TyparConstraint.CoercesTo(tgtTy1, _),
TyparConstraint.CoercesTo(tgtTy2, _) ->
typeAEquivAux erasureFlag g aenv tgtTy1 tgtTy2
| TyparConstraint.MayResolveMember(trait1, _),
TyparConstraint.MayResolveMember(trait2, _) ->
traitsAEquivAux erasureFlag g aenv trait1 trait2
| TyparConstraint.DefaultsTo(_, dfltTy1, _),
TyparConstraint.DefaultsTo(_, dfltTy2, _) ->
typeAEquivAux erasureFlag g aenv dfltTy1 dfltTy2