-
Notifications
You must be signed in to change notification settings - Fork 789
/
tast.fs
executable file
·4772 lines (3817 loc) · 226 KB
/
tast.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. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
//-------------------------------------------------------------------------
// Defines the typed abstract syntax trees used throughout the F# compiler.
//-------------------------------------------------------------------------
module internal Microsoft.FSharp.Compiler.Tast
open System
open System.Collections.Generic
open System.Reflection
open Internal.Utilities
open Microsoft.FSharp.Compiler.AbstractIL
open Microsoft.FSharp.Compiler.AbstractIL.IL
open Microsoft.FSharp.Compiler.AbstractIL.Internal
open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library
open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics
open Microsoft.FSharp.Compiler.AbstractIL.Extensions.ILX.Types
open Microsoft.FSharp.Compiler
open Microsoft.FSharp.Compiler.Range
open Microsoft.FSharp.Compiler.Ast
open Microsoft.FSharp.Compiler.ErrorLogger
open Microsoft.FSharp.Compiler.Lib
open Microsoft.FSharp.Compiler.PrettyNaming
open Microsoft.FSharp.Compiler.QuotationPickler
open Microsoft.FSharp.Core.Printf
open Microsoft.FSharp.Compiler.Rational
#if EXTENSIONTYPING
open Microsoft.FSharp.Compiler.ExtensionTyping
open Microsoft.FSharp.Core.CompilerServices
#endif
/// Unique name generator for stamps attached to lambdas and object expressions
type Unique = int64
//++GLOBAL MUTABLE STATE
let newUnique = let i = ref 0L in fun () -> System.Threading.Interlocked.Increment(i)
type Stamp = int64
/// Unique name generator for stamps attached to to val_specs, tycon_specs etc.
//++GLOBAL MUTABLE STATE
let newStamp = let i = ref 0L in fun () -> System.Threading.Interlocked.Increment(i)
/// A global generator of compiler generated names
// ++GLOBAL MUTABLE STATE
let globalNng = NiceNameGenerator()
/// A global generator of stable compiler generated names
// ++GLOBAL MUTABLE STATE
let globalStableNameGenerator = StableNiceNameGenerator ()
type StampMap<'T> = Map<Stamp,'T>
//-------------------------------------------------------------------------
// Flags
[<RequireQualifiedAccess>]
type ValInline =
/// Indicates the value must always be inlined and no .NET IL code is generated for the value/function
| PseudoVal
/// 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 must always be inlined
let mustinline = function ValInline.PseudoVal | 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
[<RequireQualifiedAccess>]
/// Indicates if a type parameter is needed at runtime and may not be eliminated
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 memberm 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 -> 0b0000000000000000000L
| CtorThisVal -> 0b0000000000000000010L
| NormalVal -> 0b0000000000000000100L
| MemberThisVal -> 0b0000000000000000110L) |||
(if isCompGen then 0b0000000000000001000L
else 0b00000000000000000000L) |||
(match inlineInfo with
| ValInline.PseudoVal -> 0b0000000000000000000L
| ValInline.Always -> 0b0000000000000010000L
| ValInline.Optional -> 0b0000000000000100000L
| ValInline.Never -> 0b0000000000000110000L) |||
(match isMutable with
| Immutable -> 0b0000000000000000000L
| Mutable -> 0b0000000000001000000L) |||
(match isModuleOrMemberBinding with
| false -> 0b0000000000000000000L
| true -> 0b0000000000010000000L) |||
(match isExtensionMember with
| false -> 0b0000000000000000000L
| true -> 0b0000000000100000000L) |||
(match isIncrClassSpecialMember with
| false -> 0b0000000000000000000L
| true -> 0b0000000001000000000L) |||
(match isTyFunc with
| false -> 0b0000000000000000000L
| true -> 0b0000000010000000000L) |||
(match recValInfo with
| ValNotInRecScope -> 0b0000000000000000000L
| ValInRecScope true -> 0b0000000100000000000L
| ValInRecScope false -> 0b0000001000000000000L) |||
(match allowTypeInst with
| false -> 0b0000000000000000000L
| true -> 0b0000100000000000000L) |||
(match isGeneratedEventVal with
| false -> 0b0000000000000000000L
| true -> 0b0100000000000000000L)
ValFlags(flags)
member x.BaseOrThisInfo =
match (flags &&& 0b0000000000000000110L) with
| 0b0000000000000000000L -> BaseVal
| 0b0000000000000000010L -> CtorThisVal
| 0b0000000000000000100L -> NormalVal
| 0b0000000000000000110L -> MemberThisVal
| _ -> failwith "unreachable"
member x.IsCompilerGenerated = (flags &&& 0b0000000000000001000L) <> 0x0L
member x.SetIsCompilerGenerated(isCompGen) =
let flags = (flags &&& ~~~0b0000000000000001000L) |||
(match isCompGen with
| false -> 0b0000000000000000000L
| true -> 0b0000000000000001000L)
ValFlags(flags)
member x.InlineInfo =
match (flags &&& 0b0000000000000110000L) with
| 0b0000000000000000000L -> ValInline.PseudoVal
| 0b0000000000000010000L -> ValInline.Always
| 0b0000000000000100000L -> ValInline.Optional
| 0b0000000000000110000L -> ValInline.Never
| _ -> failwith "unreachable"
member x.MutabilityInfo =
match (flags &&& 0b0000000000001000000L) with
| 0b0000000000000000000L -> Immutable
| 0b0000000000001000000L -> Mutable
| _ -> failwith "unreachable"
member x.IsMemberOrModuleBinding =
match (flags &&& 0b0000000000010000000L) with
| 0b0000000000000000000L -> false
| 0b0000000000010000000L -> true
| _ -> failwith "unreachable"
member x.SetIsMemberOrModuleBinding = ValFlags(flags ||| 0b0000000000010000000L)
member x.IsExtensionMember = (flags &&& 0b0000000000100000000L) <> 0L
member x.IsIncrClassSpecialMember = (flags &&& 0b0000000001000000000L) <> 0L
member x.IsTypeFunction = (flags &&& 0b0000000010000000000L) <> 0L
member x.RecursiveValInfo = match (flags &&& 0b0000001100000000000L) with
| 0b0000000000000000000L -> ValNotInRecScope
| 0b0000000100000000000L -> ValInRecScope(true)
| 0b0000001000000000000L -> ValInRecScope(false)
| _ -> failwith "unreachable"
member x.SetRecursiveValInfo(recValInfo) =
let flags =
(flags &&& ~~~0b0000001100000000000L) |||
(match recValInfo with
| ValNotInRecScope -> 0b0000000000000000000L
| ValInRecScope(true) -> 0b0000000100000000000L
| ValInRecScope(false) -> 0b0000001000000000000L)
ValFlags(flags)
member x.MakesNoCriticalTailcalls = (flags &&& 0b0000010000000000000L) <> 0L
member x.SetMakesNoCriticalTailcalls = ValFlags(flags ||| 0b0000010000000000000L)
member x.PermitsExplicitTypeInstantiation = (flags &&& 0b0000100000000000000L) <> 0L
member x.HasBeenReferenced = (flags &&& 0b0001000000000000000L) <> 0L
member x.SetHasBeenReferenced = ValFlags(flags ||| 0b0001000000000000000L)
member x.IsCompiledAsStaticPropertyWithoutField = (flags &&& 0b0010000000000000000L) <> 0L
member x.SetIsCompiledAsStaticPropertyWithoutField = ValFlags(flags ||| 0b0010000000000000000L)
member x.IsGeneratedEventVal = (flags &&& 0b0100000000000000000L) <> 0L
member x.IsFixed = (flags &&& 0b1000000000000000000L) <> 0L
member x.SetIsFixed = ValFlags(flags ||| 0b1000000000000000000L)
/// 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 &&& ~~~0b0011001100000000000L)
/// Represents the kind of a type parameter
[<RequireQualifiedAccess>]
type TyparKind =
| Type
| Measure
member x.AttrName =
match x with
| TyparKind.Type -> None
| TyparKind.Measure -> Some "Measure"
override x.ToString() =
match x with
| TyparKind.Type -> "type"
| TyparKind.Measure -> "measure"
[<RequireQualifiedAccess>]
/// 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.
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) =
TyparFlags((if isFromError then 0b000000000010 else 0) |||
(if isCompGen then 0b000000000100 else 0) |||
(match staticReq with
| NoStaticReq -> 0b000000000000
| HeadTypeStaticReq -> 0b000000001000) |||
(match rigidity with
| TyparRigidity.Rigid -> 0b000000000000
| TyparRigidity.WillBeRigid -> 0b000000100000
| TyparRigidity.WarnIfNotRigid -> 0b000001000000
| TyparRigidity.Flexible -> 0b000001100000
| TyparRigidity.Anon -> 0b000010000000) |||
(match kind with
| TyparKind.Type -> 0b000000000000
| TyparKind.Measure -> 0b000100000000) |||
(if comparisonDependsOn then
0b001000000000 else 0) |||
(match dynamicReq with
| TyparDynamicReq.No -> 0b000000000000
| TyparDynamicReq.Yes -> 0b010000000000) |||
(if equalityDependsOn then
0b100000000000 else 0))
/// Indicates if the type inference variable was generated after an error when type checking expressions or patterns
member x.IsFromError = (flags &&& 0b000000000010) <> 0x0
/// Indicates if the type variable is compiler generated, i.e. is an implicit type inference variable
member x.IsCompilerGenerated = (flags &&& 0b000000000100) <> 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 &&& 0b000000001000) with
| 0b000000000000 -> NoStaticReq
| 0b000000001000 -> HeadTypeStaticReq
| _ -> 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 &&& 0b000011100000) with
| 0b000000000000 -> TyparRigidity.Rigid
| 0b000000100000 -> TyparRigidity.WillBeRigid
| 0b000001000000 -> TyparRigidity.WarnIfNotRigid
| 0b000001100000 -> TyparRigidity.Flexible
| 0b000010000000 -> TyparRigidity.Anon
| _ -> failwith "unreachable"
/// Indicates whether a type variable can be instantiated by types or units-of-measure.
member x.Kind =
match (flags &&& 0b000100000000) with
| 0b000000000000 -> TyparKind.Type
| 0b000100000000 -> 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 &&& 0b001000000000) <> 0x0
/// Indicates if a type parameter is needed at runtime and may not be eliminated
member x.DynamicReq =
match (flags &&& 0b010000000000) with
| 0b000000000000 -> TyparDynamicReq.No
| 0b010000000000 -> 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 &&& 0b100000000000) <> 0x0
/// 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 0b00000000001L else 0L) |||
(if usesPrefixDisplay then 0b00000000010L else 0L) |||
(if preEstablishedHasDefaultCtor then 0b00000000100L else 0L) |||
(if hasSelfReferentialCtor then 0b00000001000L else 0L) |||
(if isStructRecordOrUnionType then 0b00000100000L else 0L))
member x.IsModuleOrNamespace = (flags &&& 0b00000000001L) <> 0x0L
member x.IsPrefixDisplay = (flags &&& 0b00000000010L) <> 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 &&& 0b00000000100L) <> 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 &&& 0b00000001000L) <> 0x0L
/// This bit represents a F# record that is a value type, or a struct record.
member x.IsStructRecordOrUnionType = (flags &&& 0b00000100000L) <> 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 = 0b00000010000L
/// Get the flags as included in the F# binary metadata
member x.PickledBits = (flags &&& ~~~0b00000000100L)
#if DEBUG
assert (sizeof<ValFlags> = 8)
assert (sizeof<EntityFlags> = 8)
assert (sizeof<TyparFlags> = 4)
#endif
let unassignedTyparName = "?"
type Predictions = Set<string>
let NoPredictions = Set.empty
exception UndefinedName of int * (* error func that expects identifier name *)(string -> string) * Ident * Predictions
exception InternalUndefinedItemRef of (string * string * string -> int * string) * string * string * string
let KeyTyconByDemangledNameAndArity nm (typars: _ list) x =
KeyValuePair(NameArityPair(DemangleGenericTypeName nm, typars.Length), x)
/// Generic types can be accessed either by 'List' or 'List`1'. This lists both keys. The second form should really be deprecated.
let KeyTyconByAccessNames nm x =
if IsMangledGenericName nm then
let dnm = DemangleGenericTypeName nm
[| KeyValuePair(nm,x); KeyValuePair(dnm,x) |]
else
[| KeyValuePair(nm,x) |]
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
/// 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]
/// The information ILXGEN needs about the location of an item
type CompilationPath =
| CompPath of ILScopeRef * (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,a)
member x.NestedCompPath n modKind = CompPath(x.ILScopeRef,x.AccessPath@[(n,modKind)])
let getNameOfScopeRef sref =
match sref with
| ILScopeRef.Local -> "<local>"
| ILScopeRef.Module mref -> mref.Name
| ILScopeRef.Assembly aref -> aref.Name
#if EXTENSIONTYPING
let definitionLocationOfProvidedItem (p : Tainted<#IProvidedCustomAttributeProvider>) =
let attrs = p.PUntaintNoFailure(fun x -> x.GetDefinitionLocationAttribute(p.TypeProvider.PUntaintNoFailure(id)))
match attrs with
| None | Some (null, _, _) -> None
| Some (filePath, line, column) ->
// Coordinates from type provider are 1-based for lines and columns
// Coordinates internally in the F# compiler are 1-based for lines and 0-based for columns
let pos = Range.mkPos line (max 0 (column - 1))
Range.mkRange filePath pos pos |> Some
#endif
/// Represents a type definition, exception definition, module definition or namespace definition.
[<RequireQualifiedAccess>]
type Entity =
{ mutable Data: EntityData }
/// The name of the namespace, module or type, possibly with mangling, e.g. List`1, List or FailureException
member x.LogicalName = x.Data.entity_logical_name
/// The compiled name of the namespace, module or type, e.g. FSharpList`1, ListModule or FailureException
member x.CompiledName = match x.Data.entity_compiled_name with None -> x.LogicalName | Some s -> s
/// The display name of the namespace, module or type, e.g. List instead of List`1, and no static parameters
member x.DisplayName = x.GetDisplayName(false, false)
/// The display name of the namespace, module or type with <_,_,_> added for generic types, plus static parameters if any
member x.DisplayNameWithStaticParametersAndUnderscoreTypars = x.GetDisplayName(true, true)
/// The display name of the namespace, module or type, e.g. List instead of List`1, including static parameters if any
member x.DisplayNameWithStaticParameters = x.GetDisplayName(true, false)
#if EXTENSIONTYPING
member x.IsStaticInstantiationTycon =
x.IsProvidedErasedTycon &&
let _nm,args = PrettyNaming.demangleProvidedTypeName x.LogicalName
args.Length > 0
#endif
member x.GetDisplayName(withStaticParameters, withUnderscoreTypars) =
let nm = x.LogicalName
let getName () =
match x.TyparsNoRange with
| [] -> nm
| tps ->
let nm = DemangleGenericTypeName nm
if withUnderscoreTypars && tps.Length > 0 then
nm + "<" + String.concat "," (Array.create tps.Length "_") + ">"
else
nm
#if EXTENSIONTYPING
if x.IsProvidedErasedTycon then
let nm,args = PrettyNaming.demangleProvidedTypeName nm
if withStaticParameters && args.Length > 0 then
nm + "<" + String.concat "," (Array.map snd args) + ">"
else
nm
else
getName ()
#else
ignore withStaticParameters
getName ()
#endif
/// The code location where the module, namespace or type is defined.
member x.Range =
#if EXTENSIONTYPING
match x.TypeReprInfo with
| TProvidedTypeExtensionPoint info ->
match definitionLocationOfProvidedItem info.ProvidedType with
| Some range -> range
| None -> x.Data.entity_range
| _ ->
#endif
x.Data.entity_range
/// The range in the implementation, adjusted for an item in a signature
member x.DefinitionRange =
match x.Data.entity_other_range with
| Some (r, true) -> r
| _ -> x.Range
member x.SigRange =
match x.Data.entity_other_range with
| Some (r, false) -> r
| _ -> x.Range
member x.SetOtherRange m = x.Data.entity_other_range <- Some m
/// 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.Data.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.Data.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 EXTENSIONTYPING
match x.TypeReprInfo with
| TProvidedTypeExtensionPoint info -> XmlDoc (info.ProvidedType.PUntaintNoFailure(fun st -> (st :> IProvidedCustomAttributeProvider).GetXmlDocAttributes(info.ProvidedType.TypeProvider.PUntaintNoFailure(id))))
| _ ->
#endif
x.Data.entity_xmldoc
/// 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() = x.Data.entity_xmldocsig
and set v = x.Data.entity_xmldocsig <- v
/// The logical contents of the entity when it is a module or namespace fragment.
member x.ModuleOrNamespaceType = x.Data.entity_modul_contents.Force()
/// The logical contents of the entity when it is a type definition.
member x.TypeContents = x.Data.entity_tycon_tcaug
/// The kind of the type definition - is it a measure definition or a type definition?
member x.TypeOrMeasureKind = x.Data.entity_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.Data.entity_tycon_repr
/// The information about the r.h.s. of an F# exception definition, if any.
member x.ExceptionInfo = x.Data.entity_exn_info
/// Indicates if the entity represents an F# exception declaration.
member x.IsExceptionDecl = match x.ExceptionInfo with TExnNone -> false | _ -> true
/// 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
/// Demangle the module name, if FSharpModuleWithSuffix is used
member x.DemangledModuleOrNamespaceName =
Entity.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.Data.entity_typars.Force m
/// Get the type parameters for an entity that is a type declaration, otherwise return the empty list.
member x.TyparsNoRange = x.Typars x.Range
/// Get the type abbreviated by this type definition, if it is an F# type abbreviation definition
member x.TypeAbbrev = x.Data.entity_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 = x.Data.entity_tycon_repr_accessibility
/// Get the cache of the compiled ILTypeRef representation of this module or type.
member x.CompiledReprCache = x.Data.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.Data.entity_pubpath
/// Get the value representing the accessibility of an F# type definition or module.
member x.Accessibility = x.Data.entity_accessiblity
/// Indicates the type prefers the "tycon<a,b>" syntax for display etc.
member x.IsPrefixDisplay = x.Data.entity_flags.IsPrefixDisplay
/// Indicates the "tycon blob" is actually a module
member x.IsModuleOrNamespace = x.Data.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 is an F# module definition
member x.IsModule = x.IsModuleOrNamespace && (match x.ModuleOrNamespaceType.ModuleOrNamespaceKind with Namespace -> false | _ -> true)
#if EXTENSIONTYPING
/// Indicates if the entity is a provided type or namespace definition
member x.IsProvided =
match x.TypeReprInfo with
| TProvidedTypeExtensionPoint _ -> true
| TProvidedNamespaceExtensionPoint _ -> true
| _ -> false
/// Indicates if the entity is a provided namespace fragment
member x.IsProvidedNamespace =
match x.TypeReprInfo with
| TProvidedNamespaceExtensionPoint _ -> true
| _ -> false
/// Indicates if the entity is an erased provided type definition
member x.IsProvidedErasedTycon =
match x.TypeReprInfo with
| TProvidedTypeExtensionPoint 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
| TProvidedTypeExtensionPoint 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 EXTENSIONTYPING
|| x.IsProvidedErasedTycon
#endif
/// Get a blob of data indicating how this type is nested inside other namespaces, modules and types.
member x.CompilationPathOpt = x.Data.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
| TRecdRepr x | TFSharpObjectRepr {fsobjmodel_rfields=x} -> x
| _ ->
match x.ExceptionInfo with
| TExnFresh x -> x
| _ ->
{ FieldsByIndex = [| |]
FieldsByName = NameMap.empty }
/// Get an array 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.AllFieldsArray = x.AllFieldTable.FieldsByIndex
/// Get a list 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.AllFieldsAsList = x.AllFieldsArray |> Array.toList
/// Get a list of all instance fields for F#-defined record, struct and class fields in this type definition.
/// including hidden fields from the compilation of implicit class constructions.
// NOTE: This method doesn't perform particularly well, and is over-used, but doesn't seem to appear on performance traces
member x.AllInstanceFieldsAsList = x.AllFieldsAsList |> List.filter (fun f -> not f.IsStatic)
/// Get a list of all fields for F#-defined record, struct and class fields in this type definition,
/// including static fields, but excluding compiler-generate fields.
member x.TrueFieldsAsList = x.AllFieldsAsList |> List.filter (fun f -> not f.IsCompilerGenerated)
/// Get a list of all instance fields for F#-defined record, struct and class fields in this type definition,
/// excluding compiler-generate fields.
member x.TrueInstanceFieldsAsList = x.AllFieldsAsList |> List.filter (fun f -> not f.IsStatic && not f.IsCompilerGenerated)
/// Get a field by index in definition order
member x.GetFieldByIndex n = x.AllFieldTable.FieldByIndex n
/// Get a field by name.
member x.GetFieldByName n = x.AllFieldTable.FieldByName n
/// Indicate if this is a type whose r.h.s. is known to be a union type definition.
member x.IsUnionTycon = match x.TypeReprInfo with | TUnionRepr _ -> true | _ -> false
/// Get the union cases and other union-type information for a type, if any
member x.UnionTypeInfo =
match x.TypeReprInfo with
| TUnionRepr x -> Some x
| _ -> None
/// Get the union cases for a type, if any
member x.UnionCasesArray =
match x.UnionTypeInfo with
| Some x -> x.CasesTable.CasesByIndex
| None -> [| |]
/// Get the union cases for a type, if any, as a list
member x.UnionCasesAsList = x.UnionCasesArray |> Array.toList
/// Get a union case of a type by name
member x.GetUnionCaseByName n =
match x.UnionTypeInfo with
| Some x -> NameMap.tryFind n x.CasesTable.CasesByName
| None -> None
/// Create a new entity with empty, unlinked data. Only used during unpickling of F# metadata.
static member NewUnlinked() : Entity = { Data = nullableSlotEmpty() }
/// Create a new entity with the given backing data. Only used during unpickling of F# metadata.
static member New _reason (data: EntityData) : Entity =
{ Data = data }
/// Link an entity based on empty, unlinked data to the given data. Only used during unpickling of F# metadata.
member x.Link tg = x.Data <- nullableSlotFull(tg)
/// Indicates if the entity is linked to backing data. Only used during unpickling of F# metadata.
member x.IsLinked = match box x.Data with null -> false | _ -> true
override x.ToString() = x.LogicalName
/// Get the blob of information associated with an F# object-model type definition, i.e. class, interface, struct etc.
member x.FSharpObjectModelTypeInfo =
match x.TypeReprInfo with
| TFSharpObjectRepr x -> x
| _ -> assert false; failwith "not an F# object model type definition"
/// Indicate if this is a type definition backed by Abstract IL metadata.
member x.IsILTycon = match x.TypeReprInfo with | TILObjectRepr _ -> true | _ -> false
/// Get the Abstract IL scope, nesting and metadata for this
/// type definition, assuming it is backed by Abstract IL metadata.
member x.ILTyconInfo = match x.TypeReprInfo with | TILObjectRepr (a,b,c) -> (a,b,c) | _ -> assert false; failwith "not a .NET type definition"
/// Get the Abstract IL metadata for this type definition, assuming it is backed by Abstract IL metadata.
member x.ILTyconRawMetadata = let _,_,td = x.ILTyconInfo in td
/// Indicates if this is an F# type definition whose r.h.s. is known to be a record type definition.
member x.IsRecordTycon = match x.TypeReprInfo with | TRecdRepr _ -> true | _ -> false
/// Indicates if this is an F# type definition whose r.h.s. is known to be a record type definition that is a value type.
member x.IsStructRecordOrUnionTycon = match x.TypeReprInfo with TRecdRepr _ | TUnionRepr _ -> x.Data.entity_flags.IsStructRecordOrUnionType | _ -> false
/// Indicates if this is an F# type definition whose r.h.s. is known to be some kind of F# object model definition
member x.IsFSharpObjectModelTycon = match x.TypeReprInfo with | TFSharpObjectRepr _ -> true | _ -> false
/// Indicates if this is an F# type definition which is one of the special types in FSharp.Core.dll which uses
/// an assembly-code representation for the type, e.g. the primitive array type constructor.
member x.IsAsmReprTycon = match x.TypeReprInfo with | TAsmRepr _ -> true | _ -> false
/// Indicates if this is an F# type definition which is one of the special types in FSharp.Core.dll like 'float<_>' which
/// defines a measure type with a relation to an existing non-measure type as a representation.
member x.IsMeasureableReprTycon = match x.TypeReprInfo with | TMeasureableRepr _ -> true | _ -> false
/// Indicates if this is an F# type definition whose r.h.s. definition is unknown (i.e. a traditional ML 'abstract' type in a signature,
/// which in F# is called a 'unknown representation' type).
member x.IsHiddenReprTycon = match x.TypeAbbrev,x.TypeReprInfo with | None,TNoRepr -> true | _ -> false
/// Indicates if this is an F#-defined interface type definition
member x.IsFSharpInterfaceTycon = x.IsFSharpObjectModelTycon && match x.FSharpObjectModelTypeInfo.fsobjmodel_kind with TTyconInterface -> true | _ -> false
/// Indicates if this is an F#-defined delegate type definition
member x.IsFSharpDelegateTycon = x.IsFSharpObjectModelTycon && match x.FSharpObjectModelTypeInfo.fsobjmodel_kind with TTyconDelegate _ -> true | _ -> false
/// Indicates if this is an F#-defined enum type definition
member x.IsFSharpEnumTycon = x.IsFSharpObjectModelTycon && match x.FSharpObjectModelTypeInfo.fsobjmodel_kind with TTyconEnum -> true | _ -> false
/// Indicates if this is an F#-defined class type definition
member x.IsFSharpClassTycon = x.IsFSharpObjectModelTycon && match x.FSharpObjectModelTypeInfo.fsobjmodel_kind with TTyconClass -> true | _ -> false
/// Indicates if this is a .NET-defined enum type definition
member x.IsILEnumTycon = x.IsILTycon && x.ILTyconRawMetadata.IsEnum
/// Indicates if this is an enum type definition
member x.IsEnumTycon =
#if EXTENSIONTYPING
match x.TypeReprInfo with
| TProvidedTypeExtensionPoint info -> info.IsEnum
| TProvidedNamespaceExtensionPoint _ -> false
| _ ->
#endif
x.IsILEnumTycon || x.IsFSharpEnumTycon
/// Indicates if this is an F#-defined struct or enum type definition , i.e. a value type definition
member x.IsFSharpStructOrEnumTycon =
match x.TypeReprInfo with
| TRecdRepr _ -> x.IsStructRecordOrUnionTycon
| TUnionRepr _ -> x.IsStructRecordOrUnionTycon
| TFSharpObjectRepr info ->
match info.fsobjmodel_kind with
| TTyconClass | TTyconInterface | TTyconDelegate _ -> false
| TTyconStruct | TTyconEnum -> true
| _ -> false
/// Indicates if this is a .NET-defined struct or enum type definition , i.e. a value type definition
member x.IsILStructOrEnumTycon =
x.IsILTycon &&
match x.ILTyconRawMetadata.tdKind with
| ILTypeDefKind.ValueType | ILTypeDefKind.Enum -> true
| _ -> false
/// Indicates if this is a struct or enum type definition , i.e. a value type definition
member x.IsStructOrEnumTycon =
#if EXTENSIONTYPING
match x.TypeReprInfo with
| TProvidedTypeExtensionPoint info -> info.IsStructOrEnum
| TProvidedNamespaceExtensionPoint _ -> false
| _ ->
#endif
x.IsILStructOrEnumTycon || x.IsFSharpStructOrEnumTycon
/// Gets the immediate interface definitions of an F# type definition. Further interfaces may be supported through class and interface inheritance.
member x.ImmediateInterfacesOfFSharpTycon =
x.TypeContents.tcaug_interfaces
/// Gets the immediate interface types of an F# type definition. Further interfaces may be supported through class and interface inheritance.
member x.ImmediateInterfaceTypesOfFSharpTycon =
x.ImmediateInterfacesOfFSharpTycon |> List.map (fun (x,_,_) -> x)
/// Gets the immediate members of an F# type definition, excluding compiler-generated ones.
/// Note: result is alphabetically sorted, then for each name the results are in declaration order
member x.MembersOfFSharpTyconSorted =
x.TypeContents.tcaug_adhoc
|> NameMultiMap.rangeReversingEachBucket
|> List.filter (fun v -> not v.IsCompilerGenerated)
/// Gets all immediate members of an F# type definition keyed by name, including compiler-generated ones.
/// Note: result is a indexed table, and for each name the results are in reverse declaration order
member x.MembersOfFSharpTyconByName =
x.TypeContents.tcaug_adhoc
/// Gets any implicit hash/equals (with comparer argument) methods added to an F# record, union or struct type definition.
member x.GeneratedHashAndEqualsWithComparerValues = x.TypeContents.tcaug_hash_and_equals_withc
/// Gets any implicit CompareTo (with comparer argument) methods added to an F# record, union or struct type definition.
member x.GeneratedCompareToWithComparerValues = x.TypeContents.tcaug_compare_withc
/// Gets any implicit CompareTo methods added to an F# record, union or struct type definition.
member x.GeneratedCompareToValues = x.TypeContents.tcaug_compare
/// Gets any implicit hash/equals methods added to an F# record, union or struct type definition.
member x.GeneratedHashAndEqualsValues = x.TypeContents.tcaug_equals
/// Gets all implicit hash/equals/compare methods added to an F# record, union or struct type definition.
member x.AllGeneratedValues =
[ match x.GeneratedCompareToValues with
| None -> ()
| Some (v1,v2) -> yield v1; yield v2
match x.GeneratedCompareToWithComparerValues with
| None -> ()
| Some v -> yield v
match x.GeneratedHashAndEqualsValues with
| None -> ()
| Some (v1,v2) -> yield v1; yield v2
match x.GeneratedHashAndEqualsWithComparerValues with
| None -> ()
| Some (v1,v2,v3) -> yield v1; yield v2; yield v3 ]
/// Gets the data indicating the compiled representation of a type or module in terms of Abstract IL data structures.
member x.CompiledRepresentation =
#if EXTENSIONTYPING
match x.TypeReprInfo with
// We should never be computing this property for erased types
| TProvidedTypeExtensionPoint info when info.IsErased ->
failwith "No compiled representation for provided erased type"
// Generated types that are not relocated just point straight to the generated backing assembly, computed from "st".
// These are used when running F# Interactive, which does not use static linking of provider-generated assemblies,
// and also for types with relocation suppressed.
| TProvidedTypeExtensionPoint info when info.IsGenerated && info.IsSuppressRelocate ->
let st = info.ProvidedType
let tref = ExtensionTyping.GetILTypeRefOfProvidedType (st, x.Range)
let boxity = if x.IsStructOrEnumTycon then AsValue else AsObject
CompiledTypeRepr.ILAsmNamed(tref, boxity, None)
| TProvidedNamespaceExtensionPoint _ -> failwith "No compiled representation for provided namespace"
| _ ->
#endif
let ilTypeRefForCompilationPath (CompPath(sref,p)) item =
let rec top racc p =
match p with
| [] -> ILTypeRef.Create(sref,[],textOfPath (List.rev (item::racc)))
| (h,istype)::t ->
match istype with
| FSharpModuleWithSuffix | ModuleOrType ->
let outerTypeName = (textOfPath (List.rev (h::racc)))
ILTypeRef.Create(sref, (outerTypeName :: List.map (fun (nm,_) -> nm) t),item)
| _ ->
top (h::racc) t
top [] p
cached x.CompiledReprCache (fun () ->
match x.ExceptionInfo with
| TExnAbbrevRepr ecref2 -> ecref2.CompiledRepresentation
| TExnAsmRepr tref -> CompiledTypeRepr.ILAsmNamed(tref, AsObject, Some (mkILTy AsObject (mkILTySpec (tref,[]))))
| _ ->
match x.TypeReprInfo with
| TAsmRepr typ -> CompiledTypeRepr.ILAsmOpen typ
| _ ->
let boxity = if x.IsStructOrEnumTycon then AsValue else AsObject
let ilTypeRef =
match x.TypeReprInfo with
| TILObjectRepr (ilScopeRef,ilEnclosingTypeDefs,ilTypeDef) -> IL.mkRefForNestedILTypeDef ilScopeRef (ilEnclosingTypeDefs, ilTypeDef)
| _ -> ilTypeRefForCompilationPath x.CompilationPath x.CompiledName
// Pre-allocate a ILType for monomorphic types, to reduce memory usage from Abstract IL nodes
let ilTypeOpt =
match x.TyparsNoRange with
| [] -> Some (mkILTy boxity (mkILTySpec (ilTypeRef,[])))
| _ -> None
CompiledTypeRepr.ILAsmNamed (ilTypeRef, boxity, ilTypeOpt))
/// Gets the data indicating the compiled representation of a named type or module in terms of Abstract IL data structures.
member x.CompiledRepresentationForNamedType =
match x.CompiledRepresentation with
| CompiledTypeRepr.ILAsmNamed(tref, _, _) -> tref
| CompiledTypeRepr.ILAsmOpen _ -> invalidOp (FSComp.SR.tastTypeHasAssemblyCodeRepresentation(x.DisplayNameWithStaticParametersAndUnderscoreTypars))
/// Indicates if we have pre-determined that a type definition has a default constructor.
member x.PreEstablishedHasDefaultConstructor = x.Data.entity_flags.PreEstablishedHasDefaultConstructor
/// Indicates if we have pre-determined that a type definition has a self-referential constructor using 'as x'
member x.HasSelfReferentialConstructor = x.Data.entity_flags.HasSelfReferentialConstructor
/// Set the custom attributes on an F# type definition.
member x.SetAttribs attribs = x.Data.entity_attribs <- attribs
/// Sets the structness of a record or union type definition
member x.SetIsStructRecordOrUnion b = let x = x.Data in let flags = x.entity_flags in x.entity_flags <- EntityFlags(flags.IsPrefixDisplay, flags.IsModuleOrNamespace, flags.PreEstablishedHasDefaultConstructor, flags.HasSelfReferentialConstructor, b)
and
[<NoEquality; NoComparison;RequireQualifiedAccess>]
EntityData =
{ /// The declared type parameters of the type
// MUTABILITY; used only during creation and remapping of tycons
mutable entity_typars: LazyWithContext<Typars, range>
// MUTABILITY; used only when establishing tycons.
mutable entity_kind : TyparKind
mutable entity_flags : EntityFlags
/// The unique stamp of the "tycon blob". Note the same tycon in signature and implementation get different stamps
entity_stamp: Stamp
/// The name of the type, possibly with `n mangling
entity_logical_name: string
/// The name of the type, possibly with `n mangling
// MUTABILITY; used only when establishing tycons.
mutable entity_compiled_name: string option
/// The declaration location for the type constructor