-
Notifications
You must be signed in to change notification settings - Fork 854
Expand file tree
/
Copy pathNameResolution.fs
More file actions
5585 lines (4724 loc) · 269 KB
/
NameResolution.fs
File metadata and controls
5585 lines (4724 loc) · 269 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.
/// Name environment and name resolution
module internal FSharp.Compiler.NameResolution
open System.Collections.Generic
open Internal.Utilities.Collections
open Internal.Utilities.Library
open Internal.Utilities.Library.Extras
open Internal.Utilities.Library.ResultOrException
open FSharp.Compiler
open FSharp.Compiler.AbstractIL.Diagnostics
open FSharp.Compiler.AbstractIL.IL
open FSharp.Compiler.AccessibilityLogic
open FSharp.Compiler.AttributeChecking
open FSharp.Compiler.CodeAnalysis
open FSharp.Compiler.DiagnosticsLogger
open FSharp.Compiler.CompilerGlobalState
open FSharp.Compiler.InfoReader
open FSharp.Compiler.Infos
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.Position
open FSharp.Compiler.Text.Range
open FSharp.Compiler.TypedTree
open FSharp.Compiler.TypedTreeBasics
open FSharp.Compiler.TypedTreeOps
open FSharp.Compiler.TypeHierarchy
#if !NO_TYPEPROVIDERS
open FSharp.Compiler.TypeProviders
#endif
exception NoConstructorsAvailableForType of TType * DisplayEnv * range
/// An object that captures the logical context for name resolution.
type NameResolver(g: TcGlobals,
amap: Import.ImportMap,
infoReader: InfoReader,
instantiationGenerator: range -> Typars -> TypeInst) =
/// Used to transform typars into new inference typars
// instantiationGenerator is a function to help us create the
// type parameters by copying them from type parameter specifications read
// from IL code.
//
// When looking up items in generic types we create a fresh instantiation
// of the type, i.e. instantiate the type with inference variables.
// This means the item is returned ready for use by the type inference engine
// without further freshening. However it does mean we end up plumbing 'instantiationGenerator'
// around a bit more than we would like to, which is a bit annoying.
member nr.InstantiationGenerator = instantiationGenerator
member nr.g = g
member nr.amap = amap
member nr.InfoReader = infoReader
member nr.languageSupportsNameOf = g.langVersion.SupportsFeature LanguageFeature.NameOf
//-------------------------------------------------------------------------
// Helpers for unionconstrs and recdfields
//-------------------------------------------------------------------------
/// Get references to all the union cases in the type definition
let UnionCaseRefsInTycon (modref: ModuleOrNamespaceRef) (tycon: Tycon) =
tycon.UnionCasesAsList |> List.map (mkModuleUnionCaseRef modref tycon)
/// Get references to all the union cases defined in the module
let UnionCaseRefsInModuleOrNamespace (modref: ModuleOrNamespaceRef) =
[ for x in modref.ModuleOrNamespaceType.AllEntities do yield! UnionCaseRefsInTycon modref x ]
/// Try to find a type with a union case of the given name
let TryFindTypeWithUnionCase (modref: ModuleOrNamespaceRef) (id: Ident) =
modref.ModuleOrNamespaceType.AllEntities
|> QueueList.tryFind (fun tycon -> tycon.GetUnionCaseByName id.idText |> Option.isSome)
/// Try to find a type with a record field of the given name
let TryFindTypeWithRecdField (modref: ModuleOrNamespaceRef) (id: Ident) =
modref.ModuleOrNamespaceType.AllEntities
|> QueueList.tryFind (fun tycon -> tycon.GetFieldByName id.idText |> Option.isSome)
/// Get the active pattern elements defined by a given value, if any
let ActivePatternElemsOfValRef g (vref: ValRef) =
match TryGetActivePatternInfo vref with
| Some apinfo ->
let retKind =
if apinfo.IsTotal then
ActivePatternReturnKind.RefTypeWrapper
else
let _, apReturnTy = stripFunTy g vref.TauType
let hasStructAttribute() =
vref.Attribs
|> List.exists (function
| Attrib(targetsOpt = Some(System.AttributeTargets.ReturnValue)) as a -> hasFlag (classifyValAttrib g a) WellKnownValAttributes.StructAttribute
| _ -> false)
if isValueOptionTy g apReturnTy || hasStructAttribute() then ActivePatternReturnKind.StructTypeWrapper
elif isBoolTy g apReturnTy then ActivePatternReturnKind.Boolean
else ActivePatternReturnKind.RefTypeWrapper
apinfo.ActiveTags |> List.mapi (fun i _ -> APElemRef(apinfo, vref, i, retKind))
| None -> []
/// Try to make a reference to a value in a module.
//
// mkNestedValRef may fail if the assembly load set is
// incomplete and the value is an extension member of a type that is not
// available. In some cases we can reasonably recover from this, e.g. by simply not adding
// an entry to a table. Callsites have to cope with the error (None) condition
// sensibly, e.g. in a way that won't change the way things are compiled as the
// assembly set is completed.
let TryMkValRefInModRef modref vspec =
protectAssemblyExploration
None
(fun () -> Some (mkNestedValRef modref vspec))
/// Get the active pattern elements defined by a given value, if any
let ActivePatternElemsOfVal g modref vspec =
// If the assembly load set is incomplete then don't add anything to the table
match TryMkValRefInModRef modref vspec with
| None -> []
| Some vref -> ActivePatternElemsOfValRef g vref
/// Get the active pattern elements defined in a module, if any. Cache in the slot in the module type.
let ActivePatternElemsOfModuleOrNamespace g (modref: ModuleOrNamespaceRef) : NameMap<ActivePatternElemRef> =
let mtyp = modref.ModuleOrNamespaceType
cacheOptRef mtyp.ActivePatternElemRefLookupTable (fun () ->
mtyp.AllValsAndMembers
|> Seq.collect (ActivePatternElemsOfVal g modref)
|> Seq.fold (fun acc apref -> NameMap.add apref.LogicalName apref acc) Map.empty)
//---------------------------------------------------------------------------
// Name Resolution Items
//-------------------------------------------------------------------------
/// Represents the item with which a named argument is associated.
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type ArgumentContainer =
/// The named argument is an argument of a method
| Method of MethInfo
/// The named argument is a static parameter to a provided type.
| Type of TyconRef
// Note: Active patterns are encoded like this:
// let (|A|B|) x = if x < 0 then A else B // A and B are reported as results using 'Item.ActivePatternResult'
// match () with | A | B -> () // A and B are reported using 'Item.ActivePatternCase'
let emptyTypeInst : TypeInst = []
type EnclosingTypeInst = TypeInst
let emptyEnclosingTypeInst : EnclosingTypeInst = emptyTypeInst
/// Represents an item that results from name resolution
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type Item =
/// Represents the resolution of a name to an F# value or function.
| Value of ValRef
/// Represents the resolution of a name to an F# union case.
| UnionCase of UnionCaseInfo * hasRequireQualifiedAccessAttr: bool
/// Represents the resolution of a name to an F# active pattern result.
| ActivePatternResult of apinfo: ActivePatternInfo * apOverallTy: TType * index: int * range: range
/// Represents the resolution of a name to an F# active pattern case within the body of an active pattern.
| ActivePatternCase of ActivePatternElemRef
/// Represents the resolution of a name to an F# exception definition.
| ExnCase of TyconRef
/// Represents the resolution of a name to an F# record or exception field.
| RecdField of RecdFieldInfo
/// Represents the resolution of a name to an F# trait
| Trait of TraitConstraintInfo
/// Represents the resolution of a name to a union case field.
| UnionCaseField of UnionCaseInfo * fieldIndex: int
/// Represents the resolution of a name to a field of an anonymous record type.
| AnonRecdField of anonInfo: AnonRecdTypeInfo * tys: TTypes * fieldIndex: int * range: range
// The following are never in the items table but are valid results of binding
// an identifier in different circumstances.
/// Represents the resolution of a name at the point of its own definition.
| NewDef of Ident
/// Represents the resolution of a name to a .NET field
| ILField of ILFieldInfo
/// Represents the resolution of a name to an event
| Event of EventInfo
/// Represents the resolution of a name to a property
| Property of name: string * info: PropInfo list * sourceIdentifierRange: range option
/// Represents the resolution of a name to a group of methods.
| MethodGroup of displayName: string * methods: MethInfo list * uninstantiatedMethodOpt: MethInfo option
/// Represents the resolution of a name to a constructor
| CtorGroup of string * MethInfo list
/// Represents the resolution of a name to a delegate
| DelegateCtor of TType
/// Represents the resolution of a name to a group of types
| Types of string * TType list
/// CustomOperation(nm, helpText, methInfo)
///
/// Used to indicate the availability or resolution of a custom query operation such as 'sortBy' or 'where' in computation expression syntax
| CustomOperation of string * (unit -> string option) * MethInfo option
/// Represents the resolution of a name to a custom builder in the F# computation expression syntax
| CustomBuilder of string * ValRef
/// Represents the resolution of a name to a type variable
| TypeVar of string * Typar
/// Represents the resolution of a name to a module or namespace
| ModuleOrNamespaces of ModuleOrNamespaceRef list
/// Represents the resolution of a name to an operator
| ImplicitOp of Ident * TraitConstraintSln option ref
/// Represents the resolution of a name to a named argument
//
// In the FCS API, Item.OtherName corresponds to FSharpParameter symbols.
// Not all parameters have names, e.g. for 'g' in this:
//
// let f (g: int -> int) x = ...
//
// then the symbol for 'g' reports FSharpParameters via CurriedParameterGroups
// based on analyzing the type of g as a function type.
//
// For these parameters, the identifier will be missing.
| OtherName of ident: Ident option * argType: TType * argInfo: ArgReprInfo option * container: ArgumentContainer option * range: range
/// Represents the resolution of a name to a named property setter
| SetterArg of Ident * Item
/// Represents the potential resolution of an unqualified name to a type.
| UnqualifiedType of TyconRef list
static member MakeMethGroup (nm, minfos: MethInfo list) =
let minfos = minfos |> List.sortBy (fun minfo -> minfo.NumArgs |> List.sum)
Item.MethodGroup (nm, minfos, None)
static member MakeCtorGroup (nm, minfos: MethInfo list) =
let minfos = minfos |> List.sortBy (fun minfo -> minfo.NumArgs |> List.sum)
Item.CtorGroup (nm, minfos)
member d.DisplayNameCore =
match d with
| Item.Value v -> v.DisplayNameCore
| Item.ActivePatternResult (apinfo, _ty, n, _) -> apinfo.DisplayNameCoreByIdx n
| Item.ActivePatternCase apref -> apref.DisplayNameCore
| Item.UnionCase(uinfo, _) -> uinfo.DisplayNameCore
| Item.ExnCase tcref -> tcref.DisplayNameCore
| Item.RecdField rfinfo -> rfinfo.DisplayNameCore
| Item.UnionCaseField (uci, fieldIndex) -> uci.UnionCase.GetFieldByIndex(fieldIndex).DisplayNameCore
| Item.AnonRecdField (anonInfo, _tys, fieldIndex, _m) -> anonInfo.DisplayNameCoreByIdx fieldIndex
| Item.NewDef id -> id.idText
| Item.ILField finfo -> finfo.DisplayNameCore
| Item.Event einfo -> einfo.DisplayNameCore
| Item.Property(info = pinfo :: _) -> pinfo.DisplayNameCore
| Item.Property(name = nm) -> nm |> ConvertValLogicalNameToDisplayNameCore
| Item.MethodGroup(_, FSMeth(_, _, v, _) :: _, _) -> v.DisplayNameCore
| Item.MethodGroup(nm, _, _) -> nm |> ConvertValLogicalNameToDisplayNameCore
| Item.CtorGroup(nm, ILMeth(_, ilMethInfo, _) :: _) ->
match ilMethInfo.ApparentEnclosingType |> tryNiceEntityRefOfTy with
| ValueSome tcref -> tcref.DisplayNameCore
| _ -> nm
|> DemangleGenericTypeName
| Item.CtorGroup(nm, _) -> nm |> DemangleGenericTypeName
| Item.DelegateCtor ty ->
match ty with
| AbbrevOrAppTy(tcref, _) -> tcref.DisplayNameCore
// This case is not expected
| _ -> ""
| Item.UnqualifiedType(tcref :: _) -> tcref.DisplayNameCore
| Item.Types(nm, _) -> nm |> DemangleGenericTypeName
| Item.TypeVar (nm, _) -> nm
| Item.Trait traitInfo -> traitInfo.MemberDisplayNameCore
| Item.ModuleOrNamespaces(modref :: _) -> modref.DisplayNameCore
| Item.OtherName (ident = Some id) -> id.idText
| Item.OtherName (ident = None) -> ""
| Item.SetterArg (id, _) -> id.idText
| Item.CustomOperation (customOpName, _, _) -> customOpName
| Item.CustomBuilder (nm, _) -> nm
| Item.ImplicitOp (id, _) -> id.idText
//| _ -> ""
// These singleton cases are not expected
| Item.ModuleOrNamespaces [] -> ""
| Item.UnqualifiedType [] -> ""
member d.DisplayName =
match d with
| Item.Value v -> v.DisplayName
| Item.UnionCase(uinfo, _) -> uinfo.DisplayName
| Item.ExnCase tcref -> tcref.DisplayName
| Item.RecdField rfinfo -> rfinfo.DisplayName
| Item.UnionCaseField (uci, fieldIndex) -> uci.UnionCase.GetFieldByIndex(fieldIndex).DisplayName
| Item.AnonRecdField (anonInfo, _tys, fieldIndex, _m) -> anonInfo.DisplayNameByIdx fieldIndex
| Item.ActivePatternCase apref -> apref.DisplayName
| Item.Property(info = pinfo :: _) -> pinfo.DisplayName
| Item.Event einfo -> einfo.DisplayName
| Item.MethodGroup(_, minfo :: _, _) -> minfo.DisplayName
| Item.DelegateCtor (AbbrevOrAppTy(tcref, _)) -> tcref.DisplayName
| Item.UnqualifiedType(tcref :: _) -> tcref.DisplayName
| Item.ModuleOrNamespaces(modref :: _) -> modref.DisplayName
| Item.TypeVar (nm, _) -> nm |> ConvertLogicalNameToDisplayName
| Item.OtherName (ident = Some id) -> id.idText |> ConvertValLogicalNameToDisplayName false
| Item.OtherName (ident = None) -> ""
| _ -> d.DisplayNameCore |> ConvertLogicalNameToDisplayName
let valRefHash (vref: ValRef) =
match vref.TryDeref with
| ValueNone -> 0
| ValueSome v -> LanguagePrimitives.PhysicalHash v
/// Pairs an Item with a TyparInstantiation showing how generic type variables of the item are instantiated at
/// a particular usage point.
[<RequireQualifiedAccess>]
type ItemWithInst =
{ Item: Item
TyparInstantiation: TyparInstantiation }
let ItemWithNoInst item = ({ Item = item; TyparInstantiation = emptyTyparInst } : ItemWithInst)
let (|ItemWithInst|) (x: ItemWithInst) = (x.Item, x.TyparInstantiation)
/// Represents a record field resolution and the information if the usage is deprecated.
type FieldResolution = FieldResolution of RecdFieldInfo * bool
/// Information about an extension member held in the name resolution environment
type ExtensionMember =
/// F#-style Extrinsic extension member, defined in F# code
| FSExtMem of ValRef * ExtensionMethodPriority
/// ILExtMem(declaringTyconRef, ilMetadata, pri)
///
/// IL-style extension member, backed by some kind of method with an [<Extension>] attribute
| ILExtMem of TyconRef * MethInfo * ExtensionMethodPriority
/// Check if two extension members refer to the same definition
static member Equality g e1 e2 =
match e1, e2 with
| FSExtMem (vref1, _), FSExtMem (vref2, _) -> valRefEq g vref1 vref2
| ILExtMem (_, md1, _), ILExtMem (_, md2, _) -> MethInfo.MethInfosUseIdenticalDefinitions md1 md2
| _ -> false
static member Hash e1 =
match e1 with
| FSExtMem(vref, _) -> valRefHash vref
| ILExtMem(_, m, _) ->
match m with
| ILMeth(_, ilmeth, _) -> LanguagePrimitives.PhysicalHash ilmeth.RawMetadata
| FSMeth(_, _, vref, _) -> valRefHash vref
| _ -> 0
static member Comparer g = HashIdentity.FromFunctions ExtensionMember.Hash (ExtensionMember.Equality g)
/// Describes the sequence order of the introduction of an extension method. Extension methods that are introduced
/// later through 'open' get priority in overload resolution.
member x.Priority =
match x with
| FSExtMem (_, pri) -> pri
| ILExtMem (_, _, pri) -> pri
type FullyQualifiedFlag =
/// Only resolve full paths
| FullyQualified
/// Resolve any paths accessible via 'open'
| OpenQualified
/// Indicates whether an identifier (single or long) is followed by an extra dot. Typically used
/// to provide better tooling and error reporting.
[<RequireQualifiedAccess>]
type ExtraDotAfterIdentifier =
| Yes
| No
type UnqualifiedItems = LayeredMap<string, Item>
/// The environment of information used to resolve names
[<NoEquality; NoComparison>]
type NameResolutionEnv =
{ /// Display environment information for output
eDisplayEnv: DisplayEnv
/// Values, functions, methods and other items available by unqualified name
eUnqualifiedItems: UnqualifiedItems
/// Enclosing type instantiations that are associated with an unqualified type item
eUnqualifiedEnclosingTypeInsts: TyconRefMap<EnclosingTypeInst>
/// Data Tags and Active Pattern Tags available by unqualified name
ePatItems: NameMap<Item>
/// Modules accessible via "." notation. Note this is a multi-map.
/// Adding a module abbreviation adds it a local entry to this List.map.
/// Likewise adding a ccu or opening a path adds entries to this List.map.
/// REVIEW (old comment)
/// "The boolean flag is means the namespace or module entry shouldn't 'really' be in the
/// map, and if it is ever used to resolve a name then we give a warning.
/// This is used to give warnings on unqualified namespace accesses, e.g.
/// open System
/// open Collections <--- give a warning
/// let v = new Collections.Generic.List<int>() <--- give a warning"
eModulesAndNamespaces: NameMultiMap<ModuleOrNamespaceRef>
/// Fully qualified modules and namespaces. 'open' does not change this.
eFullyQualifiedModulesAndNamespaces: NameMultiMap<ModuleOrNamespaceRef>
/// RecdField labels in scope. RecdField labels are those where type are inferred
/// by label rather than by known type annotation.
/// Bools indicate if from a record, where no warning is given on indeterminate lookup
eFieldLabels: NameMultiMap<RecdFieldRef>
/// Record or unions that may have type instantiations associated with them
/// when record labels or union cases are used in an unqualified context.
eUnqualifiedRecordOrUnionTypeInsts: TyconRefMap<TypeInst>
/// Tycons indexed by the various names that may be used to access them, e.g.
/// "List" --> multiple TyconRef's for the various tycons accessible by this name.
/// "List`1" --> TyconRef
eTyconsByAccessNames: LayeredMultiMap<string, TyconRef>
eFullyQualifiedTyconsByAccessNames: LayeredMultiMap<string, TyconRef>
/// Tycons available by unqualified, demangled names (i.e. (List, 1) --> TyconRef)
eTyconsByDemangledNameAndArity: LayeredMap<NameArityPair, TyconRef>
/// Tycons available by unqualified, demangled names (i.e. (List, 1) --> TyconRef)
eFullyQualifiedTyconsByDemangledNameAndArity: LayeredMap<NameArityPair, TyconRef>
/// Extension members by type and name
eIndexedExtensionMembers: TyconRefMultiMap<ExtensionMember>
/// Other extension members unindexed by type
eUnindexedExtensionMembers: ExtensionMember list
/// Typars (always available by unqualified names). Further typars can be
/// in the tpenv, a structure folded through each top-level definition.
eTypars: NameMap<Typar>
}
/// The initial, empty name resolution environment. The mother of all things.
static member Empty g =
{ eDisplayEnv = DisplayEnv.Empty g
eModulesAndNamespaces = Map.empty
eFullyQualifiedModulesAndNamespaces = Map.empty
eFieldLabels = Map.empty
eUnqualifiedRecordOrUnionTypeInsts = TyconRefMap.Empty
eUnqualifiedItems = LayeredMap.Empty
eUnqualifiedEnclosingTypeInsts = TyconRefMap.Empty
ePatItems = Map.empty
eTyconsByAccessNames = LayeredMultiMap.Empty
eTyconsByDemangledNameAndArity = LayeredMap.Empty
eFullyQualifiedTyconsByAccessNames = LayeredMultiMap.Empty
eFullyQualifiedTyconsByDemangledNameAndArity = LayeredMap.Empty
eIndexedExtensionMembers = TyconRefMultiMap<_>.Empty
eUnindexedExtensionMembers = []
eTypars = Map.empty }
member nenv.DisplayEnv = nenv.eDisplayEnv
member nenv.FindUnqualifiedItem nm = nenv.eUnqualifiedItems[nm]
/// Get the table of types, indexed by name and arity
member nenv.TyconsByDemangledNameAndArity fq =
match fq with
| FullyQualified -> nenv.eFullyQualifiedTyconsByDemangledNameAndArity
| OpenQualified -> nenv.eTyconsByDemangledNameAndArity
/// Get the table of types, indexed by name
member nenv.TyconsByAccessNames fq =
match fq with
| FullyQualified -> nenv.eFullyQualifiedTyconsByAccessNames
| OpenQualified -> nenv.eTyconsByAccessNames
/// Get the table of modules and namespaces
member nenv.ModulesAndNamespaces fq =
match fq with
| FullyQualified -> nenv.eFullyQualifiedModulesAndNamespaces
| OpenQualified -> nenv.eModulesAndNamespaces
//-------------------------------------------------------------------------
// Helpers to do with extension members
//-------------------------------------------------------------------------
/// Indicates if a lookup requires a match on the instance/static characteristic.
///
/// This is not supplied at all lookup sites - in theory it could be, but currently diagnostics on many paths
/// rely on returning all the content and then filtering it later for instance/static characteristic.
///
/// The isInstanceFilter also doesn't filter all content - it is currently only applied to filter out extension methods
/// that have a static/instance mismatch.
[<RequireQualifiedAccess>]
type LookupIsInstance =
| Ambivalent
| Yes
| No
/// Indicates if we only need one result or all possible results from a resolution.
[<RequireQualifiedAccess>]
type ResultCollectionSettings =
| AllResults
| AtMostOneResult
/// Allocate the next extension method priority. This is an incrementing sequence of integers
/// during type checking.
let NextExtensionMethodPriority() = uint64 (newStamp())
/// Checks if the type is used for C# style extension members.
let IsTyconRefUsedForCSharpStyleExtensionMembers g m (tcref: TyconRef) =
// Type must be non-generic and have 'Extension' attribute
match metadataOfTycon tcref.Deref with
| ILTypeMetadata(TILObjectReprData(_, _, tdef)) -> tdef.CanContainExtensionMethods
| _ -> true
&& isNil(tcref.Typars m) && TyconRefHasWellKnownAttribute g WellKnownILAttributes.ExtensionAttribute tcref
/// Checks if the type is used for C# style extension members.
let IsTypeUsedForCSharpStyleExtensionMembers g m ty =
match tryTcrefOfAppTy g ty with
| ValueSome tcref -> IsTyconRefUsedForCSharpStyleExtensionMembers g m tcref
| _ -> false
/// A 'plain' method is an extension method not interpreted as an extension method.
let IsMethInfoPlainCSharpStyleExtensionMember g m isEnclExtTy (minfo: MethInfo) =
// Method must be static, have 'Extension' attribute, must not be curried, must have at least one argument
isEnclExtTy &&
not minfo.IsInstance &&
not minfo.IsExtensionMember &&
(match minfo.NumArgs with [x] when x >= 1 -> true | _ -> false) &&
MethInfoHasWellKnownAttributeSpec
g
m
{ ILFlag = WellKnownILAttributes.ExtensionAttribute
ValFlag = WellKnownValAttributes.ExtensionAttribute
AttribInfo = g.attrib_ExtensionAttribute }
minfo
let GetTyconRefForExtensionMembers minfo (deref: Entity) amap m g =
try
let rs =
match metadataOfTycon deref, minfo with
| ILTypeMetadata (TILObjectReprData(scope=scoref)), ILMeth(ilMethInfo=ILMethInfo(ilMethodDef=ilMethod)) ->
match ilMethod.ParameterTypes with
| firstTy :: _ ->
match firstTy with
| ILType.Boxed tspec | ILType.Value tspec ->
let tref = (tspec |> rescopeILTypeSpec scoref).TypeRef
if Import.CanImportILTypeRef amap m tref then
let tcref = tref |> Import.ImportILTypeRef amap m
if isCompiledTupleTyconRef g tcref || tyconRefEq g tcref g.fastFunc_tcr then None
else Some tcref
else None
| _ -> None
| _ -> None
| _ ->
// The results are indexed by the TyconRef of the first 'this' argument, if any.
// So we need to go and crack the type of the 'this' argument.
let thisTy = minfo.GetParamTypes(amap, m, generalizeTypars minfo.FormalMethodTypars).Head.Head
match thisTy with
| AppTy g (tcrefOfTypeExtended, _) when not (isByrefTy g thisTy) -> Some tcrefOfTypeExtended
| _ -> None
Some rs
with RecoverableException e -> // Import of the ILType may fail, if so report the error and skip on
errorRecovery e m
None
/// Get the info for all the .NET-style extension members listed as static members in the type.
let private GetCSharpStyleIndexedExtensionMembersForTyconRef (amap: Import.ImportMap) m (tcrefOfStaticClass: TyconRef) =
let g = amap.g
let isApplicable =
IsTyconRefUsedForCSharpStyleExtensionMembers g m tcrefOfStaticClass ||
g.langVersion.SupportsFeature(LanguageFeature.CSharpExtensionAttributeNotRequired) &&
tcrefOfStaticClass.IsLocalRef &&
not tcrefOfStaticClass.IsTypeAbbrev
if not isApplicable then [] else
let ty = generalizedTyconRef g tcrefOfStaticClass
let pri = NextExtensionMethodPriority()
let methods =
protectAssemblyExploration []
(fun () -> GetImmediateIntrinsicMethInfosOfType (None, AccessorDomain.AccessibleFromSomeFSharpCode) g amap m ty)
[ for minfo in methods do
if IsMethInfoPlainCSharpStyleExtensionMember g m true minfo then
let ilExtMem = ILExtMem (tcrefOfStaticClass, minfo, pri)
// The results are indexed by the TyconRef of the first 'this' argument, if any.
// So we need to go and crack the type of the 'this' argument.
//
// This is convoluted because we only need the ILTypeRef of the first argument, and we don't
// want to read any other metadata as it can trigger missing-assembly errors. It turns out ImportILTypeRef
// is less eager in reading metadata than GetParamTypes.
//
// We don't use the index for the IL extension method for tuple of F# function types (e.g. if extension
// methods for tuple occur in C# code)
let thisTyconRef = GetTyconRefForExtensionMembers minfo tcrefOfStaticClass.Deref amap m g
match thisTyconRef with
| None -> ()
| Some (Some tcref) -> yield Choice1Of2(tcref, ilExtMem)
| Some None -> yield Choice2Of2 ilExtMem ]
/// Query the declared properties of a type (including inherited properties)
let IntrinsicPropInfosOfTypeInScope (infoReader: InfoReader) optFilter ad findFlag m ty =
let g = infoReader.g
let amap = infoReader.amap
let pinfos = GetIntrinsicPropInfoSetsOfType infoReader optFilter ad AllowMultiIntfInstantiations.Yes findFlag m ty
let pinfos = pinfos |> ExcludeHiddenOfPropInfos g amap m
pinfos
/// Select from a list of extension properties
let SelectPropInfosFromExtMembers (infoReader: InfoReader) ad optFilter declaringTy m extMemInfos =
let g = infoReader.g
let amap = infoReader.amap
// NOTE: multiple "open"'s push multiple duplicate values into eIndexedExtensionMembers, hence use a set.
let seen = HashSet(ExtensionMember.Comparer g)
let propCollector = PropertyCollector(g, amap, m, declaringTy, optFilter, ad)
for emem in extMemInfos do
if seen.Add emem then
match emem with
| FSExtMem (vref, _pri) ->
match vref.MemberInfo with
| None -> ()
| Some membInfo -> propCollector.Collect(membInfo, vref)
| ILExtMem _ ->
// No extension properties coming from .NET
()
propCollector.Close()
/// Query the available extension properties of a type (including extension properties for inherited types)
let ExtensionPropInfosOfTypeInScope collectionSettings (infoReader:InfoReader) (nenv: NameResolutionEnv) optFilter isInstanceFilter ad m ty =
let g = infoReader.g
let extMemsDangling = SelectPropInfosFromExtMembers infoReader ad optFilter ty m nenv.eUnindexedExtensionMembers
let pinfos =
if collectionSettings = ResultCollectionSettings.AtMostOneResult && not (isNil extMemsDangling) then
extMemsDangling
else
let extMemsFromHierarchy =
infoReader.GetEntireTypeHierarchy(AllowMultiIntfInstantiations.Yes, m, ty)
|> List.collect (fun ty ->
match tryTcrefOfAppTy g ty with
| ValueSome tcref ->
let extMemInfos = nenv.eIndexedExtensionMembers.Find tcref
SelectPropInfosFromExtMembers infoReader ad optFilter ty m extMemInfos
| _ -> [])
extMemsDangling @ extMemsFromHierarchy
pinfos
|> List.filter (fun pinfo ->
match isInstanceFilter with
| LookupIsInstance.Ambivalent -> true
| LookupIsInstance.Yes -> not pinfo.IsStatic
| LookupIsInstance.No -> pinfo.IsStatic)
/// Get all the available properties of a type (both intrinsic and extension)
let AllPropInfosOfTypeInScope collectionSettings infoReader nenv optFilter ad findFlag m ty =
IntrinsicPropInfosOfTypeInScope infoReader optFilter ad findFlag m ty
@ ExtensionPropInfosOfTypeInScope collectionSettings infoReader nenv optFilter LookupIsInstance.Ambivalent ad m ty
/// Get the available methods of a type (both declared and inherited)
let IntrinsicMethInfosOfType (infoReader: InfoReader) optFilter ad allowMultiIntfInst findFlag m ty =
let g = infoReader.g
let amap = infoReader.amap
let minfos = GetIntrinsicMethInfoSetsOfType infoReader optFilter ad allowMultiIntfInst findFlag m ty
let minfos = minfos |> ExcludeHiddenOfMethInfos g amap m
minfos
let rec TrySelectExtensionMethInfoOfILExtMem m amap apparentTy (actualParent, minfo, pri) =
match minfo with
| ILMeth(_,ilminfo,_) ->
MethInfo.CreateILExtensionMeth (amap, m, apparentTy, actualParent, Some pri, ilminfo.RawMetadata) |> Some
// F#-defined IL-style extension methods are not seen as extension methods in F# code
| FSMeth(g,_,vref,_) ->
FSMeth(g, apparentTy, vref, Some pri) |> Some
| MethInfoWithModifiedReturnType(mi,_) -> TrySelectExtensionMethInfoOfILExtMem m amap apparentTy (actualParent, mi, pri)
#if !NO_TYPEPROVIDERS
// // Provided extension methods are not yet supported
| ProvidedMeth(amap,providedMeth,_,m) ->
ProvidedMeth(amap, providedMeth, Some pri,m) |> Some
#endif
| DefaultStructCtor _ ->
None
/// Select from a list of extension methods
let SelectMethInfosFromExtMembers (infoReader: InfoReader) optFilter apparentTy m extMemInfos =
let g = infoReader.g
// NOTE: multiple "open"'s push multiple duplicate values into eIndexedExtensionMembers
let seen = HashSet(ExtensionMember.Comparer g)
[
for emem in extMemInfos do
if seen.Add emem then
match emem with
| FSExtMem (vref, pri) ->
match vref.MemberInfo with
| None -> ()
| Some membInfo ->
match TrySelectMemberVal g optFilter apparentTy (Some pri) membInfo vref with
| Some m -> yield m
| _ -> ()
| ILExtMem (actualParent, minfo, pri) when (match optFilter with None -> true | Some nm -> nm = minfo.LogicalName) ->
// Make a reference to the type containing the extension members
match TrySelectExtensionMethInfoOfILExtMem m infoReader.amap apparentTy (actualParent, minfo, pri) with
| Some minfo -> yield minfo
| None -> ()
| _ -> ()
]
/// Query the available extension methods of a type (including extension methods for inherited types)
let ExtensionMethInfosOfTypeInScope (collectionSettings: ResultCollectionSettings) (infoReader: InfoReader) (nenv: NameResolutionEnv) ad optFilter isInstanceFilter m ty =
let amap = infoReader.amap
let extMemsDangling = SelectMethInfosFromExtMembers infoReader optFilter ty m nenv.eUnindexedExtensionMembers
if collectionSettings = ResultCollectionSettings.AtMostOneResult && not (isNil extMemsDangling) then
extMemsDangling
else
let extMemsFromHierarchy =
infoReader.GetEntireTypeHierarchy(AllowMultiIntfInstantiations.Yes, m, ty)
|> List.collect (fun ty ->
let g = infoReader.g
match tryTcrefOfAppTy g ty with
| ValueSome tcref ->
let extValRefs = nenv.eIndexedExtensionMembers.Find tcref
SelectMethInfosFromExtMembers infoReader optFilter ty m extValRefs
| _ -> [])
extMemsDangling @ extMemsFromHierarchy
|> List.filter (fun minfo ->
let isAccesible = AccessibilityLogic.IsMethInfoAccessible amap m ad minfo
isAccesible &&
match isInstanceFilter with
| LookupIsInstance.Ambivalent -> true
| LookupIsInstance.Yes -> minfo.IsInstance
| LookupIsInstance.No -> not minfo.IsInstance)
/// Get all the available methods of a type (both intrinsic and extension)
let AllMethInfosOfTypeInScope collectionSettings infoReader nenv optFilter ad findFlag m ty =
let intrinsic = IntrinsicMethInfosOfType infoReader optFilter ad AllowMultiIntfInstantiations.Yes findFlag m ty
if collectionSettings = ResultCollectionSettings.AtMostOneResult && not (isNil intrinsic) then
intrinsic
else
intrinsic @ ExtensionMethInfosOfTypeInScope collectionSettings infoReader nenv ad optFilter LookupIsInstance.Ambivalent m ty
let IsExtensionMethCompatibleWithTy g amap m (ty: TType) (minfo: MethInfo) =
not minfo.IsExtensionMember ||
match minfo.GetObjArgTypes(amap, m, []) with
| thisTy :: _ ->
let ty1 = thisTy |> stripTyEqns g
let ty2 = ty |> stripTyEqns g
match ty1, ty2 with
| TType_var (tp1, _), _ ->
tp1.Constraints |> List.exists (function
| TyparConstraint.CoercesTo(targetCTy, _) ->
let cTy = targetCTy |> stripTyEqns g
TypeRelations.TypeFeasiblySubsumesType 0 g amap m cTy TypeRelations.CanCoerce ty2
| _ -> false)
| _, TType_var _ -> true
| _ ->
TypeRelations.TypeFeasiblySubsumesType 0 g amap m ty1 TypeRelations.CanCoerce ty2
| _ ->
true
//-------------------------------------------------------------------------
// Helpers to do with building environments
//-------------------------------------------------------------------------
/// For the operations that build the overall name resolution
/// tables, BulkAdd.Yes is set to true when "opening" a
/// namespace. If BulkAdd is true then add-and-collapse
/// is used for the backing maps.Multiple "open" operations are
/// thus coalesced, and the first subsequent lookup after a sequence
/// of opens will collapse the maps and build the backing dictionary.
[<RequireQualifiedAccess>]
type BulkAdd = Yes | No
/// bulkAddMode: true when adding the values from the 'open' of a namespace
/// or module, when we collapse the value table down to a dictionary.
let AddValRefsToItems (bulkAddMode: BulkAdd) (eUnqualifiedItems: UnqualifiedItems) (vrefs: ValRef[]) =
// Object model members are not added to the unqualified name resolution environment
let vrefs = vrefs |> Array.filter (fun vref -> not vref.IsMember)
if vrefs.Length = 0 then eUnqualifiedItems else
match bulkAddMode with
| BulkAdd.Yes ->
eUnqualifiedItems.AddMany(vrefs |> Array.map (fun vref -> KeyValuePair(vref.LogicalName, Item.Value vref)))
| BulkAdd.No ->
assert (vrefs.Length = 1)
let vref = vrefs[0]
eUnqualifiedItems.Add (vref.LogicalName, Item.Value vref)
/// Add an F# value to the table of available extension members, if necessary, as an FSharp-style extension member
let AddValRefToExtensionMembers pri (eIndexedExtensionMembers: TyconRefMultiMap<_>) (vref: ValRef) =
if vref.IsMember && vref.IsExtensionMember then
eIndexedExtensionMembers.Add (vref.MemberApparentEntity, FSExtMem (vref, pri))
else
eIndexedExtensionMembers
/// This entry point is used to add some extra items to the environment for Visual Studio, e.g. static members
let AddFakeNamedValRefToNameEnv nm nenv vref =
{nenv with eUnqualifiedItems = nenv.eUnqualifiedItems.Add (nm, Item.Value vref) }
/// This entry point is used to add some extra items to the environment for Visual Studio, e.g. record members
let AddFakeNameToNameEnv nm nenv item =
{nenv with eUnqualifiedItems = nenv.eUnqualifiedItems.Add (nm, item) }
/// Add an F# value to the table of available active patterns
let AddValRefsToActivePatternsNameEnv g ePatItems (vref: ValRef) =
let ePatItems =
(ActivePatternElemsOfValRef g vref, ePatItems)
||> List.foldBack (fun apref tab ->
NameMap.add apref.LogicalName (Item.ActivePatternCase apref) tab)
// Add literal constants to the environment available for resolving items in patterns
let ePatItems =
match vref.LiteralValue with
| None -> ePatItems
| Some _ -> NameMap.add vref.LogicalName (Item.Value vref) ePatItems
ePatItems
/// Add a set of F# values to the environment.
let AddValRefsToNameEnvWithPriority g bulkAddMode pri nenv (vrefs: ValRef []) =
if vrefs.Length = 0 then nenv else
{ nenv with
eUnqualifiedItems = AddValRefsToItems bulkAddMode nenv.eUnqualifiedItems vrefs
eIndexedExtensionMembers = (nenv.eIndexedExtensionMembers, vrefs) ||> Array.fold (AddValRefToExtensionMembers pri)
ePatItems = (nenv.ePatItems, vrefs) ||> Array.fold (AddValRefsToActivePatternsNameEnv g) }
/// Add a single F# value to the environment.
let AddValRefToNameEnv g nenv (vref: ValRef) =
let pri = NextExtensionMethodPriority()
{ nenv with
eUnqualifiedItems =
if not vref.IsMember then
nenv.eUnqualifiedItems.Add (vref.LogicalName, Item.Value vref)
else
nenv.eUnqualifiedItems
eIndexedExtensionMembers = AddValRefToExtensionMembers pri nenv.eIndexedExtensionMembers vref
ePatItems = AddValRefsToActivePatternsNameEnv g nenv.ePatItems vref }
/// Add a set of active pattern result tags to the environment.
let AddActivePatternResultTagsToNameEnv (apinfo: ActivePatternInfo) nenv apOverallTy m =
if List.isEmpty apinfo.ActiveTags then nenv else
let apResultNameList = List.indexed apinfo.ActiveTags
{ nenv with
eUnqualifiedItems =
(apResultNameList, nenv.eUnqualifiedItems)
||> List.foldBack (fun (j, nm) acc -> acc.Add(nm, Item.ActivePatternResult(apinfo, apOverallTy, j, m))) }
/// Generalize a union case, from Cons --> List<T>.Cons
let GeneralizeUnionCaseRef (ucref: UnionCaseRef) =
UnionCaseInfo (generalTyconRefInst ucref.TyconRef, ucref)
/// Add type definitions to the sub-table of the environment indexed by name and arity
let AddTyconsByDemangledNameAndArity (bulkAddMode: BulkAdd) (tcrefs: TyconRef[]) (tab: LayeredMap<NameArityPair, TyconRef>) =
if tcrefs.Length = 0 then tab else
let entries =
tcrefs
|> Array.map (fun tcref -> Construct.KeyTyconByDecodedName tcref.LogicalName tcref)
match bulkAddMode with
| BulkAdd.Yes -> tab.AddMany entries
| BulkAdd.No -> (tab, entries) ||> Array.fold (fun tab (KeyValue(k, v)) -> tab.Add(k, v))
/// Add type definitions to the sub-table of the environment indexed by access name
let AddTyconByAccessNames bulkAddMode (tcrefs: TyconRef[]) (tab: LayeredMultiMap<string, _>) =
if tcrefs.Length = 0 then tab else
let entries =
tcrefs
|> Array.collect (fun tcref -> Construct.KeyTyconByAccessNames tcref.LogicalName tcref)
match bulkAddMode with
| BulkAdd.Yes -> tab.AddMany entries
| BulkAdd.No -> (tab, entries) ||> Array.fold (fun tab (KeyValue(k, v)) -> tab.Add (k, v))
/// Add a record field to the corresponding sub-table of the name resolution environment
let AddRecdField (rfref: RecdFieldRef) tab = NameMultiMap.add rfref.FieldName rfref tab
/// Add a set of union cases to the corresponding sub-table of the environment
let AddUnionCases1 (tab: Map<_, _>) (ucrefs: UnionCaseRef list) =
(tab, ucrefs) ||> List.fold (fun acc ucref ->
let item = Item.UnionCase(GeneralizeUnionCaseRef ucref, false)
acc.Add (ucref.CaseName, item))
/// Add a set of union cases to the corresponding sub-table of the environment
let AddUnionCases2 bulkAddMode (eUnqualifiedItems: UnqualifiedItems) (ucrefs: UnionCaseRef list) =
match bulkAddMode with
| BulkAdd.Yes ->
let items =
ucrefs |> Array.ofList |> Array.map (fun ucref ->
let item = Item.UnionCase(GeneralizeUnionCaseRef ucref, false)
KeyValuePair(ucref.CaseName, item))
eUnqualifiedItems.AddMany items
| BulkAdd.No ->
(eUnqualifiedItems, ucrefs) ||> List.fold (fun acc ucref ->
let item = Item.UnionCase(GeneralizeUnionCaseRef ucref, false)
acc.Add (ucref.CaseName, item))
//-------------------------------------------------------------------------
// TypeNameResolutionInfo
//-------------------------------------------------------------------------
/// Indicates whether we are resolving type names to type definitions or to constructor methods.
type TypeNameResolutionFlag =
| ResolveTypeNamesToCtors
| ResolveTypeNamesToTypeRefs
/// Represents information about the generic argument count of a type name when resolving it.
///
/// In some situations we resolve "List" to any type definition with that name regardless of the number
/// of generic arguments. In others, we know precisely how many generic arguments are needed.
[<RequireQualifiedAccess>]
[<NoEquality; NoComparison>]
type TypeNameResolutionStaticArgsInfo =
/// Indicates indefinite knowledge of type arguments
| Indefinite
/// Indicates definite knowledge of type arguments
| Definite of int
/// Indicates definite knowledge of empty type arguments
static member DefiniteEmpty = TypeNameResolutionStaticArgsInfo.Definite 0
static member FromTyArgs (numTyArgs: int) = TypeNameResolutionStaticArgsInfo.Definite numTyArgs
member x.HasNoStaticArgsInfo = match x with TypeNameResolutionStaticArgsInfo.Indefinite -> true | _-> false
member x.NumStaticArgs = match x with TypeNameResolutionStaticArgsInfo.Indefinite -> 0 | TypeNameResolutionStaticArgsInfo.Definite n -> n
// Get the first possible mangled name of the type, assuming the args are generic args
member x.MangledNameForType nm =
if x.NumStaticArgs = 0 || TryDemangleGenericNameAndPos nm <> ValueNone then nm
else nm + "`" + string x.NumStaticArgs
/// Represents information which guides name resolution of types.
[<NoEquality; NoComparison>]
type TypeNameResolutionInfo =
| TypeNameResolutionInfo of TypeNameResolutionFlag * TypeNameResolutionStaticArgsInfo
static member Default = TypeNameResolutionInfo (ResolveTypeNamesToCtors, TypeNameResolutionStaticArgsInfo.Indefinite)
static member ResolveToTypeRefs statResInfo = TypeNameResolutionInfo (ResolveTypeNamesToTypeRefs, statResInfo)
member x.StaticArgsInfo = match x with TypeNameResolutionInfo(_, staticResInfo) -> staticResInfo
member x.ResolutionFlag = match x with TypeNameResolutionInfo(flag, _) -> flag
member x.DropStaticArgsInfo = match x with TypeNameResolutionInfo(flag2, _) -> TypeNameResolutionInfo(flag2, TypeNameResolutionStaticArgsInfo.Indefinite)
/// A flag which indicates if direct references to generated provided types are allowed. Normally these
/// are disallowed.
[<RequireQualifiedAccess>]
type PermitDirectReferenceToGeneratedType =
| Yes
| No
#if !NO_TYPEPROVIDERS
/// Check for direct references to generated provided types.
let CheckForDirectReferenceToGeneratedType (tcref: TyconRef, genOk, m) =
match genOk with
| PermitDirectReferenceToGeneratedType.Yes -> ()
| PermitDirectReferenceToGeneratedType.No ->
match tcref.TypeReprInfo with
| TProvidedTypeRepr info when not info.IsErased ->
if IsGeneratedTypeDirectReference (info.ProvidedType, m) then
error (Error(FSComp.SR.etDirectReferenceToGeneratedTypeNotAllowed(tcref.DisplayName), m))
| _ -> ()
/// This adds a new entity for a lazily discovered provided type into the TAST structure.
let AddEntityForProvidedType (amap: Import.ImportMap, modref: ModuleOrNamespaceRef, resolutionEnvironment, st: Tainted<ProvidedType>, m) =
let importProvidedType t = Import.ImportProvidedType amap m t
let isSuppressRelocate = amap.g.isInteractive || st.PUntaint((fun st -> st.IsSuppressRelocate), m)
let tycon = Construct.NewProvidedTycon(resolutionEnvironment, st, importProvidedType, isSuppressRelocate, m)
modref.ModuleOrNamespaceType.AddProvidedTypeEntity tycon
let tcref = modref.NestedTyconRef tycon
System.Diagnostics.Debug.Assert(modref.TryDeref.IsSome)
tcref