Skip to content

Commit 6452dba

Browse files
committed
extension witness implementation
1 parent e07132b commit 6452dba

File tree

31 files changed

+609
-309
lines changed

31 files changed

+609
-309
lines changed

src/fsharp/AccessibilityLogic.fs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ type AccessorDomain =
3737
/// An AccessorDomain which returns all items
3838
| AccessibleFromSomewhere
3939

40+
interface TraitAccessorDomain
41+
4042
// Hashing and comparison is used for the memoization tables keyed by an accessor domain.
4143
// It is dependent on a TcGlobals because of the TyconRef in the data structure
4244
static member CustomGetHashCode(ad:AccessorDomain) =
@@ -45,6 +47,7 @@ type AccessorDomain =
4547
| AccessibleFromEverywhere -> 2
4648
| AccessibleFromSomeFSharpCode -> 3
4749
| AccessibleFromSomewhere -> 4
50+
4851
static member CustomEquals(g:TcGlobals, ad1:AccessorDomain, ad2:AccessorDomain) =
4952
match ad1, ad2 with
5053
| AccessibleFrom(cs1, tc1), AccessibleFrom(cs2, tc2) -> (cs1 = cs2) && (match tc1, tc2 with None, None -> true | Some tc1, Some tc2 -> tyconRefEq g tc1 tc2 | _ -> false)

src/fsharp/CheckFormatStrings.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ open FSharp.Compiler.NameResolution
1515
type FormatItem = Simple of TType | FuncAndVal
1616

1717
let copyAndFixupFormatTypar m tp =
18-
let _,_,tinst = FreshenAndFixupTypars m TyparRigidity.Flexible [] [] [tp]
18+
let _,_,tinst = FreshenAndFixupTypars None m TyparRigidity.Flexible [] [] [tp]
1919
List.head tinst
2020

2121
let lowestDefaultPriority = 0 (* See comment on TyparConstraint.DefaultsTo *)

src/fsharp/CompileOptions.fs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1716,7 +1716,6 @@ let ApplyAllOptimizations (tcConfig:TcConfig, tcGlobals, tcVal, outfile, importM
17161716
let optSettings = tcConfig.optSettings
17171717
let optSettings = { optSettings with abstractBigTargets = tcConfig.doTLR }
17181718
let optSettings = { optSettings with reportingPhase = true }
1719-
17201719
let results, (optEnvFirstLoop, _, _, _) =
17211720
((optEnv0, optEnv0, optEnv0, SignatureHidingInfo.Empty), implFiles)
17221721

src/fsharp/ConstraintSolver.fs

Lines changed: 224 additions & 128 deletions
Large diffs are not rendered by default.

src/fsharp/ConstraintSolver.fsi

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ open FSharp.Compiler
77
open FSharp.Compiler.AccessibilityLogic
88
open FSharp.Compiler.Ast
99
open FSharp.Compiler.ErrorLogger
10+
open FSharp.Compiler.NameResolution
1011
open FSharp.Compiler.Tast
1112
open FSharp.Compiler.Range
1213
open FSharp.Compiler.Import
@@ -34,18 +35,27 @@ val NewErrorMeasure : unit -> Measure
3435
/// Create a list of inference type variables, one for each element in the input list
3536
val NewInferenceTypes : 'a list -> TType list
3637

38+
/// Freshen a trait for use at a particular location
39+
type TraitFreshener = (TraitConstraintInfo -> TraitPossibleExtensionMemberSolutions * TraitAccessorDomain)
40+
3741
/// Given a set of formal type parameters and their constraints, make new inference type variables for
3842
/// each and ensure that the constraints on the new type variables are adjusted to refer to these.
39-
val FreshenAndFixupTypars : range -> TyparRigidity -> Typars -> TType list -> Typars -> Typars * TyparInst * TType list
43+
val FreshenAndFixupTypars : TraitFreshener option -> range -> TyparRigidity -> Typars -> TType list -> Typars -> Typars * TyparInst * TType list
44+
45+
/// Make new type inference variables for the use of a generic construct at a particular location
46+
val FreshenTypeInst : TraitFreshener option -> range -> Typars -> Typars * TyparInst * TType list
4047

41-
val FreshenTypeInst : range -> Typars -> Typars * TyparInst * TType list
48+
/// Make new type inference variables for the use of a generic construct at a particular location
49+
val FreshenTypars : TraitFreshener option -> range -> Typars -> TType list
4250

43-
val FreshenTypars : range -> Typars -> TType list
51+
/// Make new type inference variables for the use of a method at a particular location
52+
val FreshenMethInfo : TraitFreshener option -> range -> MethInfo -> TType list
4453

45-
val FreshenMethInfo : range -> MethInfo -> TType list
54+
/// Get the trait freshener for a particular location
55+
val GetTraitFreshner : AccessorDomain -> NameResolutionEnv -> TraitFreshener
4656

4757
[<RequireQualifiedAccess>]
48-
/// Information about the context of a type equation.
58+
/// Information about the context of a type equation, for better error reporting
4959
type ContextInfo =
5060

5161
/// No context was given.
@@ -163,4 +173,7 @@ val CodegenWitnessThatTypeSupportsTraitConstraint : TcValF -> TcGlobals -> Impor
163173

164174
val ChooseTyparSolutionAndSolve : ConstraintSolverState -> DisplayEnv -> Typar -> unit
165175

176+
/// Get the type variables that may help provide solutions to a statically resolved member trait constraint
177+
val GetSupportOfMemberConstraint : ConstraintSolverEnv -> TraitConstraintInfo -> Typar list
178+
166179
val IsApplicableMethApprox : TcGlobals -> ImportMap -> range -> MethInfo -> TType -> bool

src/fsharp/FSComp.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1080,7 +1080,7 @@ lexIndentOffForML,"Consider using a file with extension '.ml' or '.mli' instead"
10801080
1212,tcOptionalArgsMustComeAfterNonOptionalArgs,"Optional arguments must come at the end of the argument list, after any non-optional arguments"
10811081
1213,tcConditionalAttributeUsage,"Attribute 'System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes"
10821082
#1214,monoRegistryBugWorkaround,"Could not determine highest installed .NET framework version from Registry keys, using version 2.0"
1083-
1215,tcMemberOperatorDefinitionInExtrinsic,"Extension members cannot provide operator overloads. Consider defining the operator as part of the type definition instead."
1083+
#1215,tcMemberOperatorDefinitionInExtrinsic,"Extension members cannot provide operator overloads. Consider defining the operator as part of the type definition instead."
10841084
1216,ilwriteMDBFileNameCannotBeChangedWarning,"The name of the MDB file must be <assembly-file-name>.mdb. The --pdb option will be ignored."
10851085
1217,ilwriteMDBMemberMissing,"MDB generation failed. Could not find compatible member %s"
10861086
1218,ilwriteErrorCreatingMdb,"Cannot generate MDB debug information. Failed to load the 'MonoSymbolWriter' type from the 'Mono.CompilerServices.SymbolWriter.dll' assembly."

src/fsharp/FindUnsolved.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ and accOp cenv env (op, tyargs, args, _m) =
135135
accTypeInst cenv env enclTypeArgs
136136
accTypeInst cenv env methTypeArgs
137137
accTypeInst cenv env tys
138-
| TOp.TraitCall (TTrait(tys, _nm, _, argtys, rty, _sln)) ->
138+
| TOp.TraitCall (TTrait(tys, _nm, _, argtys, rty, _sln, _extSlns, _ad)) ->
139139
argtys |> accTypeInst cenv env
140140
rty |> Option.iter (accTy cenv env)
141141
tys |> List.iter (accTy cenv env)

src/fsharp/MethodCalls.fs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,12 +1037,12 @@ let BuildFSharpMethodApp g m (vref: ValRef) vexp vexprty (args: Exprs) =
10371037
retTy
10381038

10391039
/// Build a call to an F# method.
1040-
let BuildFSharpMethodCall g m (ty, vref: ValRef) valUseFlags minst args =
1040+
let BuildFSharpMethodCall g m (vref: ValRef) valUseFlags declaringTypeInst minst args =
10411041
let vexp = Expr.Val (vref, valUseFlags, m)
10421042
let vexpty = vref.Type
1043-
let tpsorig, tau = vref.TypeScheme
1044-
let vtinst = argsOfAppTy g ty @ minst
1045-
if tpsorig.Length <> vtinst.Length then error(InternalError("BuildFSharpMethodCall: unexpected List.length mismatch", m))
1043+
let tpsorig,tau = vref.TypeScheme
1044+
let vtinst = declaringTypeInst @ minst
1045+
if tpsorig.Length <> vtinst.Length then error(InternalError("BuildFSharpMethodCall: unexpected typar length mismatch",m))
10461046
let expr = mkTyAppExpr m (vexp, vexpty) vtinst
10471047
let exprty = instType (mkTyparInst tpsorig vtinst) tau
10481048
BuildFSharpMethodApp g m vref expr exprty args
@@ -1060,8 +1060,8 @@ let MakeMethInfoCall amap m minfo minst args =
10601060
let isProp = false // not necessarily correct, but this is only used post-creflect where this flag is irrelevant
10611061
BuildILMethInfoCall g amap m isProp ilminfo valUseFlags minst direct args |> fst
10621062

1063-
| FSMeth(g, ty, vref, _) ->
1064-
BuildFSharpMethodCall g m (ty, vref) valUseFlags minst args |> fst
1063+
| FSMeth(g, _, vref, _) ->
1064+
BuildFSharpMethodCall g m vref valUseFlags minfo.DeclaringTypeInst minst args |> fst
10651065

10661066
| DefaultStructCtor(_, ty) ->
10671067
mkDefault (m, ty)

src/fsharp/NameResolution.fs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,8 @@ type ExtensionMember =
284284
/// IL-style extension member, backed by some kind of method with an [<Extension>] attribute
285285
| ILExtMem of TyconRef * MethInfo * ExtensionMethodPriority
286286

287+
interface TraitPossibleExtensionMemberSolution
288+
287289
/// Check if two extension members refer to the same definition
288290
static member Equality g e1 e2 =
289291
match e1, e2 with
@@ -309,7 +311,12 @@ type ExtensionMember =
309311
| FSExtMem (_, pri) -> pri
310312
| ILExtMem (_, _, pri) -> pri
311313

312-
type FullyQualifiedFlag =
314+
member x.LogicalName =
315+
match x with
316+
| FSExtMem (vref, _) -> vref.LogicalName
317+
| ILExtMem (_, minfo, _) -> minfo.LogicalName
318+
319+
type FullyQualifiedFlag =
313320
/// Only resolve full paths
314321
| FullyQualified
315322
/// Resolve any paths accessible via 'open'
@@ -369,6 +376,9 @@ type NameResolutionEnv =
369376
/// Extension members by type and name
370377
eIndexedExtensionMembers: TyconRefMultiMap<ExtensionMember>
371378

379+
/// Extension members by name
380+
eExtensionMembersByName: NameMultiMap<ExtensionMember>
381+
372382
/// Other extension members unindexed by type
373383
eUnindexedExtensionMembers: ExtensionMember list
374384

@@ -391,6 +401,7 @@ type NameResolutionEnv =
391401
eFullyQualifiedTyconsByAccessNames = LayeredMultiMap.Empty
392402
eFullyQualifiedTyconsByDemangledNameAndArity = LayeredMap.Empty
393403
eIndexedExtensionMembers = TyconRefMultiMap<_>.Empty
404+
eExtensionMembersByName = NameMultiMap<_>.Empty
394405
eUnindexedExtensionMembers = []
395406
eTypars = Map.empty }
396407

@@ -658,6 +669,17 @@ let AddValRefToExtensionMembers pri (eIndexedExtensionMembers: TyconRefMultiMap<
658669
else
659670
eIndexedExtensionMembers
660671

672+
/// Add an F# value to the table of available extension members, if necessary, as an FSharp-style extension member
673+
let AddValRefToExtensionMembersByNameTable logicalName (eExtensionMembersByName: NameMultiMap<_>) extMemInfo =
674+
NameMultiMap.add logicalName extMemInfo eExtensionMembersByName
675+
676+
/// Add an F# value to the table of available extension members, if necessary, as an FSharp-style extension member
677+
let AddValRefToExtensionMembersByName pri (eExtensionMembersByName: NameMultiMap<_>) (vref:ValRef) =
678+
if vref.IsMember && vref.IsExtensionMember then
679+
AddValRefToExtensionMembersByNameTable vref.LogicalName eExtensionMembersByName (FSExtMem (vref,pri))
680+
else
681+
eExtensionMembersByName
682+
661683

662684
/// This entry point is used to add some extra items to the environment for Visual Studio, e.g. static members
663685
let AddFakeNamedValRefToNameEnv nm nenv vref =
@@ -688,6 +710,7 @@ let AddValRefsToNameEnvWithPriority bulkAddMode pri nenv (vrefs: ValRef []) =
688710
{ nenv with
689711
eUnqualifiedItems = AddValRefsToItems bulkAddMode nenv.eUnqualifiedItems vrefs
690712
eIndexedExtensionMembers = (nenv.eIndexedExtensionMembers, vrefs) ||> Array.fold (AddValRefToExtensionMembers pri)
713+
eExtensionMembersByName = (nenv.eExtensionMembersByName, vrefs) ||> Array.fold (AddValRefToExtensionMembersByName pri)
691714
ePatItems = (nenv.ePatItems, vrefs) ||> Array.fold AddValRefsToActivePatternsNameEnv }
692715

693716
/// Add a single F# value to the environment.
@@ -700,6 +723,7 @@ let AddValRefToNameEnv nenv (vref: ValRef) =
700723
else
701724
nenv.eUnqualifiedItems
702725
eIndexedExtensionMembers = AddValRefToExtensionMembers pri nenv.eIndexedExtensionMembers vref
726+
eExtensionMembersByName = AddValRefToExtensionMembersByName pri nenv.eExtensionMembersByName vref
703727
ePatItems = AddValRefsToActivePatternsNameEnv nenv.ePatItems vref }
704728

705729

@@ -808,12 +832,12 @@ let private AddPartsOfTyconRefToNameEnv bulkAddMode ownDefinition (g: TcGlobals)
808832
let ucrefs = if isIL then [] else tcref.UnionCasesAsList |> List.map tcref.MakeNestedUnionCaseRef
809833
let flds = if isIL then [| |] else tcref.AllFieldsArray
810834

811-
let eIndexedExtensionMembers, eUnindexedExtensionMembers =
835+
let eIndexedExtensionMembers, eExtensionMembersByName, eUnindexedExtensionMembers =
812836
let ilStyleExtensionMeths = GetCSharpStyleIndexedExtensionMembersForTyconRef amap m tcref
813-
((nenv.eIndexedExtensionMembers, nenv.eUnindexedExtensionMembers), ilStyleExtensionMeths) ||> List.fold (fun (tab1, tab2) extMemInfo ->
837+
((nenv.eIndexedExtensionMembers, nenv.eExtensionMembersByName, nenv.eUnindexedExtensionMembers),ilStyleExtensionMeths) ||> List.fold (fun (tab1,tab2,tab3) extMemInfo ->
814838
match extMemInfo with
815-
| Choice1Of2 (tcref, extMemInfo) -> tab1.Add (tcref, extMemInfo), tab2
816-
| Choice2Of2 extMemInfo -> tab1, extMemInfo :: tab2)
839+
| Choice1Of2 (tcref, extMemInfo) -> tab1.Add (tcref, extMemInfo), AddValRefToExtensionMembersByNameTable extMemInfo.LogicalName tab2 extMemInfo, tab3
840+
| Choice2Of2 extMemInfo -> tab1, AddValRefToExtensionMembersByNameTable extMemInfo.LogicalName tab2 extMemInfo, extMemInfo :: tab3)
817841

818842
let isILOrRequiredQualifiedAccess = isIL || (not ownDefinition && HasFSharpAttribute g g.attrib_RequireQualifiedAccessAttribute tcref.Attribs)
819843
let eFieldLabels =
@@ -871,6 +895,7 @@ let private AddPartsOfTyconRefToNameEnv bulkAddMode ownDefinition (g: TcGlobals)
871895
eUnqualifiedItems = eUnqualifiedItems
872896
ePatItems = ePatItems
873897
eIndexedExtensionMembers = eIndexedExtensionMembers
898+
eExtensionMembersByName = eExtensionMembersByName
874899
eUnindexedExtensionMembers = eUnindexedExtensionMembers }
875900

876901
let nenv =

src/fsharp/NameResolution.fsi

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,11 @@ type ExtensionMember =
150150
/// IL-style extension member, backed by some kind of method with an [<Extension>] attribute
151151
| ILExtMem of TyconRef * MethInfo * ExtensionMethodPriority
152152

153+
interface TraitPossibleExtensionMemberSolution
154+
155+
/// The logical name, e.g. for constraint solving
156+
member LogicalName : string
157+
153158
/// Describes the sequence order of the introduction of an extension method. Extension methods that are introduced
154159
/// later through 'open' get priority in overload resolution.
155160
member Priority : ExtensionMethodPriority
@@ -169,8 +174,9 @@ type NameResolutionEnv =
169174
/// Modules accessible via "." notation. Note this is a multi-map.
170175
/// Adding a module abbreviation adds it a local entry to this List.map.
171176
/// Likewise adding a ccu or opening a path adds entries to this List.map.
177+
172178
eModulesAndNamespaces: NameMultiMap<Tast.ModuleOrNamespaceRef>
173-
179+
174180
/// Fully qualified modules and namespaces. 'open' does not change this.
175181
eFullyQualifiedModulesAndNamespaces: NameMultiMap<Tast.ModuleOrNamespaceRef>
176182

@@ -195,6 +201,9 @@ type NameResolutionEnv =
195201
/// Extension members by type and name
196202
eIndexedExtensionMembers: TyconRefMultiMap<ExtensionMember>
197203

204+
/// Extension members by name
205+
eExtensionMembersByName: NameMultiMap<ExtensionMember>
206+
198207
/// Other extension members unindexed by type
199208
eUnindexedExtensionMembers: ExtensionMember list
200209

@@ -589,5 +598,5 @@ val GetVisibleNamespacesAndModulesAtPoint : NameResolver -> NameResolutionEnv ->
589598

590599
val IsItemResolvable : NameResolver -> NameResolutionEnv -> range -> AccessorDomain -> string list -> Item -> bool
591600

592-
val TrySelectExtensionMethInfoOfILExtMem : range -> ImportMap -> TType -> TyconRef * MethInfo * ExtensionMethodPriority -> MethInfo option
593-
601+
val TrySelectExtensionMethInfoOfILExtMem : range -> ImportMap -> TType -> TyconRef * MethInfo * ExtensionMethodPriority -> MethInfo option
602+

0 commit comments

Comments
 (0)