-
Notifications
You must be signed in to change notification settings - Fork 855
Expand file tree
/
Copy pathTypedTree.fs
More file actions
6477 lines (5071 loc) · 287 KB
/
TypedTree.fs
File metadata and controls
6477 lines (5071 loc) · 287 KB
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 the typed abstract syntax intermediate representation used throughout the F# compiler.
module internal rec FSharp.Compiler.TypedTree
open System
open System.Collections.Generic
open System.Collections.Immutable
open System.Diagnostics
open Internal.Utilities.Collections
open Internal.Utilities.Library
open Internal.Utilities.Library.Extras
open Internal.Utilities.Rational
open FSharp.Compiler
open FSharp.Compiler.AbstractIL.IL
open FSharp.Compiler.AbstractIL.ILX.Types
open FSharp.Compiler.CompilerGlobalState
open FSharp.Compiler.DiagnosticsLogger
open FSharp.Compiler.Syntax
open FSharp.Compiler.Syntax.PrettyNaming
open FSharp.Compiler.QuotationPickler
open FSharp.Compiler.SyntaxTreeOps
open FSharp.Compiler.Text
open FSharp.Compiler.Text.Range
open FSharp.Compiler.Xml
#if !NO_TYPEPROVIDERS
open FSharp.Compiler.TypeProviders
open FSharp.Core.CompilerServices
#endif
[<RequireQualifiedAccess>]
module WellKnownNames =
/// Special name for the defensive copy of a struct, we use it in situations like when we get an address of a field in ax-assembly scenario.
let [<Literal>] CopyOfStruct = "copyOfStruct"
type Stamp = int64
type StampMap<'T> = Map<Stamp, 'T>
[<RequireQualifiedAccess>]
type ValInline =
/// Indicates the value is inlined but the .NET IL code for the function still exists, e.g. to satisfy interfaces on objects, but that it is also always inlined
| Always
/// Indicates the value may optionally be inlined by the optimizer
| Optional
/// Indicates the value must never be inlined by the optimizer
| Never
/// Returns true if the implementation of a value should be inlined
member x.ShouldInline =
match x with
| ValInline.Always -> true
| ValInline.Optional | ValInline.Never -> false
/// A flag associated with values that indicates whether the recursive scope of the value is currently being processed, and
/// if the value has been generalized or not as yet.
type ValRecursiveScopeInfo =
/// Set while the value is within its recursive scope. The flag indicates if the value has been eagerly generalized and accepts generic-recursive calls
| ValInRecScope of bool
/// The normal value for this flag when the value is not within its recursive scope
| ValNotInRecScope
type ValMutability =
| Immutable
| Mutable
/// Indicates if a type parameter is needed at runtime and may not be eliminated
[<RequireQualifiedAccess>]
type TyparDynamicReq =
/// Indicates the type parameter is not needed at runtime and may be eliminated
| No
/// Indicates the type parameter is needed at runtime and may not be eliminated
| Yes
type ValBaseOrThisInfo =
/// Indicates a ref-cell holding 'this' or the implicit 'this' used throughout an
/// implicit constructor to access and set values
| CtorThisVal
/// Indicates the value called 'base' available for calling base class members
| BaseVal
/// Indicates a normal value
| NormalVal
/// Indicates the 'this' value specified in a member e.g. 'x' in 'member x.M() = 1'
| MemberThisVal
/// Flags on values
[<Struct>]
type ValFlags(flags: int64) =
new (recValInfo, baseOrThis, isCompGen, inlineInfo, isMutable, isModuleOrMemberBinding, isExtensionMember, isIncrClassSpecialMember, isTyFunc, allowTypeInst, isGeneratedEventVal) =
let flags =
(match baseOrThis with
| BaseVal -> 0b00000000000000000000L
| CtorThisVal -> 0b00000000000000000010L
| NormalVal -> 0b00000000000000000100L
| MemberThisVal -> 0b00000000000000000110L) |||
(if isCompGen then 0b00000000000000001000L
else 0b000000000000000000000L) |||
(match inlineInfo with
| ValInline.Always -> 0b00000000000000010000L
| ValInline.Optional -> 0b00000000000000100000L
| ValInline.Never -> 0b00000000000000110000L) |||
(match isMutable with
| Immutable -> 0b00000000000000000000L
| Mutable -> 0b00000000000001000000L) |||
(match isModuleOrMemberBinding with
| false -> 0b00000000000000000000L
| true -> 0b00000000000010000000L) |||
(match isExtensionMember with
| false -> 0b00000000000000000000L
| true -> 0b00000000000100000000L) |||
(match isIncrClassSpecialMember with
| false -> 0b00000000000000000000L
| true -> 0b00000000001000000000L) |||
(match isTyFunc with
| false -> 0b00000000000000000000L
| true -> 0b00000000010000000000L) |||
(match recValInfo with
| ValNotInRecScope -> 0b00000000000000000000L
| ValInRecScope true -> 0b00000000100000000000L
| ValInRecScope false -> 0b00000001000000000000L) |||
(match allowTypeInst with
| false -> 0b00000000000000000000L
| true -> 0b00000100000000000000L) |||
(match isGeneratedEventVal with
| false -> 0b00000000000000000000L
| true -> 0b00100000000000000000L)
ValFlags flags
member x.BaseOrThisInfo =
match (flags &&& 0b00000000000000000110L) with
| 0b00000000000000000000L -> BaseVal
| 0b00000000000000000010L -> CtorThisVal
| 0b00000000000000000100L -> NormalVal
| 0b00000000000000000110L -> MemberThisVal
| _ -> failwith "unreachable"
member x.IsCompilerGenerated = (flags &&& 0b00000000000000001000L) <> 0x0L
member x.WithIsCompilerGenerated isCompGen =
let flags = (flags &&& ~~~0b00000000000000001000L) |||
(match isCompGen with
| false -> 0b00000000000000000000L
| true -> 0b00000000000000001000L)
ValFlags flags
member x.InlineInfo =
match (flags &&& 0b00000000000000110000L) with
| 0b00000000000000000000L
| 0b00000000000000010000L -> ValInline.Always
| 0b00000000000000100000L -> ValInline.Optional
| 0b00000000000000110000L -> ValInline.Never
| _ -> failwith "unreachable"
member x.MutabilityInfo =
match (flags &&& 0b00000000000001000000L) with
| 0b00000000000000000000L -> Immutable
| 0b00000000000001000000L -> Mutable
| _ -> failwith "unreachable"
member x.IsMemberOrModuleBinding =
match (flags &&& 0b00000000000010000000L) with
| 0b00000000000000000000L -> false
| 0b00000000000010000000L -> true
| _ -> failwith "unreachable"
member x.WithIsMemberOrModuleBinding = ValFlags(flags ||| 0b00000000000010000000L)
member x.IsExtensionMember = (flags &&& 0b00000000000100000000L) <> 0L
member x.IsIncrClassSpecialMember = (flags &&& 0b00000000001000000000L) <> 0L
member x.IsTypeFunction = (flags &&& 0b00000000010000000000L) <> 0L
member x.RecursiveValInfo = match (flags &&& 0b00000001100000000000L) with
| 0b00000000000000000000L -> ValNotInRecScope
| 0b00000000100000000000L -> ValInRecScope true
| 0b00000001000000000000L -> ValInRecScope false
| _ -> failwith "unreachable"
member x.WithRecursiveValInfo recValInfo =
let flags =
(flags &&& ~~~0b00000001100000000000L) |||
(match recValInfo with
| ValNotInRecScope -> 0b00000000000000000000L
| ValInRecScope true -> 0b00000000100000000000L
| ValInRecScope false -> 0b00000001000000000000L)
ValFlags flags
member x.MakesNoCriticalTailcalls = (flags &&& 0b00000010000000000000L) <> 0L
member x.WithMakesNoCriticalTailcalls = ValFlags(flags ||| 0b00000010000000000000L)
member x.PermitsExplicitTypeInstantiation = (flags &&& 0b00000100000000000000L) <> 0L
member x.HasBeenReferenced = (flags &&& 0b00001000000000000000L) <> 0L
member x.WithHasBeenReferenced = ValFlags(flags ||| 0b00001000000000000000L)
member x.IsCompiledAsStaticPropertyWithoutField = (flags &&& 0b00010000000000000000L) <> 0L
member x.WithIsCompiledAsStaticPropertyWithoutField = ValFlags(flags ||| 0b00010000000000000000L)
member x.IsGeneratedEventVal = (flags &&& 0b00100000000000000000L) <> 0L
member x.IsFixed = (flags &&& 0b01000000000000000000L) <> 0L
member x.WithIsFixed = ValFlags(flags ||| 0b01000000000000000000L)
member x.IgnoresByrefScope = (flags &&& 0b10000000000000000000L) <> 0L
member x.WithIgnoresByrefScope = ValFlags(flags ||| 0b10000000000000000000L)
member x.InlineIfLambda = (flags &&& 0b100000000000000000000L) <> 0L
member x.WithInlineIfLambda = ValFlags(flags ||| 0b100000000000000000000L)
member x.IsImplied = (flags &&& 0b1000000000000000000000L) <> 0L
member x.WithIsImplied = ValFlags(flags ||| 0b1000000000000000000000L)
/// Get the flags as included in the F# binary metadata
member x.PickledBits =
// Clear the RecursiveValInfo, only used during inference and irrelevant across assembly boundaries
// Clear the IsCompiledAsStaticPropertyWithoutField, only used to determine whether to use a true field for a value, and to eliminate the optimization info for observable bindings
// Clear the HasBeenReferenced, only used to report "unreferenced variable" warnings and to help collect 'it' values in FSI.EXE
// Clear the IsGeneratedEventVal, since there's no use in propagating specialname information for generated add/remove event vals
(flags &&& ~~~0b010011001100000000000L)
/// Represents the kind of a type parameter
[<RequireQualifiedAccess (* ; StructuredFormatDisplay("{DebugText}") *) >]
type TyparKind =
| Type
| Measure
member x.AttrName =
match x with
| TyparKind.Type -> ValueNone
| TyparKind.Measure -> ValueSome "Measure"
//[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
//member x.DebugText = x.ToString()
override x.ToString() =
match x with
| TyparKind.Type -> "type"
| TyparKind.Measure -> "measure"
/// Indicates if the type variable can be solved or given new constraints. The status of a type variable
/// evolves towards being either rigid or solved.
[<RequireQualifiedAccess>]
type TyparRigidity =
/// Indicates the type parameter can't be solved
| Rigid
/// Indicates the type parameter can't be solved, but the variable is not set to "rigid" until after inference is complete
| WillBeRigid
/// Indicates we give a warning if the type parameter is ever solved
| WarnIfNotRigid
/// Indicates the type parameter is an inference variable may be solved
| Flexible
/// Indicates the type parameter derives from an '_' anonymous type
/// For units-of-measure, we give a warning if this gets solved to '1'
| Anon
member x.ErrorIfUnified = match x with TyparRigidity.Rigid -> true | _ -> false
member x.WarnIfUnified = match x with TyparRigidity.WillBeRigid | TyparRigidity.WarnIfNotRigid -> true | _ -> false
member x.WarnIfMissingConstraint = match x with TyparRigidity.WillBeRigid -> true | _ -> false
/// Encode typar flags into a bit field
[<Struct>]
type TyparFlags(flags: int32) =
new (kind: TyparKind, rigidity: TyparRigidity, isFromError: bool, isCompGen: bool, staticReq: TyparStaticReq, dynamicReq: TyparDynamicReq, equalityDependsOn: bool, comparisonDependsOn: bool, supportsNullFlex: bool) =
TyparFlags((if isFromError then 0b00000000000000010 else 0) |||
(if isCompGen then 0b00000000000000100 else 0) |||
(match staticReq with
| TyparStaticReq.None -> 0b00000000000000000
| TyparStaticReq.HeadType -> 0b00000000000001000) |||
(match rigidity with
| TyparRigidity.Rigid -> 0b00000000000000000
| TyparRigidity.WillBeRigid -> 0b00000000000100000
| TyparRigidity.WarnIfNotRigid -> 0b00000000001000000
| TyparRigidity.Flexible -> 0b00000000001100000
| TyparRigidity.Anon -> 0b00000000010000000) |||
(match kind with
| TyparKind.Type -> 0b00000000000000000
| TyparKind.Measure -> 0b00000000100000000) |||
(if comparisonDependsOn then
0b00000001000000000 else 0) |||
(match dynamicReq with
| TyparDynamicReq.No -> 0b00000000000000000
| TyparDynamicReq.Yes -> 0b00000010000000000) |||
(if equalityDependsOn then
0b00000100000000000 else 0) |||
// 0b00001000100000000 is being checked by x.Kind, but never set in this version of the code
// 0b00010000000000000 is taken by compat flex
(if supportsNullFlex then
0b00100000000000000 else 0))
/// Indicates if the type inference variable was generated after an error when type checking expressions or patterns
member x.IsFromError = (flags &&& 0b00000000000000010) <> 0x0
/// Indicates if the type variable is compiler generated, i.e. is an implicit type inference variable
member x.IsCompilerGenerated = (flags &&& 0b00000000000000100) <> 0x0
/// Indicates if the type variable has a static "head type" requirement, i.e. ^a variables used in FSharp.Core and member constraints.
member x.StaticReq =
match (flags &&& 0b00000000000001000) with
| 0b00000000000000000 -> TyparStaticReq.None
| 0b00000000000001000 -> TyparStaticReq.HeadType
| _ -> failwith "unreachable"
/// Indicates if the type variable can be solved or given new constraints. The status of a type variable
/// generally always evolves towards being either rigid or solved.
member x.Rigidity =
match (flags &&& 0b00000000011100000) with
| 0b00000000000000000 -> TyparRigidity.Rigid
| 0b00000000000100000 -> TyparRigidity.WillBeRigid
| 0b00000000001000000 -> TyparRigidity.WarnIfNotRigid
| 0b00000000001100000 -> TyparRigidity.Flexible
| 0b00000000010000000 -> TyparRigidity.Anon
| _ -> failwith "unreachable"
/// Indicates whether a type variable can be instantiated by types or units-of-measure.
member x.Kind =
match (flags &&& 0b00001000100000000) with
| 0b00000000000000000 -> TyparKind.Type
| 0b00000000100000000 -> TyparKind.Measure
| _ -> failwith "unreachable"
/// Indicates that whether or not a generic type definition satisfies the comparison constraint is dependent on whether this type variable satisfies the comparison constraint.
member x.ComparisonConditionalOn =
(flags &&& 0b00000001000000000) <> 0x0
/// Indicates if a type parameter is needed at runtime and may not be eliminated
member x.DynamicReq =
match (flags &&& 0b00000010000000000) with
| 0b00000000000000000 -> TyparDynamicReq.No
| 0b00000010000000000 -> TyparDynamicReq.Yes
| _ -> failwith "unreachable"
/// Indicates that whether or not a generic type definition satisfies the equality constraint is dependent on whether this type variable satisfies the equality constraint.
member x.EqualityConditionalOn =
(flags &&& 0b00000100000000000) <> 0x0
/// Indicates that whether this type parameter is a compat-flex type parameter (i.e. where "expr :> tp" only emits an optional warning)
member x.IsCompatFlex =
(flags &&& 0b00010000000000000) <> 0x0
member x.WithCompatFlex b =
if b then
TyparFlags(flags ||| 0b00010000000000000)
else
TyparFlags(flags &&& ~~~0b00010000000000000)
/// Indicates that whether this type parameter is flexible for 'supports null' constraint, e.g. in the case of assignment to a mutable value
member x.IsSupportsNullFlex =
(flags &&& 0b00100000000000000) <> 0x0
member x.WithSupportsNullFlex b =
if b then
TyparFlags(flags ||| 0b00100000000000000)
else
TyparFlags(flags &&& ~~~0b00100000000000000)
member x.WithStaticReq staticReq =
TyparFlags(x.Kind, x.Rigidity, x.IsFromError, x.IsCompilerGenerated, staticReq, x.DynamicReq, x.EqualityConditionalOn, x.ComparisonConditionalOn, x.IsSupportsNullFlex)
/// Get the flags as included in the F# binary metadata. We pickle this as int64 to allow for future expansion
member x.PickledBits = flags
/// Encode entity flags into a bit field. We leave lots of space to allow for future expansion.
[<Struct>]
type EntityFlags(flags: int64) =
new (usesPrefixDisplay, isModuleOrNamespace, preEstablishedHasDefaultCtor, hasSelfReferentialCtor, isStructRecordOrUnionType) =
EntityFlags((if isModuleOrNamespace then 0b000000000000001L else 0L) |||
(if usesPrefixDisplay then 0b000000000000010L else 0L) |||
(if preEstablishedHasDefaultCtor then 0b000000000000100L else 0L) |||
(if hasSelfReferentialCtor then 0b000000000001000L else 0L) |||
(if isStructRecordOrUnionType then 0b000000000100000L else 0L))
/// Indicates the Entity is actually a module or namespace, not a type definition
member x.IsModuleOrNamespace = (flags &&& 0b000000000000001L) <> 0x0L
/// Indicates the type prefers the "tycon<a, b>" syntax for display etc.
member x.IsPrefixDisplay = (flags &&& 0b000000000000010L) <> 0x0L
// This bit is not pickled, only used while establishing a type constructor. It is needed because the type constructor
// is known to satisfy the default constructor constraint even before any of its members have been established.
member x.PreEstablishedHasDefaultConstructor = (flags &&& 0b000000000000100L) <> 0x0L
// This bit represents an F# specific condition where a type has at least one constructor that may access
// the 'this' pointer prior to successful initialization of the partial contents of the object. In this
// case sub-classes must protect themselves against early access to their contents.
member x.HasSelfReferentialConstructor = (flags &&& 0b000000000001000L) <> 0x0L
/// This bit is reserved for us in the pickle format, see pickle.fs, it's being listed here to stop it ever being used for anything else
static member ReservedBitForPickleFormatTyconReprFlag = 0b000000000010000L
/// This bit represents a F# record that is a value type, or a struct record.
member x.IsStructRecordOrUnionType = (flags &&& 0b000000000100000L) <> 0x0L
/// These two bits represents the on-demand analysis about whether the entity has the IsByRefLike attribute
member x.TryIsByRefLike = (flags &&& 0b000000011000000L)
|> function
| 0b000000011000000L -> ValueSome true
| 0b000000010000000L -> ValueSome false
| _ -> ValueNone
/// Adjust the on-demand analysis about whether the entity has the IsByRefLike attribute
member x.WithIsByRefLike flag =
let flags =
(flags &&& ~~~0b000000011000000L) |||
(match flag with
| true -> 0b000000011000000L
| false -> 0b000000010000000L)
EntityFlags flags
/// These two bits represents the on-demand analysis about whether the entity has the IsReadOnly attribute
member x.TryIsReadOnly = (flags &&& 0b000001100000000L)
|> function
| 0b000001100000000L -> ValueSome true
| 0b000001000000000L -> ValueSome false
| _ -> ValueNone
/// Adjust the on-demand analysis about whether the entity has the IsReadOnly attribute
member x.WithIsReadOnly flag =
let flags =
(flags &&& ~~~0b000001100000000L) |||
(match flag with
| true -> 0b000001100000000L
| false -> 0b000001000000000L)
EntityFlags flags
/// These two bits represents the on-demand analysis about whether the entity is assumed to be a readonly struct
member x.TryIsAssumedReadOnly = (flags &&& 0b000110000000000L)
|> function
| 0b000110000000000L -> ValueSome true
| 0b000100000000000L -> ValueSome false
| _ -> ValueNone
/// Adjust the on-demand analysis about whether the entity is assumed to be a readonly struct
member x.WithIsAssumedReadOnly flag =
let flags =
(flags &&& ~~~0b000110000000000L) |||
(match flag with
| true -> 0b000110000000000L
| false -> 0b000100000000000L)
EntityFlags flags
/// Get the flags as included in the F# binary metadata
member x.PickledBits = (flags &&& ~~~0b000111111000100L)
exception UndefinedName of
depth: int *
error: (string -> string) *
id: Ident *
suggestions: Suggestions
exception InternalUndefinedItemRef of (string * string * string -> int * string) * string * string * string
[<CustomEquality;NoComparison>]
type ModuleOrNamespaceKind =
/// Indicates that a module is compiled to a class with the "Module" suffix added.
| FSharpModuleWithSuffix
/// Indicates that a module is compiled to a class with the same name as the original module
| ModuleOrType
/// Indicates that a 'module' is really a namespace
| Namespace of
/// Indicates that the sourcecode had a namespace.
/// If false, this namespace was implicitly constructed during type checking.
isExplicit: bool
override this.Equals other =
match other with
| :? ModuleOrNamespaceKind as kind ->
match this, kind with
| FSharpModuleWithSuffix, FSharpModuleWithSuffix
| ModuleOrType, ModuleOrType
| Namespace _, Namespace _ -> true
| _ -> false
| _ -> false
override this.GetHashCode () =
match this with
| FSharpModuleWithSuffix -> 0
| ModuleOrType -> 1
| Namespace _ -> 2
/// A public path records where a construct lives within the global namespace
/// of a CCU.
type PublicPath =
| PubPath of string[]
member x.EnclosingPath =
let (PubPath pp) = x
assert (pp.Length >= 1)
pp[0..pp.Length-2]
/// Represents the specified visibility of the accessibility -- used to ensure IL visibility
[<RequireQualifiedAccess>]
type SyntaxAccess =
| Public
| Internal
| Private
| Unknown
/// The information ILXGEN needs about the location of an item
type CompilationPath =
| CompPath of ILScopeRef * SyntaxAccess * (string * ModuleOrNamespaceKind) list
member x.ILScopeRef = let (CompPath(scoref, _, _)) = x in scoref
member x.AccessPath = let (CompPath(_, _, p)) = x in p
member x.MangledPath = List.map fst x.AccessPath
member x.NestedPublicPath (id: Ident) = PubPath(Array.append (Array.ofList x.MangledPath) [| id.idText |])
member x.ParentCompPath =
let a, _ = List.frontAndBack x.AccessPath
CompPath(x.ILScopeRef, x.SyntaxAccess, a)
member x.NestedCompPath n moduleKind =
CompPath(x.ILScopeRef, x.SyntaxAccess, x.AccessPath@[(n, moduleKind)])
member x.DemangledPath =
x.AccessPath |> List.map (fun (nm, k) -> CompilationPath.DemangleEntityName nm k)
/// String 'Module' off an F# module name, if FSharpModuleWithSuffix is used
static member DemangleEntityName nm k =
match k with
| FSharpModuleWithSuffix -> String.dropSuffix nm FSharpModuleSuffix
| _ -> nm
member x.SyntaxAccess = let (CompPath(_, access, _)) = x in access
[<NoEquality; NoComparison; StructuredFormatDisplay("{DebugText}")>]
type EntityOptionalData =
{
/// The name of the type, possibly with `n mangling
// MUTABILITY; used only when establishing tycons.
mutable entity_compiled_name: string option
// MUTABILITY: the signature is adjusted when it is checked
/// If this field is populated, this is the implementation range for an item in a signature, otherwise it is
/// the signature range for an item in an implementation
mutable entity_other_range: (range * bool) option
// MUTABILITY; used only when establishing tycons.
mutable entity_kind: TyparKind
/// The declared documentation for the type or module
// MUTABILITY: only for unpickle linkage
mutable entity_xmldoc: XmlDoc
/// the signature xml doc for an item in an implementation file.
mutable entity_other_xmldoc : XmlDoc option
/// The XML document signature for this entity
mutable entity_xmldocsig: string
/// If non-None, indicates the type is an abbreviation for another type.
//
// MUTABILITY; used only during creation and remapping of tycons
mutable entity_tycon_abbrev: TType option
/// The declared accessibility of the representation, not taking signatures into account
mutable entity_tycon_repr_accessibility: Accessibility
/// Indicates how visible is the entity is.
// MUTABILITY: only for unpickle linkage
mutable entity_accessibility: Accessibility
/// Field used when the 'tycon' is really an exception definition
//
// MUTABILITY; used only during creation and remapping of tycons
mutable entity_exn_info: ExceptionInfo
}
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
member x.DebugText = x.ToString()
override x.ToString() = "EntityOptionalData(...)"
/// Represents a type definition, exception definition, module definition or namespace definition.
[<NoEquality; NoComparison; RequireQualifiedAccess; StructuredFormatDisplay("{DebugText}")>]
type Entity =
{
/// The declared type parameters of the type
// MUTABILITY; used only during creation and remapping of tycons
mutable entity_typars: LazyWithContext<Typars, range>
mutable entity_flags: EntityFlags
/// The unique stamp of the "tycon blob". Note the same tycon in signature and implementation get different stamps
// MUTABILITY: only for unpickle linkage
mutable entity_stamp: Stamp
/// The name of the type, possibly with `n mangling
// MUTABILITY: only for unpickle linkage
mutable entity_logical_name: string
/// The declaration location for the type constructor
mutable entity_range: range
/// The declared attributes for the type
// MUTABILITY; used during creation and remapping of tycons
// MUTABILITY; used when propagating signature attributes into the implementation.
mutable entity_attribs: WellKnownEntityAttribs
/// The declared representation of the type, i.e. record, union, class etc.
//
// MUTABILITY; used only during creation and remapping of tycons
mutable entity_tycon_repr: TyconRepresentation
/// The methods and properties of the type
//
// MUTABILITY; used only during creation and remapping of tycons
mutable entity_tycon_tcaug: TyconAugmentation
/// This field is used when the 'tycon' is really a module definition. It holds statically nested type definitions and nested modules
//
// MUTABILITY: only used during creation and remapping of tycons and
// when compiling fslib to fixup compiler forward references to internal items
mutable entity_modul_type: MaybeLazy<ModuleOrNamespaceType>
/// The stable path to the type, e.g. Microsoft.FSharp.Core.FSharpFunc`2
// REVIEW: it looks like entity_cpath subsumes this
// MUTABILITY: only for unpickle linkage
mutable entity_pubpath: PublicPath option
/// The stable path to the type, e.g. Microsoft.FSharp.Core.FSharpFunc`2
// MUTABILITY: only for unpickle linkage
mutable entity_cpath: CompilationPath option
/// Used during codegen to hold the ILX representation indicating how to access the type
// MUTABILITY: only for unpickle linkage and caching
mutable entity_il_repr_cache: CompiledTypeRepr cache
mutable entity_opt_data: EntityOptionalData option
}
static member NewEmptyEntityOptData() =
{ entity_compiled_name = None
entity_other_range = None
entity_kind = TyparKind.Type
entity_xmldoc = XmlDoc.Empty
entity_other_xmldoc = None
entity_xmldocsig = ""
entity_tycon_abbrev = None
entity_tycon_repr_accessibility = TAccess []
entity_accessibility = TAccess []
entity_exn_info = TExnNone }
/// The name of the namespace, module or type, possibly with mangling, e.g. List`1, List or FailureException
member x.LogicalName = x.entity_logical_name
/// The compiled name of the namespace, module or type, e.g. FSharpList`1, ListModule or FailureException
member x.CompiledName =
match x.entity_opt_data with
| Some { entity_compiled_name = Some s } -> s
| _ -> x.LogicalName
member x.EntityCompiledName =
match x.entity_opt_data with
| Some optData -> optData.entity_compiled_name
| _ -> None
member x.SetCompiledName name =
match x.entity_opt_data with
| Some optData -> optData.entity_compiled_name <- name
| _ -> x.entity_opt_data <- Some { Entity.NewEmptyEntityOptData() with entity_compiled_name = name }
/// The display name of the namespace, module or type, e.g. List instead of List`1, and no static parameters.
/// For modules the Module suffix is removed if FSharpModuleWithSuffix is used.
///
/// No backticks are added for entities with non-identifier names
member x.DisplayNameCore = x.GetDisplayName(coreName=true)
/// The display name of the namespace, module or type, e.g. List instead of List`1, and no static parameters
/// For modules the Module suffix is removed if FSharpModuleWithSuffix is used.
///
/// Backticks are added implicitly for entities with non-identifier names
member x.DisplayName = x.GetDisplayName(coreName=false)
/// The display name of the namespace, module or type with <_, _, _> added for generic types, plus static parameters if any
/// For modules the Module suffix is removed if FSharpModuleWithSuffix is used.
///
/// Backticks are added implicitly for entities with non-identifier names
member x.DisplayNameWithStaticParametersAndUnderscoreTypars =
x.GetDisplayName(coreName=false, withStaticParameters=true, withUnderscoreTypars=true)
/// The display name of the namespace, module or type, e.g. List instead of List`1, including static parameters if any
/// For modules the Module suffix is removed if FSharpModuleWithSuffix is used.
///
/// Backticks are added implicitly for entities with non-identifier names
member x.DisplayNameWithStaticParameters =
x.GetDisplayName(coreName=false, withStaticParameters=true, withUnderscoreTypars=false)
#if !NO_TYPEPROVIDERS
member x.IsStaticInstantiationTycon =
x.IsProvidedErasedTycon &&
let _nm, args = DemangleProvidedTypeName x.LogicalName
args.Length > 0
#endif
member x.GetDisplayName(coreName, ?withStaticParameters, ?withUnderscoreTypars) =
let withStaticParameters = defaultArg withStaticParameters false
let withUnderscoreTypars = defaultArg withUnderscoreTypars false
let nm = x.LogicalName
if x.IsModuleOrNamespace then x.DemangledModuleOrNamespaceName
#if !NO_TYPEPROVIDERS
elif x.IsProvidedErasedTycon then
let nm, args = DemangleProvidedTypeName nm
if withStaticParameters && args.Length > 0 then
nm + "<" + String.concat "," (Array.map snd args) + ">"
else
nm
#endif
else
ignore withStaticParameters
match x.TyparsNoRange with
| [] -> nm
| tps ->
let nm = DemangleGenericTypeName nm
let isArray = nm.StartsWithOrdinal("[") && nm.EndsWithOrdinal("]")
let nm = if coreName || isArray then nm else ConvertLogicalNameToDisplayName nm
if withUnderscoreTypars then
let typarNames = tps |> List.map (fun _ -> "_")
nm + "<" + String.concat "," typarNames + ">"
else
nm
/// The code location where the module, namespace or type is defined.
member x.Range =
#if !NO_TYPEPROVIDERS
match x.TypeReprInfo with
| TProvidedTypeRepr info ->
match Construct.ComputeDefinitionLocationOfProvidedItem info.ProvidedType with
| Some range -> range
| None -> x.entity_range
| _ ->
#endif
x.entity_range
/// The range in the implementation, adjusted for an item in a signature
member x.DefinitionRange =
match x.entity_opt_data with
| Some { entity_other_range = Some (r, true) } -> r
| _ -> x.Range
member x.SigRange =
match x.entity_opt_data with
| Some { entity_other_range = Some (r, false) } -> r
| _ -> x.Range
member x.SetOtherRange m =
match x.entity_opt_data with
| Some optData -> optData.entity_other_range <- Some m
| _ -> x.entity_opt_data <- Some { Entity.NewEmptyEntityOptData() with entity_other_range = Some m }
member x.SetOtherXmlDoc xmlDoc =
match x.entity_opt_data with
| Some optData -> optData.entity_other_xmldoc <- Some xmlDoc
| _ -> x.entity_opt_data <- Some { Entity.NewEmptyEntityOptData() with entity_other_xmldoc = Some xmlDoc }
/// A unique stamp for this module, namespace or type definition within the context of this compilation.
/// Note that because of signatures, there are situations where in a single compilation the "same"
/// module, namespace or type may have two distinct Entity objects that have distinct stamps.
member x.Stamp = x.entity_stamp
/// The F#-defined custom attributes of the entity, if any. If the entity is backed by Abstract IL or provided metadata
/// then this does not include any attributes from those sources.
member x.Attribs = x.entity_attribs.AsList()
member x.EntityAttribs = x.entity_attribs
/// The XML documentation of the entity, if any. If the entity is backed by provided metadata
/// then this _does_ include this documentation. If the entity is backed by Abstract IL metadata
/// or comes from another F# assembly then it does not (because the documentation will get read from
/// an XML file).
member x.XmlDoc =
#if !NO_TYPEPROVIDERS
match x.TypeReprInfo with
| TProvidedTypeRepr info ->
let lines = info.ProvidedType.PUntaintNoFailure(fun st -> (st :> IProvidedCustomAttributeProvider).GetXmlDocAttributes(info.ProvidedType.TypeProvider.PUntaintNoFailure id))
XmlDoc (lines, x.DefinitionRange)
| _ ->
#endif
match x.entity_opt_data with
| Some optData ->
if not optData.entity_xmldoc.IsEmpty then
optData.entity_xmldoc
else
match optData.entity_other_xmldoc with
| Some xmlDoc -> xmlDoc
| None -> XmlDoc.Empty
| _ -> XmlDoc.Empty
/// The XML documentation sig-string of the entity, if any, to use to lookup an .xml doc file. This also acts
/// as a cache for this sig-string computation.
member x.XmlDocSig
with get() =
match x.entity_opt_data with
| Some optData -> optData.entity_xmldocsig
| _ -> ""
and set v =
match x.entity_opt_data with
| Some optData -> optData.entity_xmldocsig <- v
| _ -> x.entity_opt_data <- Some { Entity.NewEmptyEntityOptData() with entity_xmldocsig = v }
/// The logical contents of the entity when it is a module or namespace fragment.
member x.ModuleOrNamespaceType = x.entity_modul_type.Force()
/// The logical contents of the entity when it is a type definition.
member x.TypeContents = x.entity_tycon_tcaug
/// The kind of the type definition - is it a measure definition or a type definition?
member x.TypeOrMeasureKind =
match x.entity_opt_data with
| Some optData -> optData.entity_kind
| _ -> TyparKind.Type
member x.SetTypeOrMeasureKind kind =
match x.entity_opt_data with
| Some optData -> optData.entity_kind <- kind
| _ -> x.entity_opt_data <- Some { Entity.NewEmptyEntityOptData() with entity_kind = kind }
/// The identifier at the point of declaration of the type definition.
member x.Id = ident(x.LogicalName, x.Range)
/// The information about the r.h.s. of a type definition, if any. For example, the r.h.s. of a union or record type.
member x.TypeReprInfo = x.entity_tycon_repr
/// The information about the r.h.s. of an F# exception definition, if any.
member x.ExceptionInfo =
match x.entity_opt_data with
| Some optData -> optData.entity_exn_info
| _ -> TExnNone
member x.SetExceptionInfo exn_info =
match x.entity_opt_data with
| Some optData -> optData.entity_exn_info <- exn_info
| _ -> x.entity_opt_data <- Some { Entity.NewEmptyEntityOptData() with entity_exn_info = exn_info }
/// Indicates if the entity represents an F# exception declaration.
member x.IsFSharpException = match x.ExceptionInfo with TExnNone -> false | _ -> true
/// Demangle the module name, if FSharpModuleWithSuffix is used
member x.DemangledModuleOrNamespaceName =
CompilationPath.DemangleEntityName x.LogicalName x.ModuleOrNamespaceType.ModuleOrNamespaceKind
/// Get the type parameters for an entity that is a type declaration, otherwise return the empty list.
///
/// Lazy because it may read metadata, must provide a context "range" in case error occurs reading metadata.
member x.Typars m = x.entity_typars.Force m
/// Get the type parameters for an entity that is a type declaration, otherwise return the empty list.
member x.TyparsNoRange: Typars = x.Typars x.Range
/// Get the type abbreviated by this type definition, if it is an F# type abbreviation definition
member x.TypeAbbrev =
match x.entity_opt_data with
| Some optData -> optData.entity_tycon_abbrev
| _ -> None
member x.SetTypeAbbrev tycon_abbrev =
match x.entity_opt_data with
| Some optData -> optData.entity_tycon_abbrev <- tycon_abbrev
| _ -> x.entity_opt_data <- Some { Entity.NewEmptyEntityOptData() with entity_tycon_abbrev = tycon_abbrev }
/// Indicates if this entity is an F# type abbreviation definition
member x.IsTypeAbbrev = x.TypeAbbrev.IsSome
/// Get the value representing the accessibility of the r.h.s. of an F# type definition.
member x.TypeReprAccessibility =
match x.entity_opt_data with
| Some optData -> optData.entity_tycon_repr_accessibility
| _ -> TAccess []
/// Get the cache of the compiled ILTypeRef representation of this module or type.
member x.CompiledReprCache = x.entity_il_repr_cache
/// Get a blob of data indicating how this type is nested in other namespaces, modules or types.
member x.PublicPath = x.entity_pubpath
/// Get the value representing the accessibility of an F# type definition or module.
member x.Accessibility =
match x.entity_opt_data with
| Some optData -> optData.entity_accessibility
| _ -> TAccess []
/// Indicates the type prefers the "tycon<a, b>" syntax for display etc.
member x.IsPrefixDisplay = x.entity_flags.IsPrefixDisplay
/// Indicates the Entity is actually a module or namespace, not a type definition
member x.IsModuleOrNamespace = x.entity_flags.IsModuleOrNamespace
/// Indicates if the entity is a namespace
member x.IsNamespace = x.IsModuleOrNamespace && (match x.ModuleOrNamespaceType.ModuleOrNamespaceKind with Namespace _ -> true | _ -> false)
/// Indicates if the entity has an implicit namespace
member x.IsImplicitNamespace = (match x.ModuleOrNamespaceType.ModuleOrNamespaceKind with Namespace false -> true | _ -> false)
/// Indicates if the entity is an F# module definition
member x.IsModule = x.IsModuleOrNamespace && (match x.ModuleOrNamespaceType.ModuleOrNamespaceKind with Namespace _ -> false | _ -> true)
#if !NO_TYPEPROVIDERS
/// Indicates if the entity is a provided type or namespace definition
member x.IsProvided =
match x.TypeReprInfo with
| TProvidedTypeRepr _ -> true
| TProvidedNamespaceRepr _ -> true
| _ -> false
/// Indicates if the entity is a provided namespace fragment
member x.IsProvidedNamespace =
match x.TypeReprInfo with
| TProvidedNamespaceRepr _ -> true
| _ -> false
/// Indicates if the entity is an erased provided type definition
member x.IsProvidedErasedTycon =
match x.TypeReprInfo with
| TProvidedTypeRepr info -> info.IsErased
| _ -> false
/// Indicates if the entity is a generated provided type definition, i.e. not erased.
member x.IsProvidedGeneratedTycon =
match x.TypeReprInfo with
| TProvidedTypeRepr info -> info.IsGenerated
| _ -> false
#endif
/// Indicates if the entity is erased, either a measure definition, or an erased provided type definition
member x.IsErased =
x.IsMeasureableReprTycon
#if !NO_TYPEPROVIDERS
|| x.IsProvidedErasedTycon
#endif
/// Get a blob of data indicating how this type is nested inside other namespaces, modules and types.
member x.CompilationPathOpt = x.entity_cpath
/// Get a blob of data indicating how this type is nested inside other namespaces, modules and types.
member x.CompilationPath =
match x.CompilationPathOpt with
| Some cpath -> cpath
| None -> error(Error(FSComp.SR.tastTypeOrModuleNotConcrete(x.LogicalName), x.Range))
/// Get a table of fields for all the F#-defined record, struct and class fields in this type definition, including
/// static fields, 'val' declarations and hidden fields from the compilation of implicit class constructions.
member x.AllFieldTable =
match x.TypeReprInfo with
| TFSharpTyconRepr {fsobjmodel_rfields=x} -> x
| _ ->
match x.ExceptionInfo with
| TExnFresh x -> x