diff --git a/src/fsharp/AccessibilityLogic.fs b/src/fsharp/AccessibilityLogic.fs index c69d00cd0a0..dc9d9593f99 100644 --- a/src/fsharp/AccessibilityLogic.fs +++ b/src/fsharp/AccessibilityLogic.fs @@ -40,6 +40,8 @@ type AccessorDomain = /// An AccessorDomain which returns all items | AccessibleFromSomewhere + interface TraitAccessorDomain + // Hashing and comparison is used for the memoization tables keyed by an accessor domain. // It is dependent on a TcGlobals because of the TyconRef in the data structure static member CustomGetHashCode(ad:AccessorDomain) = @@ -48,6 +50,7 @@ type AccessorDomain = | AccessibleFromEverywhere -> 2 | AccessibleFromSomeFSharpCode -> 3 | AccessibleFromSomewhere -> 4 + static member CustomEquals(g:TcGlobals, ad1:AccessorDomain, ad2:AccessorDomain) = match ad1, ad2 with | AccessibleFrom(cs1,tc1), AccessibleFrom(cs2,tc2) -> (cs1 = cs2) && (match tc1,tc2 with None,None -> true | Some tc1, Some tc2 -> tyconRefEq g tc1 tc2 | _ -> false) diff --git a/src/fsharp/CheckFormatStrings.fs b/src/fsharp/CheckFormatStrings.fs index 3ca134907c4..fa0002f8706 100644 --- a/src/fsharp/CheckFormatStrings.fs +++ b/src/fsharp/CheckFormatStrings.fs @@ -15,7 +15,7 @@ open Microsoft.FSharp.Compiler.ConstraintSolver type FormatItem = Simple of TType | FuncAndVal let copyAndFixupFormatTypar m tp = - let _,_,tinst = FreshenAndFixupTypars m TyparRigidity.Flexible [] [] [tp] + let _,_,tinst = FreshenAndFixupTypars None m TyparRigidity.Flexible [] [] [tp] List.head tinst let lowestDefaultPriority = 0 (* See comment on TyparConstraint.DefaultsTo *) diff --git a/src/fsharp/CompileOptions.fs b/src/fsharp/CompileOptions.fs index 1c78fd9aa33..1ce35f6625e 100644 --- a/src/fsharp/CompileOptions.fs +++ b/src/fsharp/CompileOptions.fs @@ -1269,7 +1269,6 @@ let ApplyAllOptimizations (tcConfig:TcConfig, tcGlobals, tcVal, outfile, importM let optSettings = tcConfig.optSettings let optSettings = { optSettings with abstractBigTargets = tcConfig.doTLR } let optSettings = { optSettings with reportingPhase = true } - let results,(optEnvFirstLoop,_,_,_) = ((optEnv0,optEnv0,optEnv0,SignatureHidingInfo.Empty),implFiles) ||> List.mapFold (fun (optEnvFirstLoop,optEnvExtraLoop,optEnvFinalSimplify,hidden) implFile -> @@ -1356,7 +1355,7 @@ let GenerateIlxCode (ilxBackend, isInteractiveItExpr, isInteractiveOnMono, tcCon isInteractiveItExpr = isInteractiveItExpr alwaysCallVirt = tcConfig.alwaysCallVirt } - ilxGenerator.GenerateCode (ilxGenOpts, optimizedImpls, topAttrs.assemblyAttrs,topAttrs.netModuleAttrs) + ilxGenerator.GenerateCode (ilxGenOpts, optimizedImpls, topAttrs.assemblyAttrs, topAttrs.netModuleAttrs) //---------------------------------------------------------------------------- // Assembly ref normalization: make sure all assemblies are referred to diff --git a/src/fsharp/ConstraintSolver.fs b/src/fsharp/ConstraintSolver.fs index 0ec8f9f832a..6434101a3ce 100644 --- a/src/fsharp/ConstraintSolver.fs +++ b/src/fsharp/ConstraintSolver.fs @@ -32,7 +32,8 @@ module internal Microsoft.FSharp.Compiler.ConstraintSolver open Internal.Utilities.Collections -open Microsoft.FSharp.Compiler +open Microsoft.FSharp.Compiler +open Microsoft.FSharp.Compiler.NameResolution open Microsoft.FSharp.Compiler.AbstractIL open Microsoft.FSharp.Compiler.AbstractIL.Internal open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library @@ -81,29 +82,32 @@ let NewErrorMeasure () = Measure.Var (NewErrorMeasureVar ()) let NewInferenceTypes l = l |> List.map (fun _ -> NewInferenceType ()) +/// Freshen a trait for use at a particular location +type TraitFreshener = (TraitConstraintInfo -> TraitPossibleExtensionMemberSolutions * TraitAccessorDomain) + // QUERY: should 'rigid' ever really be 'true'? We set this when we know // we are going to have to generalize a typar, e.g. when implementing a // abstract generic method slot. But we later check the generalization // condition anyway, so we could get away with a non-rigid typar. This // would sort of be cleaner, though give errors later. -let FreshenAndFixupTypars m rigid fctps tinst tpsorig = +let FreshenAndFixupTypars (traitFreshner: TraitFreshener option) m rigid fctps tinst tpsorig = let copy_tyvar (tp:Typar) = NewCompGenTypar (tp.Kind, rigid, tp.StaticReq, (if rigid=TyparRigidity.Rigid then TyparDynamicReq.Yes else TyparDynamicReq.No), false) let tps = tpsorig |> List.map copy_tyvar - let renaming, tinst = FixupNewTypars m fctps tinst tpsorig tps + let renaming, tinst = FixupNewTypars traitFreshner m fctps tinst tpsorig tps tps, renaming, tinst -let FreshenTypeInst m tpsorig = FreshenAndFixupTypars m TyparRigidity.Flexible [] [] tpsorig -let FreshMethInst m fctps tinst tpsorig = FreshenAndFixupTypars m TyparRigidity.Flexible fctps tinst tpsorig +let FreshenTypeInst traitFreshner m tpsorig = FreshenAndFixupTypars traitFreshner m TyparRigidity.Flexible [] [] tpsorig +let FreshenMethInst traitFreshner m fctps tinst tpsorig = FreshenAndFixupTypars traitFreshner m TyparRigidity.Flexible fctps tinst tpsorig -let FreshenTypars m tpsorig = +let FreshenTypars traitFreshner m tpsorig = match tpsorig with | [] -> [] | _ -> - let _, _, tptys = FreshenTypeInst m tpsorig + let _, _, tptys = FreshenTypeInst traitFreshner m tpsorig tptys -let FreshenMethInfo m (minfo:MethInfo) = - let _, _, tptys = FreshMethInst m (minfo.GetFormalTyparsOfDeclaringType m) minfo.DeclaringTypeInst minfo.FormalMethodTypars +let FreshenMethInfo traitFreshner m (minfo:MethInfo) = + let _, _, tptys = FreshenMethInst traitFreshner m (minfo.GetFormalTyparsOfDeclaringType m) minfo.DeclaringTypeInst minfo.FormalMethodTypars tptys @@ -115,32 +119,32 @@ let FreshenMethInfo m (minfo:MethInfo) = [] /// Information about the context of a type equation. type ContextInfo = -/// No context was given. -| NoContext -/// The type equation comes from an IF expression. -| IfExpression of range -/// The type equation comes from an omitted else branch. -| OmittedElseBranch of range -/// The type equation comes from a type check of the result of an else branch. -| ElseBranchResult of range -/// The type equation comes from the verification of record fields. -| RecordFields -/// The type equation comes from the verification of a tuple in record fields. -| TupleInRecordFields -/// The type equation comes from a list or array constructor -| CollectionElement of bool * range -/// The type equation comes from a return in a computation expression. -| ReturnInComputationExpression -/// The type equation comes from a yield in a computation expression. -| YieldInComputationExpression -/// The type equation comes from a runtime type test. -| RuntimeTypeTest of bool -/// The type equation comes from an downcast where a upcast could be used. -| DowncastUsedInsteadOfUpcast of bool -/// The type equation comes from a return type of a pattern match clause (not the first clause). -| FollowingPatternMatchClause of range -/// The type equation comes from a pattern match guard. -| PatternMatchGuard of range + /// No context was given. + | NoContext + /// The type equation comes from an IF expression. + | IfExpression of range + /// The type equation comes from an omitted else branch. + | OmittedElseBranch of range + /// The type equation comes from a type check of the result of an else branch. + | ElseBranchResult of range + /// The type equation comes from the verification of record fields. + | RecordFields + /// The type equation comes from the verification of a tuple in record fields. + | TupleInRecordFields + /// The type equation comes from a list or array constructor + | CollectionElement of bool * range + /// The type equation comes from a return in a computation expression. + | ReturnInComputationExpression + /// The type equation comes from a yield in a computation expression. + | YieldInComputationExpression + /// The type equation comes from a runtime type test. + | RuntimeTypeTest of bool + /// The type equation comes from an downcast where a upcast could be used. + | DowncastUsedInsteadOfUpcast of bool + /// The type equation comes from a return type of a pattern match clause (not the first clause). + | FollowingPatternMatchClause of range + /// The type equation comes from a pattern match guard. + | PatternMatchGuard of range exception ConstraintSolverTupleDiffLengths of DisplayEnv * TType list * TType list * range * range exception ConstraintSolverInfiniteTypes of ContextInfo * DisplayEnv * TType * TType * range * range @@ -191,7 +195,7 @@ type ConstraintSolverEnv = MatchingOnly: bool m: range EquivEnv: TypeEquivEnv - DisplayEnv: DisplayEnv + DisplayEnv : DisplayEnv } member csenv.InfoReader = csenv.SolverState.InfoReader member csenv.g = csenv.SolverState.g @@ -270,11 +274,17 @@ let isFpTy g ty = let isDecimalTy g ty = typeEquivAux EraseMeasures g g.decimal_ty ty -let IsNonDecimalNumericOrIntegralEnumType g ty = isIntegerOrIntegerEnumTy g ty || isFpTy g ty -let IsNumericOrIntegralEnumType g ty = IsNonDecimalNumericOrIntegralEnumType g ty || isDecimalTy g ty -let IsNonDecimalNumericType g ty = isIntegerTy g ty || isFpTy g ty -let IsNumericType g ty = IsNonDecimalNumericType g ty || isDecimalTy g ty -let IsRelationalType g ty = IsNumericType g ty || isStringTy g ty || isCharTy g ty || isBoolTy g ty +let IsNonDecimalNumericOrIntegralEnumTy g ty = isIntegerOrIntegerEnumTy g ty || isFpTy g ty +let IsIntegerOrEnumTy g ty = isIntegerOrIntegerEnumTy g ty || isEnumTy g ty +let IsNumericOrIntegralEnumTy g ty = IsNonDecimalNumericOrIntegralEnumTy g ty || isDecimalTy g ty +let IsNonDecimalNumericTy g ty = isIntegerTy g ty || isFpTy g ty +let IsNumericTy g ty = IsNonDecimalNumericTy g ty || isDecimalTy g ty +let IsNumericOrCharTy g ty = IsNumericTy g ty || isCharTy g ty +let IsRelationalTy g ty = IsNumericTy g ty || isStringTy g ty || isCharTy g ty || isBoolTy g ty +let IsFpOrDecimalTy g ty = isFpTy g ty || isDecimalTy g ty +let IsSignedIntegerOrFpOrDecimalTy g ty = isSignedIntegerTy g ty || IsFpOrDecimalTy g ty +let IsCharOrStringTy g ty = isCharTy g ty || isStringTy g ty +let IsNumericOrIntegralEnumOrCharOrStringTy g ty = IsNumericOrIntegralEnumTy g ty || IsCharOrStringTy g ty // Get measure of type, float<_> or float32<_> or decimal<_> but not float=float<1> or float32=float32<1> or decimal=decimal<1> let GetMeasureOfType g ty = @@ -709,7 +719,7 @@ let rec SolveTyparEqualsTyp (csenv:ConstraintSolverEnv) ndeep m2 (trace:Optional // Check to see if this type variable is relevant to any trait constraints. // If so, re-solve the relevant constraints. (if csenv.SolverState.ExtraCxs.ContainsKey r.Stamp then - RepeatWhileD ndeep (fun ndeep -> SolveRelevantMemberConstraintsForTypar csenv ndeep false trace r) + RepeatWhileD ndeep (fun ndeep -> SolveRelevantMemberConstraintsForTypar csenv ndeep (*permitWeakResolution*)false trace r) else CompleteD) ++ (fun _ -> @@ -750,7 +760,7 @@ and solveTypMeetsTyparConstraints (csenv:ConstraintSolverEnv) ndeep m2 trace ty | TyparConstraint.SimpleChoice(tys, m2) -> SolveTypChoice csenv ndeep m2 trace ty tys | TyparConstraint.CoercesTo(ty2, m2) -> SolveTypSubsumesTypKeepAbbrevs csenv ndeep m2 trace None ty2 ty | TyparConstraint.MayResolveMember(traitInfo, m2) -> - SolveMemberConstraint csenv false false ndeep m2 trace traitInfo ++ (fun _ -> CompleteD) + SolveMemberConstraint csenv false (*permitWeakResolution*)false ndeep m2 trace traitInfo ++ (fun _ -> CompleteD) ))) @@ -790,7 +800,7 @@ and SolveTypEqualsTyp (csenv:ConstraintSolverEnv) ndeep m2 (trace: OptionalTrace -> SolveTypEqualsTyp csenv ndeep m2 trace None ms (TType_measure Measure.One) | TType_app (tc1, l1) , TType_app (tc2, l2) when tyconRefEq g tc1 tc2 -> SolveTypEqualsTypEqns csenv ndeep m2 trace None l1 l2 - | TType_app (_, _) , TType_app (_, _) -> localAbortD + | TType_app _ , TType_app _ -> localAbortD | TType_tuple (tupInfo1, l1) , TType_tuple (tupInfo2, l2) -> if evalTupInfoIsStruct tupInfo1 <> evalTupInfoIsStruct tupInfo2 then ErrorD (ConstraintSolverError(FSComp.SR.tcTupleStructMismatch(), csenv.m, m2)) else SolveTypEqualsTypEqns csenv ndeep m2 trace None l1 l2 @@ -938,12 +948,25 @@ and SolveDimensionlessNumericType (csenv:ConstraintSolverEnv) ndeep m2 trace ty | None -> CompleteD -/// We do a bunch of fakery to pretend that primitive types have certain members. -/// We pretend int and other types support a number of operators. In the actual IL for mscorlib they -/// don't, however the type-directed static optimization rules in the library code that makes use of this -/// will deal with the problem. -and SolveMemberConstraint (csenv:ConstraintSolverEnv) ignoreUnresolvedOverload permitWeakResolution ndeep m2 trace (TTrait(tys, nm, memFlags, argtys, rty, sln)): OperationResult = +/// Attempt to solve a statically resolved member constraint. +/// +/// 1. We do a bunch of fakery to pretend that primitive types have certain members. +/// We pretend int and other types support a number of operators. In the actual IL for mscorlib they +/// don't. The type-directed static optimization rules in the library code that makes use of this +/// will deal with the problem. +/// +/// 2. Some additional solutions are forced prior to generalization (permitWeakResolution=true). These are, roughly speaking, rules +/// for binary-operand constraints arising from constructs such as "1.0 + x" where "x" is an unknown type. THe constraint here +/// involves two type parameters - one for the left, and one for the right. The left is already known to be Double. +/// In this situation (and in the absence of other evidence prior to generalization), constraint solving forces an assumption that +/// the right is also Double - this is "weak" because there is only weak evidence for it. +/// +/// permitWeakResolution also applies to resolutions of multi-type-variable constraints via method overloads. Method overloading gets applied even if +/// only one of the two type variables is known +/// +and SolveMemberConstraint (csenv:ConstraintSolverEnv) ignoreUnresolvedOverload permitWeakResolution ndeep m2 trace traitInfo : OperationResult = // Do not re-solve if already solved + let (TTrait(traitSupportTys, traitName, traitMemFlags, traitObjAndArgTys, traitRetTy, sln, extSlns, traitAD)) = traitInfo if sln.Value.IsSome then ResultD true else let g = csenv.g let m = csenv.m @@ -954,28 +977,29 @@ and SolveMemberConstraint (csenv:ConstraintSolverEnv) ignoreUnresolvedOverload p DepthCheck ndeep m ++ (fun () -> // Remove duplicates from the set of types in the support - let tys = ListSet.setify (typeAEquiv g aenv) tys + let traitSupportTys = ListSet.setify (typeAEquiv g aenv) traitSupportTys + // Rebuild the trait info after removing duplicates - let traitInfo = TTrait(tys, nm, memFlags, argtys, rty, sln) - let rty = GetFSharpViewOfReturnType g rty + let traitInfo = TTrait(traitSupportTys, traitName, traitMemFlags, traitObjAndArgTys, traitRetTy, sln, extSlns, traitAD) + let traitRetTy = GetFSharpViewOfReturnType g traitRetTy + let traitAD = match traitAD with None -> AccessibilityLogic.AccessibleFromEverywhere | Some ad -> (ad :?> AccessorDomain) // Assert the object type if the constraint is for an instance member - if memFlags.IsInstance then - match tys, argtys with + if traitMemFlags.IsInstance then + match traitSupportTys, traitObjAndArgTys with | [ty], (h :: _) -> SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace h ty | _ -> ErrorD (ConstraintSolverError(FSComp.SR.csExpectedArguments(), m, m2)) else CompleteD ++ (fun () -> // Trait calls are only supported on pseudo type (variables) - tys |> IterateD (SolveTypStaticReq csenv trace HeadTypeStaticReq)) ++ (fun () -> + traitSupportTys |> IterateD (SolveTypStaticReq csenv trace HeadTypeStaticReq)) ++ (fun () -> - let argtys = if memFlags.IsInstance then List.tail argtys else argtys - - let minfos = GetRelevantMethodsForTrait csenv permitWeakResolution nm traitInfo + let traitArgTys = if traitMemFlags.IsInstance then List.tail traitObjAndArgTys else traitObjAndArgTys + let minfos = GetRelevantMethodsForTrait csenv permitWeakResolution traitName traitInfo - match minfos, tys, memFlags.IsInstance, nm, argtys with - | _, _, false, ("op_Division" | "op_Multiply"), [argty1;argty2] + match traitMemFlags.IsInstance, traitName, traitArgTys with + | false, ("op_Division" | "op_Multiply"), [argty1;argty2] when // This simulates the existence of // float * float -> float @@ -999,10 +1023,10 @@ and SolveMemberConstraint (csenv:ConstraintSolverEnv) ignoreUnresolvedOverload p // The rule is triggered by these sorts of inputs when permitWeakResolution=true // float * 'a // 'a * float - // decimal<'u> * 'a <--- + // decimal<'u> * 'a (let checkRuleAppliesInPreferenceToMethods argty1 argty2 = // Check that at least one of the argument types is numeric - (IsNumericOrIntegralEnumType g argty1) && + (IsNumericOrIntegralEnumTy g argty1) && // Check that the support of type variables is empty. That is, // if we're canonicalizing, then having one of the types nominal is sufficient. // If not, then both must be nominal (i.e. not a type variable). @@ -1011,7 +1035,7 @@ and SolveMemberConstraint (csenv:ConstraintSolverEnv) ignoreUnresolvedOverload p // - Neither type contributes any methods OR // - We have the special case "decimal<_> * decimal". In this case we have some // possibly-relevant methods from "decimal" but we ignore them in this case. - (isNil minfos || (Option.isSome (GetMeasureOfType g argty1) && isDecimalTy g argty2)) in + (isNil minfos || IsNumericOrIntegralEnumTy g argty2 || (Option.isSome (GetMeasureOfType g argty1) && isDecimalTy g argty2)) checkRuleAppliesInPreferenceToMethods argty1 argty2 || checkRuleAppliesInPreferenceToMethods argty2 argty1) -> @@ -1020,186 +1044,209 @@ and SolveMemberConstraint (csenv:ConstraintSolverEnv) ignoreUnresolvedOverload p | Some (tcref, ms1) -> let ms2 = freshMeasure () SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace argty2 (mkAppTy tcref [TType_measure ms2]) ++ (fun () -> - SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty (mkAppTy tcref [TType_measure (Measure.Prod(ms1, if nm = "op_Multiply" then ms2 else Measure.Inv ms2))]) ++ (fun () -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy (mkAppTy tcref [TType_measure (Measure.Prod(ms1, if traitName = "op_Multiply" then ms2 else Measure.Inv ms2))]) ++ (fun () -> ResultD TTraitBuiltIn)) | _ -> match GetMeasureOfType g argty2 with | Some (tcref, ms2) -> let ms1 = freshMeasure () SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace argty1 (mkAppTy tcref [TType_measure ms1]) ++ (fun () -> - SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty (mkAppTy tcref [TType_measure (Measure.Prod(ms1, if nm = "op_Multiply" then ms2 else Measure.Inv ms2))]) ++ (fun () -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy (mkAppTy tcref [TType_measure (Measure.Prod(ms1, if traitName = "op_Multiply" then ms2 else Measure.Inv ms2))]) ++ (fun () -> ResultD TTraitBuiltIn)) | _ -> SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace argty2 argty1 ++ (fun () -> - SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty argty1 ++ (fun () -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy argty1 ++ (fun () -> ResultD TTraitBuiltIn)) - | _, _, false, ("op_Addition" | "op_Subtraction" | "op_Modulus"), [argty1;argty2] - when // Ignore any explicit +/- overloads from any basic integral types - (minfos |> List.forall (fun minfo -> isIntegerTy g minfo.EnclosingType ) && - ( (IsNumericOrIntegralEnumType g argty1 || (nm = "op_Addition" && (isCharTy g argty1 || isStringTy g argty1))) && (permitWeakResolution || not (isTyparTy g argty2)) - || (IsNumericOrIntegralEnumType g argty2 || (nm = "op_Addition" && (isCharTy g argty2 || isStringTy g argty2))) && (permitWeakResolution || not (isTyparTy g argty1)))) -> + | false, "op_Addition", [argty1;argty2] + when traitSupportTys |> List.exists (IsNumericOrIntegralEnumOrCharOrStringTy g) && + ( IsNumericOrIntegralEnumOrCharOrStringTy g argty1 && (permitWeakResolution || not (isTyparTy g argty2)) + || IsNumericOrIntegralEnumOrCharOrStringTy g argty2 && (permitWeakResolution || not (isTyparTy g argty1))) -> SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace argty2 argty1 ++ (fun () -> - SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty argty1 ++ (fun () -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy argty1 ++ (fun () -> ResultD TTraitBuiltIn)) - | _, _, false, ("op_LessThan" | "op_LessThanOrEqual" | "op_GreaterThan" | "op_GreaterThanOrEqual" | "op_Equality" | "op_Inequality" ), [argty1;argty2] - when // Ignore any explicit overloads from any basic integral types - (minfos |> List.forall (fun minfo -> isIntegerTy g minfo.EnclosingType ) && - ( (IsRelationalType g argty1 && (permitWeakResolution || not (isTyparTy g argty2))) - || (IsRelationalType g argty2 && (permitWeakResolution || not (isTyparTy g argty1))))) -> + | false, ("op_Subtraction" | "op_Modulus"), [argty1;argty2] + when traitSupportTys |> List.exists (IsNumericOrIntegralEnumTy g) && + ( IsNumericOrIntegralEnumTy g argty1 && (permitWeakResolution || not (isTyparTy g argty2)) + || IsNumericOrIntegralEnumTy g argty2 && (permitWeakResolution || not (isTyparTy g argty1))) -> SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace argty2 argty1 ++ (fun () -> - SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty g.bool_ty ++ (fun () -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy argty1 ++ (fun () -> + ResultD TTraitBuiltIn)) + + | false, ("op_LessThan" | "op_LessThanOrEqual" | "op_GreaterThan" | "op_GreaterThanOrEqual" | "op_Equality" | "op_Inequality" ), [argty1;argty2] + when traitSupportTys |> List.exists (IsRelationalTy g) && + ( (IsRelationalTy g argty1 && (permitWeakResolution || not (isTyparTy g argty2))) + || (IsRelationalTy g argty2 && (permitWeakResolution || not (isTyparTy g argty1)))) -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace argty2 argty1 ++ (fun () -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy g.bool_ty ++ (fun () -> ResultD TTraitBuiltIn)) // We pretend for uniformity that the numeric types have a static property called Zero and One // As with constants, only zero is polymorphic in its units - | [], [ty], false, "get_Zero", [] - when IsNumericType g ty -> - SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty ty ++ (fun () -> + | false, "get_Zero", [] + when traitSupportTys |> List.exists (IsNumericTy g) -> + + let ty = traitSupportTys |> List.find (IsNumericTy g) + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy ty ++ (fun () -> ResultD TTraitBuiltIn) - | [], [ty], false, "get_One", [] - when IsNumericType g ty || isCharTy g ty -> + | false, "get_One", [] + when traitSupportTys |> List.exists (IsNumericOrCharTy g) -> + + let ty = traitSupportTys |> List.find (IsNumericOrCharTy g) SolveDimensionlessNumericType csenv ndeep m2 trace ty ++ (fun () -> - SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty ty ++ (fun () -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy ty ++ (fun () -> ResultD TTraitBuiltIn)) - | [], _, false, ("DivideByInt"), [argty1;argty2] - when isFpTy g argty1 || isDecimalTy g argty1 -> + | false, "DivideByInt", [argty1;argty2] + when traitSupportTys |> List.exists (IsFpOrDecimalTy g) -> SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace argty2 g.int_ty ++ (fun () -> - SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty argty1 ++ (fun () -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy argty1 ++ (fun () -> ResultD TTraitBuiltIn)) - // We pretend for uniformity that the 'string' and 'array' types have an indexer property called 'Item' - | [], [ty], true, ("get_Item"), [argty1] - when isStringTy g ty -> + // Simulate the 'string' has an indexer property called 'Item' + | true, "get_Item", [argty1] + when traitSupportTys |> List.exists (isStringTy g) -> SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace argty1 g.int_ty ++ (fun () -> - SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty g.char_ty ++ (fun () -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy g.char_ty ++ (fun () -> ResultD TTraitBuiltIn)) - | [], [ty], true, ("get_Item"), argtys - when isArrayTy g ty -> + // Simulate that all array types have an indexer property called 'Item' + | true, "get_Item", argtys + when traitSupportTys |> List.exists (isArrayTy g) -> - (if rankOfArrayTy g ty <> argtys.Length then ErrorD(ConstraintSolverError(FSComp.SR.csIndexArgumentMismatch((rankOfArrayTy g ty), argtys.Length), m, m2)) else CompleteD) ++ (fun () -> + let arrayTy = traitSupportTys |> List.find (isArrayTy g) + let rank = rankOfArrayTy g arrayTy + (if rank <> argtys.Length then ErrorD(ConstraintSolverError(FSComp.SR.csIndexArgumentMismatch(rank, argtys.Length), m, m2)) else CompleteD) ++ (fun () -> (argtys |> IterateD (fun argty -> SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace argty g.int_ty)) ++ (fun () -> - let ety = destArrayTy g ty - SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty ety ++ (fun () -> + let ety = destArrayTy g arrayTy + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy ety ++ (fun () -> ResultD TTraitBuiltIn))) - | [], [ty], true, ("set_Item"), argtys - when isArrayTy g ty -> + // Simulate that all array types have an indexer setter property called 'Item' + | true, "set_Item", argtys + when traitSupportTys |> List.exists (isArrayTy g) -> - (if rankOfArrayTy g ty <> argtys.Length - 1 then ErrorD(ConstraintSolverError(FSComp.SR.csIndexArgumentMismatch((rankOfArrayTy g ty), (argtys.Length - 1)), m, m2)) else CompleteD) ++ (fun () -> + let arrayTy = traitSupportTys |> List.find (isArrayTy g) + let rank = rankOfArrayTy g arrayTy + (if rank <> argtys.Length - 1 then ErrorD(ConstraintSolverError(FSComp.SR.csIndexArgumentMismatch(rank, (argtys.Length - 1)), m, m2)) else CompleteD) ++ (fun () -> let argtys, ety = List.frontAndBack argtys (argtys |> IterateD (fun argty -> SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace argty g.int_ty)) ++ (fun () -> - let etys = destArrayTy g ty + let etys = destArrayTy g arrayTy SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace ety etys ++ (fun () -> ResultD TTraitBuiltIn))) - | [], _, false, ("op_BitwiseAnd" | "op_BitwiseOr" | "op_ExclusiveOr"), [argty1;argty2] - when (isIntegerOrIntegerEnumTy g argty1 || (isEnumTy g argty1)) && (permitWeakResolution || not (isTyparTy g argty2)) - || (isIntegerOrIntegerEnumTy g argty2 || (isEnumTy g argty2)) && (permitWeakResolution || not (isTyparTy g argty1)) -> + | false, ("op_BitwiseAnd" | "op_BitwiseOr" | "op_ExclusiveOr"), [argty1;argty2] + when traitSupportTys |> List.exists (IsIntegerOrEnumTy g) && + ( IsIntegerOrEnumTy g argty1 && (permitWeakResolution || not (isTyparTy g argty2)) + || IsIntegerOrEnumTy g argty2 && (permitWeakResolution || not (isTyparTy g argty1))) -> SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace argty2 argty1 ++ (fun () -> - SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty argty1 ++ (fun () -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy argty1 ++ (fun () -> SolveDimensionlessNumericType csenv ndeep m2 trace argty1 ++ (fun () -> - ResultD TTraitBuiltIn))); + ResultD TTraitBuiltIn))) - | [], _, false, ("op_LeftShift" | "op_RightShift"), [argty1;argty2] - when isIntegerOrIntegerEnumTy g argty1 -> + | false, ("op_LeftShift" | "op_RightShift"), [argty1;argty2] + when traitSupportTys |> List.exists (isIntegerOrIntegerEnumTy g) && + isIntegerOrIntegerEnumTy g argty1 -> SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace argty2 g.int_ty ++ (fun () -> - SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty argty1 ++ (fun () -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy argty1 ++ (fun () -> SolveDimensionlessNumericType csenv ndeep m2 trace argty1 ++ (fun () -> ResultD TTraitBuiltIn))) - | _, _, false, ("op_UnaryPlus"), [argty] - when IsNumericOrIntegralEnumType g argty -> + | false, "op_UnaryPlus", [argty] + when traitSupportTys |> List.exists (IsNumericOrIntegralEnumTy g) && + IsNumericOrIntegralEnumTy g argty -> - SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty argty ++ (fun () -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy argty ++ (fun () -> ResultD TTraitBuiltIn) - | _, _, false, ("op_UnaryNegation"), [argty] - when isSignedIntegerTy g argty || isFpTy g argty || isDecimalTy g argty -> + | false, "op_UnaryNegation", [argty] + when traitSupportTys |> List.exists (IsSignedIntegerOrFpOrDecimalTy g) && + IsSignedIntegerOrFpOrDecimalTy g argty -> - SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty argty ++ (fun () -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy argty ++ (fun () -> ResultD TTraitBuiltIn) - | _, _, true, ("get_Sign"), [] - when (let argty = tys.Head in isSignedIntegerTy g argty || isFpTy g argty || isDecimalTy g argty) -> + | true, "get_Sign", [] + when traitSupportTys |> List.exists (IsSignedIntegerOrFpOrDecimalTy g) -> - SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty g.int32_ty ++ (fun () -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy g.int32_ty ++ (fun () -> ResultD TTraitBuiltIn) - | _, _, false, ("op_LogicalNot" | "op_OnesComplement"), [argty] - when isIntegerOrIntegerEnumTy g argty -> + | false, ("op_LogicalNot" | "op_OnesComplement"), [argty] + when traitSupportTys |> List.exists (isIntegerOrIntegerEnumTy g) -> - SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty argty ++ (fun () -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy argty ++ (fun () -> SolveDimensionlessNumericType csenv ndeep m2 trace argty ++ (fun () -> ResultD TTraitBuiltIn)) - | _, _, false, ("Abs"), [argty] - when isSignedIntegerTy g argty || isFpTy g argty || isDecimalTy g argty -> + | false, "Abs", [argty] + when traitSupportTys |> List.exists (IsSignedIntegerOrFpOrDecimalTy g) -> - SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty argty ++ (fun () -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy argty ++ (fun () -> ResultD TTraitBuiltIn) - | _, _, false, "Sqrt", [argty1] - when isFpTy g argty1 -> - match GetMeasureOfType g argty1 with + | false, "Sqrt", [argty] + when traitSupportTys |> List.exists (isFpTy g) -> + + match GetMeasureOfType g argty with | Some (tcref, _) -> let ms1 = freshMeasure () - SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace argty1 (mkAppTy tcref [TType_measure (Measure.Prod (ms1, ms1))]) ++ (fun () -> - SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty (mkAppTy tcref [TType_measure ms1]) ++ (fun () -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace argty (mkAppTy tcref [TType_measure (Measure.Prod (ms1, ms1))]) ++ (fun () -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy (mkAppTy tcref [TType_measure ms1]) ++ (fun () -> ResultD TTraitBuiltIn)) | None -> - SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty argty1 ++ (fun () -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy argty ++ (fun () -> ResultD TTraitBuiltIn) - | _, _, false, ("Sin" | "Cos" | "Tan" | "Sinh" | "Cosh" | "Tanh" | "Atan" | "Acos" | "Asin" | "Exp" | "Ceiling" | "Floor" | "Round" | "Truncate" | "Log10" | "Log" | "Sqrt"), [argty] - when isFpTy g argty -> + | false, ("Sin" | "Cos" | "Tan" | "Sinh" | "Cosh" | "Tanh" | "Atan" | "Acos" | "Asin" | "Exp" | "Ceiling" | "Floor" | "Round" | "Truncate" | "Log10" | "Log" | "Sqrt"), [argty] + when traitSupportTys |> List.exists (isFpTy g) -> SolveDimensionlessNumericType csenv ndeep m2 trace argty ++ (fun () -> - SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty argty ++ (fun () -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy argty ++ (fun () -> ResultD TTraitBuiltIn)) - | _, _, false, ("op_Explicit"), [argty] + // Simulate solutions to op_Implicit and op_Explicit + | false, "op_Explicit", [argty] when (// The input type. - (IsNonDecimalNumericOrIntegralEnumType g argty || isStringTy g argty || isCharTy g argty) && + (IsNonDecimalNumericOrIntegralEnumTy g argty || isStringTy g argty || isCharTy g argty) && // The output type - (IsNonDecimalNumericOrIntegralEnumType g rty || isCharTy g rty) && + (IsNonDecimalNumericOrIntegralEnumTy g traitRetTy || isCharTy g traitRetTy) && // Exclusion: IntPtr and UIntPtr do not support .Parse() from string - not (isStringTy g argty && isNativeIntegerTy g rty) && + not (isStringTy g argty && isNativeIntegerTy g traitRetTy) && // Exclusion: No conversion from char to decimal - not (isCharTy g argty && isDecimalTy g rty)) -> + not (isCharTy g argty && isDecimalTy g traitRetTy)) -> ResultD TTraitBuiltIn - | _, _, false, ("op_Explicit"), [argty] + | false, "op_Explicit", [argty] when (// The input type. - (IsNumericOrIntegralEnumType g argty || isStringTy g argty) && + (IsNumericOrIntegralEnumTy g argty || isStringTy g argty) && // The output type - (isDecimalTy g rty)) -> + (isDecimalTy g traitRetTy)) -> ResultD TTraitBuiltIn - | [], _, false, "Pow", [argty1; argty2] - when isFpTy g argty1 -> + | false, "Pow", [argty1; argty2] + when traitSupportTys |> List.exists (isFpTy g) -> SolveDimensionlessNumericType csenv ndeep m2 trace argty1 ++ (fun () -> SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace argty2 argty1 ++ (fun () -> - SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty argty1 ++ (fun () -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy argty1 ++ (fun () -> ResultD TTraitBuiltIn))) - | _, _, false, ("Atan2"), [argty1; argty2] - when isFpTy g argty1 -> + | false, "Atan2", [argty1; argty2] + when traitSupportTys |> List.exists (isFpTy g) -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace argty2 argty1 ++ (fun () -> match GetMeasureOfType g argty1 with - | None -> SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty argty1 - | Some (tcref, _) -> SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty (mkAppTy tcref [TType_measure Measure.One])) ++ (fun () -> + | None -> SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy argty1 + | Some (tcref, _) -> SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy (mkAppTy tcref [TType_measure Measure.One])) ++ (fun () -> ResultD TTraitBuiltIn) | _ -> @@ -1208,17 +1255,17 @@ and SolveMemberConstraint (csenv:ConstraintSolverEnv) ignoreUnresolvedOverload p // First look for a solution by a record property let recdPropSearch = - let isGetProp = nm.StartsWith "get_" - let isSetProp = nm.StartsWith "set_" - if argtys.IsEmpty && isGetProp || isSetProp then - let propName = nm.[4..] + let isGetProp = traitName.StartsWith "get_" + let isSetProp = traitName.StartsWith "set_" + if (traitArgTys.IsEmpty && isGetProp) || isSetProp then + let propName = traitName.[4..] let props = - tys |> List.choose (fun ty -> - match TryFindIntrinsicNamedItemOfType csenv.InfoReader (propName, AccessibleFromEverywhere) FindMemberFlag.IgnoreOverrides m ty with + traitSupportTys |> List.choose (fun ty -> + match TryFindIntrinsicNamedItemOfType csenv.InfoReader (propName, traitAD) FindMemberFlag.IgnoreOverrides m ty with | Some (RecdFieldItem rfinfo) when (isGetProp || rfinfo.RecdField.IsMutable) && - (rfinfo.IsStatic = not memFlags.IsInstance) && - IsRecdFieldAccessible amap m AccessibleFromEverywhere rfinfo.RecdFieldRef && + (rfinfo.IsStatic = not traitMemFlags.IsInstance) && + IsRecdFieldAccessible amap m traitAD rfinfo.RecdFieldRef && not rfinfo.LiteralValue.IsSome && not rfinfo.RecdField.IsCompilerGenerated -> Some (rfinfo, isSetProp) @@ -1231,29 +1278,33 @@ and SolveMemberConstraint (csenv:ConstraintSolverEnv) ignoreUnresolvedOverload p // Now check if there are no feasible solutions at all match minfos, recdPropSearch with - | [], None when not (tys |> List.exists (isAnyParTy g)) -> - if tys |> List.exists (isFunTy g) then - ErrorD (ConstraintSolverError(FSComp.SR.csExpectTypeWithOperatorButGivenFunction(DecompileOpName nm), m, m2)) - elif tys |> List.exists (isAnyTupleTy g) then - ErrorD (ConstraintSolverError(FSComp.SR.csExpectTypeWithOperatorButGivenTuple(DecompileOpName nm), m, m2)) + | [], None when MemberConstraintIsReadyForStrongResolution csenv traitInfo -> + + if traitSupportTys |> List.exists (isFunTy g) then + ErrorD (ConstraintSolverError(FSComp.SR.csExpectTypeWithOperatorButGivenFunction(DecompileOpName traitName), m, m2)) + + elif traitSupportTys |> List.exists (isAnyTupleTy g) then + ErrorD (ConstraintSolverError(FSComp.SR.csExpectTypeWithOperatorButGivenTuple(DecompileOpName traitName), m, m2)) + else - match nm, argtys with - | "op_Explicit", [argty] -> ErrorD (ConstraintSolverError(FSComp.SR.csTypeDoesNotSupportConversion((NicePrint.prettyStringOfTy denv argty), (NicePrint.prettyStringOfTy denv rty)), m, m2)) + + match traitName, traitArgTys with + | "op_Explicit", [argty] -> ErrorD (ConstraintSolverError(FSComp.SR.csTypeDoesNotSupportConversion((NicePrint.prettyStringOfTy denv argty), (NicePrint.prettyStringOfTy denv traitRetTy)), m, m2)) | _ -> let tyString = - match tys with + match traitSupportTys with | [ty] -> NicePrint.minimalStringOfType denv ty - | _ -> tys |> List.map (NicePrint.minimalStringOfType denv) |> String.concat ", " - let opName = DecompileOpName nm + | _ -> traitSupportTys |> List.map (NicePrint.minimalStringOfType denv) |> String.concat ", " + let opName = DecompileOpName traitName let err = match opName with | "?>=" | "?>" | "?<=" | "?<" | "?=" | "?<>" | ">=?" | ">?" | "<=?" | "?" | "?>=?" | "?>?" | "?<=?" | "??" -> - if tys.Length = 1 then FSComp.SR.csTypeDoesNotSupportOperatorNullable(tyString, opName) + if traitSupportTys.Length = 1 then FSComp.SR.csTypeDoesNotSupportOperatorNullable(tyString, opName) else FSComp.SR.csTypesDoNotSupportOperatorNullable(tyString, opName) | _ -> - if tys.Length = 1 then FSComp.SR.csTypeDoesNotSupportOperator(tyString, opName) + if traitSupportTys.Length = 1 then FSComp.SR.csTypeDoesNotSupportOperator(tyString, opName) else FSComp.SR.csTypesDoNotSupportOperator(tyString, opName) ErrorD(ConstraintSolverError(err, m, m2)) @@ -1265,31 +1316,33 @@ and SolveMemberConstraint (csenv:ConstraintSolverEnv) ignoreUnresolvedOverload p // curried members may not be used to satisfy constraints |> List.choose (fun minfo -> if minfo.IsCurried then None else - let callerArgs = argtys |> List.map (fun argty -> CallerArg(argty, m, false, dummyExpr)) - let minst = FreshenMethInfo m minfo - let objtys = minfo.GetObjArgTypes(amap, m, minst) - Some(CalledMeth(csenv.InfoReader, None, false, FreshenMethInfo, m, AccessibleFromEverywhere, minfo, minst, minst, None, objtys, [(callerArgs, [])], false, false, None))) + let callerArgs = traitArgTys |> List.map (fun argty -> CallerArg(argty, m, false, dummyExpr)) + let minst = FreshenMethInfo None m minfo + //let objtys = minfo.GetObjArgTypes(amap, m, minst) + let callerObjTys = if traitMemFlags.IsInstance then [ List.head traitObjAndArgTys ] else [] + Some(CalledMeth(csenv.InfoReader, None, false, FreshenMethInfo None, m, traitAD, minfo, minst, minst, None, callerObjTys, [(callerArgs, [])], false, false, None))) let methOverloadResult, errors = - trace.CollectThenUndoOrCommit (fun (a, _) -> Option.isSome a) (fun trace -> ResolveOverloading csenv (WithTrace trace) nm ndeep (Some traitInfo) (0, 0) AccessibleFromEverywhere calledMethGroup false (Some rty)) + trace.CollectThenUndoOrCommit (fun (a, _) -> Option.isSome a) (fun trace -> + ResolveOverloading csenv (WithTrace trace) traitName ndeep (Some traitInfo) (0, 0) traitAD calledMethGroup false (Some traitRetTy)) match recdPropSearch, methOverloadResult with | Some (rfinfo, isSetProp), None -> // OK, the constraint is solved by a record property. Assert that the return types match. let rty2 = if isSetProp then g.unit_ty else rfinfo.FieldType - SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty rty2 ++ (fun () -> + SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace traitRetTy rty2 ++ (fun () -> ResultD (TTraitSolvedRecdProp(rfinfo, isSetProp))) + | None, Some (calledMeth:CalledMeth<_>) -> - // OK, the constraint is solved. + // OK, the constraint is solved by a method let minfo = calledMeth.Method - errors ++ (fun () -> let isInstance = minfo.IsInstance - if isInstance <> memFlags.IsInstance then + if isInstance <> traitMemFlags.IsInstance then if isInstance then - ErrorD(ConstraintSolverError(FSComp.SR.csMethodFoundButIsNotStatic((NicePrint.minimalStringOfType denv minfo.EnclosingType), (DecompileOpName nm), nm), m, m2 )) + ErrorD(ConstraintSolverError(FSComp.SR.csMethodFoundButIsNotStatic((NicePrint.minimalStringOfType denv minfo.EnclosingType), (DecompileOpName traitName), traitName), m, m2 )) else - ErrorD(ConstraintSolverError(FSComp.SR.csMethodFoundButIsStatic((NicePrint.minimalStringOfType denv minfo.EnclosingType), (DecompileOpName nm), nm), m, m2 )) + ErrorD(ConstraintSolverError(FSComp.SR.csMethodFoundButIsStatic((NicePrint.minimalStringOfType denv minfo.EnclosingType), (DecompileOpName traitName), traitName), m, m2 )) else CheckMethInfoAttributes g m None minfo ++ (fun () -> ResultD (TTraitSolved (minfo, calledMeth.CalledTyArgs)))) @@ -1298,12 +1351,14 @@ and SolveMemberConstraint (csenv:ConstraintSolverEnv) ignoreUnresolvedOverload p let support = GetSupportOfMemberConstraint csenv traitInfo let frees = GetFreeTyparsOfMemberConstraint csenv traitInfo - // If there's nothing left to learn then raise the errors - (if (permitWeakResolution && isNil support) || isNil frees then errors + // If there's nothing left to learn then raise the errors. + // Note: we should likely call MemberConstraintIsReadyForResolution here when permitWeakResolution=false but for stability + // reasons we use the more restrictive isNil frees. + (if (permitWeakResolution && MemberConstraintIsReadyForWeakResolution csenv traitInfo) || isNil frees then errors // Otherwise re-record the trait waiting for canonicalization else AddMemberConstraint csenv ndeep m2 trace traitInfo support frees) ++ (fun () -> match errors with - | ErrorResult (_, UnresolvedOverloading _) when not ignoreUnresolvedOverload && (not (nm = "op_Explicit" || nm = "op_Implicit")) -> ErrorD LocallyAbortOperationThatFailsToResolveOverload + | ErrorResult (_, UnresolvedOverloading _) when not ignoreUnresolvedOverload && (not (traitName = "op_Explicit" || traitName = "op_Implicit")) -> ErrorD LocallyAbortOperationThatFailsToResolveOverload | _ -> ResultD TTraitUnsolved) ) ++ @@ -1323,12 +1378,12 @@ and RecordMemberConstraintSolution css m trace traitInfo res = ResultD true | TTraitBuiltIn -> - TransactMemberConstraintSolution traitInfo trace BuiltInSln; + TransactMemberConstraintSolution traitInfo trace BuiltInSln ResultD true | TTraitSolvedRecdProp (rfinfo, isSetProp) -> let sln = MemberConstraintSolutionOfRecdFieldInfo rfinfo isSetProp - TransactMemberConstraintSolution traitInfo trace sln; + TransactMemberConstraintSolution traitInfo trace sln ResultD true /// Convert a MethInfo into the data we save in the TAST @@ -1343,10 +1398,13 @@ and MemberConstraintSolutionOfMethInfo css m minfo minst = let mref = IL.mkRefToILMethod (ilMeth.DeclaringTyconRef.CompiledRepresentationForNamedType, ilMeth.RawMetadata) let iltref = ilMeth.DeclaringTyconRefOption |> Option.map (fun tcref -> tcref.CompiledRepresentationForNamedType) ILMethSln(ilMeth.ApparentEnclosingType, iltref, mref, minst) + | FSMeth(_, typ, vref, _) -> - FSMethSln(typ, vref, minst) + FSMethSln(typ, vref, minst) + | MethInfo.DefaultStructCtor _ -> error(InternalError("the default struct constructor was the unexpected solution to a trait constraint", m)) + #if !NO_EXTENSIONTYPING | ProvidedMeth(amap, mi, _, m) -> let g = amap.g @@ -1380,43 +1438,81 @@ and TransactMemberConstraintSolution traitInfo (trace:OptionalTrace) sln = let prev = traitInfo.Solution trace.Exec (fun () -> traitInfo.Solution <- Some sln) (fun () -> traitInfo.Solution <- prev) +and GetRelevantExtensionMethodsForTrait m (amap: Import.ImportMap) (traitInfo: TraitConstraintInfo) = + + // TODO: check the use of 'allPairs' - not all these extensions apply to each type variable. + (traitInfo.SupportTypes, traitInfo.PossibleExtensionSolutions) + ||> List.allPairs + |> List.choose (fun (traitSupportTy,extMem) -> + match (extMem :?> ExtensionMember) with + | FSExtMem (vref, pri) -> Some (FSMeth(amap.g, traitSupportTy, vref, Some pri) ) + | ILExtMem (actualParent, minfo, pri) -> TrySelectExtensionMethInfoOfILExtMem m amap traitSupportTy (actualParent, minfo, pri)) + /// Only consider overload resolution if canonicalizing or all the types are now nominal. /// That is, don't perform resolution if more nominal information may influence the set of available overloads -and GetRelevantMethodsForTrait (csenv:ConstraintSolverEnv) permitWeakResolution nm (TTrait(tys, _, memFlags, argtys, rty, soln) as traitInfo): MethInfo list = +and GetRelevantMethodsForTrait (csenv:ConstraintSolverEnv) permitWeakResolution traitName (TTrait(traitSupportTys, _, memFlags, argtys, traitRetTy, soln, extSlns, ad) as traitInfo) : MethInfo list = let results = - if permitWeakResolution || isNil (GetSupportOfMemberConstraint csenv traitInfo) then + if MemberConstraintSupportIsReadyForDeterminingOverloads permitWeakResolution csenv traitInfo then let m = csenv.m let minfos = match memFlags.MemberKind with | MemberKind.Constructor -> - tys |> List.map (GetIntrinsicConstructorInfosOfType csenv.SolverState.InfoReader m) + traitSupportTys |> List.map (GetIntrinsicConstructorInfosOfType csenv.SolverState.InfoReader m) | _ -> - tys |> List.map (GetIntrinsicMethInfosOfType csenv.SolverState.InfoReader (Some nm, AccessibleFromSomeFSharpCode, AllowMultiIntfInstantiations.Yes) IgnoreOverrides m) - /// Merge the sets so we don't get the same minfo from each side - /// We merge based on whether minfos use identical metadata or not. + traitSupportTys |> List.map (GetIntrinsicMethInfosOfType csenv.SolverState.InfoReader (Some traitName, AccessibleFromSomeFSharpCode, AllowMultiIntfInstantiations.Yes) IgnoreOverrides m) - /// REVIEW: Consider the pathological cases where this may cause a loss of distinction - /// between potential overloads because a generic instantiation derived from the left hand type differs - /// to a generic instantiation for an operator based on the right hand type. - + // Merge the sets so we don't get the same minfo from each side + // We merge based on whether minfos use identical metadata or not. let minfos = List.reduce (ListSet.unionFavourLeft MethInfo.MethInfosUseIdenticalDefinitions) minfos - minfos + if minfos.Length <= 1 || MemberConstraintSignatureIsReadyForResolution csenv traitInfo then + minfos + else + [] // nothing available yet, there are overloads and the signature has not been fully determined + else [] + // The trait name "op_Explicit" also covers "op_Implicit", so look for that one too. - if nm = "op_Explicit" then - results @ GetRelevantMethodsForTrait (csenv:ConstraintSolverEnv) permitWeakResolution "op_Implicit" (TTrait(tys, "op_Implicit", memFlags, argtys, rty, soln)) + if traitName = "op_Explicit" then + results @ GetRelevantMethodsForTrait csenv permitWeakResolution "op_Implicit" (TTrait(traitSupportTys, "op_Implicit", memFlags, argtys, traitRetTy, soln, extSlns, ad)) else results /// The nominal support of the member constraint -and GetSupportOfMemberConstraint (csenv:ConstraintSolverEnv) (TTrait(tys, _, _, _, _, _)) = - tys |> List.choose (tryAnyParTy csenv.g) +and GetSupportOfMemberConstraint (csenv:ConstraintSolverEnv) (traitInfo : TraitConstraintInfo) = + traitInfo.SupportTypes |> List.choose (tryAnyParTy csenv.g) + +/// Check if the support is fully solved. +and SupportOfMemberConstraintIsFullySolved (csenv:ConstraintSolverEnv) (TTrait(traitSupportTys, _, _, _, _, _, _, _)) = + traitSupportTys |> List.forall (isAnyParTy csenv.g >> not) + +/// Check if some part of the support is solved. +and SupportOfMemberConstraintIsPartiallySolved (csenv:ConstraintSolverEnv) (TTrait(traitSupportTys, _, _, _, _, _, _, _)) = + traitSupportTys |> List.exists (isAnyParTy csenv.g >> not) -/// All the typars relevant to the member constraint *) -and GetFreeTyparsOfMemberConstraint (csenv:ConstraintSolverEnv) (TTrait(tys, _, _, argtys, rty, _)) = - freeInTypesLeftToRightSkippingConstraints csenv.g (tys@argtys@ Option.toList rty) +/// Get all the unsolved typars (statically resolved or not) relevant to the member constraint +and GetFreeTyparsOfMemberConstraint (csenv:ConstraintSolverEnv) (TTrait(traitSupportTys, _, _, traitArgTys, traitRetTy, _, _, _)) = + freeInTypesLeftToRightSkippingConstraints csenv.g (traitSupportTys @ traitArgTys @ Option.toList traitRetTy) + +/// Check there are no unsolved statically-resolved type parameters in the argument types of the trait method signature. +/// This is necessary to prevent overload resolution being applied to statically resolved members +// constraints before all argument types are known. The return type is not taken into account. +and MemberConstraintSignatureIsReadyForResolution csenv (TTrait(traitSupportTys, _, _, traitArgTys, _, _, _, _)) = + let typarsRelevantToOverloadResultion = freeInTypesLeftToRightSkippingConstraints csenv.g (traitSupportTys @ traitArgTys) + typarsRelevantToOverloadResultion |> List.forall (fun tp -> match tp.StaticReq with HeadTypeStaticReq -> false | _ -> true) + +and MemberConstraintIsReadyForWeakResolution csenv traitInfo = + SupportOfMemberConstraintIsPartiallySolved csenv traitInfo && + MemberConstraintSignatureIsReadyForResolution csenv traitInfo + +and MemberConstraintIsReadyForStrongResolution csenv traitInfo = + SupportOfMemberConstraintIsFullySolved csenv traitInfo && + MemberConstraintSignatureIsReadyForResolution csenv traitInfo + +and MemberConstraintSupportIsReadyForDeterminingOverloads permitWeakResolution csenv traitInfo = + (permitWeakResolution && SupportOfMemberConstraintIsPartiallySolved csenv traitInfo) + || SupportOfMemberConstraintIsFullySolved csenv traitInfo /// Re-solve the global constraints involving any of the given type variables. /// Trait constraints can't always be solved using the pessimistic rules. We only canonicalize @@ -1434,6 +1530,12 @@ and SolveRelevantMemberConstraints (csenv:ConstraintSolverEnv) ndeep permitWeakR | None -> ResultD false)) +and GetTraitFreshner (ad: AccessorDomain) (nenv: NameResolutionEnv) (traitInfo: TraitConstraintInfo) = + let slns = + NameMultiMap.find traitInfo.MemberName nenv.eExtensionMembersByName + |> List.map (fun extMem -> (extMem :> TraitPossibleExtensionMemberSolution)) + slns, (ad :> TraitAccessorDomain) + and SolveRelevantMemberConstraintsForTypar (csenv:ConstraintSolverEnv) ndeep permitWeakResolution (trace:OptionalTrace) tp = let cxst = csenv.SolverState.ExtraCxs let tpn = tp.Stamp @@ -1449,7 +1551,7 @@ and SolveRelevantMemberConstraintsForTypar (csenv:ConstraintSolverEnv) ndeep per SolveMemberConstraint csenv true permitWeakResolution (ndeep+1) m2 trace traitInfo) and CanonicalizeRelevantMemberConstraints (csenv:ConstraintSolverEnv) ndeep trace tps = - SolveRelevantMemberConstraints csenv ndeep true trace tps + SolveRelevantMemberConstraints csenv ndeep (*permitWeakResolution*)true trace tps and AddMemberConstraint (csenv:ConstraintSolverEnv) ndeep m2 trace traitInfo support frees = let g = csenv.g @@ -1466,7 +1568,8 @@ and AddMemberConstraint (csenv:ConstraintSolverEnv) ndeep m2 trace traitInfo sup let cxs = cxst.FindAll tpn // check the constraint is not already listed for this type variable - if not (cxs |> List.exists (fun (traitInfo2, _) -> traitsAEquiv g aenv traitInfo traitInfo2)) then + // + if not (cxs |> List.exists (fun (traitInfo2, _valRefs) -> traitsAEquiv g aenv traitInfo traitInfo2)) then trace.Exec (fun () -> csenv.SolverState.ExtraCxs.Add (tpn, (traitInfo, m2))) (fun () -> csenv.SolverState.ExtraCxs.Remove tpn) ) @@ -1490,8 +1593,8 @@ and AddConstraint (csenv:ConstraintSolverEnv) ndeep m2 trace tp newConstraint = // may require type annotations. See FSharp 1.0 bug 6477. let consistent tpc1 tpc2 = match tpc1, tpc2 with - | (TyparConstraint.MayResolveMember(TTrait(tys1, nm1, memFlags1, argtys1, rty1, _), _), - TyparConstraint.MayResolveMember(TTrait(tys2, nm2, memFlags2, argtys2, rty2, _), _)) + | (TyparConstraint.MayResolveMember(TTrait(tys1, nm1, memFlags1, argtys1, rty1, _, _, _), _), + TyparConstraint.MayResolveMember(TTrait(tys2, nm2, memFlags2, argtys2, rty2, _, _, _), _)) when (memFlags1 = memFlags2 && nm1 = nm2 && // Multiple op_Explicit and op_Implicit constraints can exist for the same type variable. @@ -1556,8 +1659,8 @@ and AddConstraint (csenv:ConstraintSolverEnv) ndeep m2 trace tp newConstraint = // If it does occur, e.g. at instantiation T2, then the check above will have enforced that // T2 = ty2 let implies tpc1 tpc2 = - match tpc1, tpc2 with - | TyparConstraint.MayResolveMember(trait1, _), + match tpc1,tpc2 with + | TyparConstraint.MayResolveMember(trait1, _), TyparConstraint.MayResolveMember(trait2, _) -> traitsAEquiv g aenv trait1 trait2 @@ -2409,9 +2512,10 @@ and ResolveOverloading // Unify return types. match calledMethOpt with | Some calledMeth -> - calledMethOpt, - errors ++ (fun () -> - let cxsln = Option.map (fun traitInfo -> (traitInfo, MemberConstraintSolutionOfMethInfo csenv.SolverState m calledMeth.Method calledMeth.CalledTyArgs)) cx + calledMethOpt, + errors ++ (fun () -> + let ofTraitInfo traitInfo = (traitInfo, MemberConstraintSolutionOfMethInfo csenv.SolverState m calledMeth.Method calledMeth.CalledTyArgs) + let cxsln = Option.map ofTraitInfo cx match calledMethTrace with | NoTrace -> @@ -2541,8 +2645,8 @@ let AddCxTypeMustSubsumeType contextInfo denv css m trace ty1 ty2 = SolveTypSubsumesTypWithReport (MakeConstraintSolverEnv contextInfo css m denv) 0 m trace None ty1 ty2 |> RaiseOperationResult -let AddCxMethodConstraint denv css m trace traitInfo = - TryD (fun () -> SolveMemberConstraint (MakeConstraintSolverEnv ContextInfo.NoContext css m denv) true false 0 m trace traitInfo ++ (fun _ -> CompleteD)) +let AddCxMethodConstraint denv css m trace (traitInfo : TraitConstraintInfo) = + TryD (fun () -> SolveMemberConstraint (MakeConstraintSolverEnv ContextInfo.NoContext css m denv) true (*permitWeakResolution*)false 0 m trace traitInfo ++ (fun _ -> CompleteD)) (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) |> RaiseOperationResult @@ -2597,35 +2701,52 @@ let CodegenWitnessThatTypSupportsTraitConstraint tcVal g amap m (traitInfo:Trait amap = amap TcVal = tcVal ExtraCxs = HashMultiMap(10, HashIdentity.Structural) - InfoReader = new InfoReader(g, amap) } + InfoReader = new InfoReader(g,amap) } let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m (DisplayEnv.Empty g) - SolveMemberConstraint csenv true true 0 m NoTrace traitInfo ++ (fun _res -> + + SolveMemberConstraint csenv true (*permitWeakResolution*)true 0 m NoTrace traitInfo ++ (fun _res -> + let sln = match traitInfo.Solution with | None -> Choice4Of4() | Some sln -> + + // Given the solution information, reconstruct the MethInfo for the solution match sln with - | ILMethSln(typ, extOpt, mref, minst) -> - let tcref, _tinst = destAppTy g typ - let mdef = IL.resolveILMethodRef tcref.ILTyconRawMetadata mref + | ILMethSln (apparentTy, extOpt, mref, minst) -> + + // Find the actual type containing the solution + let actualTyconRef = + match extOpt with + | None -> tcrefOfAppTy g apparentTy + | Some ilActualTypeRef -> Import.ImportILTypeRef amap m ilActualTypeRef + + // Find the ILMethodDef corresponding to the solution + let mdef = IL.resolveILMethodRef actualTyconRef.ILTyconRawMetadata mref + + // Make the MethInfo for the solution let ilMethInfo = match extOpt with - | None -> MethInfo.CreateILMeth(amap, m, typ, mdef) - | Some ilActualTypeRef -> - let actualTyconRef = Import.ImportILTypeRef amap m ilActualTypeRef - MethInfo.CreateILExtensionMeth(amap, m, typ, actualTyconRef, None, mdef) + | None -> MethInfo.CreateILMeth(amap, m, apparentTy, mdef) + | Some _ -> MethInfo.CreateILExtensionMeth(amap, m, apparentTy, actualTyconRef, None, mdef) + Choice1Of4 (ilMethInfo, minst) - | FSMethSln(typ, vref, minst) -> - Choice1Of4 (FSMeth(g, typ, vref, None), minst) - | FSRecdFieldSln(tinst, rfref, isSetProp) -> - Choice2Of4 (tinst, rfref, isSetProp) + + | FSMethSln (apparentTy, vref, minst) -> + Choice1Of4 (FSMeth(g, apparentTy, vref, None), minst) + + | FSRecdFieldSln (tinst, rfref, isSetProp) -> + Choice2Of4 (tinst, rfref, isSetProp) + | BuiltInSln -> Choice4Of4 () + | ClosedExprSln expr -> Choice3Of4 expr + match sln with - | Choice1Of4(minfo, methArgTys) -> + | Choice1Of4(minfo, minst) -> let argExprs = // FIX for #421894 - typechecker assumes that coercion can be applied for the trait calls arguments but codegen doesn't emit coercion operations // result - generation of non-verifyable code @@ -2633,8 +2754,9 @@ let CodegenWitnessThatTypSupportsTraitConstraint tcVal g amap m (traitInfo:Trait // flatten list of argument types (looks like trait calls with curried arguments are not supported so we can just convert argument list in straighforward way) let argTypes = - minfo.GetParamTypes(amap, m, methArgTys) + minfo.GetParamTypes(amap, m, minst) |> List.concat + // do not apply coercion to the 'receiver' argument let receiverArgOpt, argExprs = if minfo.IsInstance then @@ -2642,6 +2764,7 @@ let CodegenWitnessThatTypSupportsTraitConstraint tcVal g amap m (traitInfo:Trait | h::t -> Some h, t | argExprs -> None, argExprs else None, argExprs + let convertedArgs = (argExprs, argTypes) ||> List.map2 (fun expr expectedTy -> mkCoerceIfNeeded g expectedTy (tyOfExpr g expr) expr) match receiverArgOpt with | Some r -> r::convertedArgs @@ -2654,7 +2777,7 @@ let CodegenWitnessThatTypSupportsTraitConstraint tcVal g amap m (traitInfo:Trait let wrap, h' = mkExprAddrOfExpr g true false PossiblyMutates h None m ResultD (Some (wrap (Expr.Op(TOp.TraitCall(traitInfo), [], (h' :: t), m)))) else - ResultD (Some (MakeMethInfoCall amap m minfo methArgTys argExprs )) + ResultD (Some (MakeMethInfoCall amap m minfo minst argExprs )) | Choice2Of4 (tinst, rfref, isSet) -> let res = @@ -2686,7 +2809,7 @@ let CodegenWitnessThatTypSupportsTraitConstraint tcVal g amap m (traitInfo:Trait let ChooseTyparSolutionAndSolve css denv tp = let g = css.g let amap = css.amap - let max, m = ChooseTyparSolutionAndRange g amap tp + let max,m = ChooseTyparSolutionAndRange g amap tp let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv TryD (fun () -> SolveTyparEqualsTyp csenv 0 m NoTrace (mkTyparTy tp) max) (fun err -> ErrorD(ErrorFromApplyingDefault(g, denv, tp, max, err, m))) @@ -2716,7 +2839,7 @@ let IsApplicableMethApprox g amap m (minfo:MethInfo) availObjTy = ExtraCxs = HashMultiMap(10, HashIdentity.Structural) InfoReader = new InfoReader(g, amap) } let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m (DisplayEnv.Empty g) - let minst = FreshenMethInfo m minfo + let minst = FreshenMethInfo None m minfo match minfo.GetObjArgTypes(amap, m, minst) with | [reqdObjTy] -> TryD (fun () -> SolveTypSubsumesTyp csenv 0 m NoTrace None reqdObjTy availObjTy ++ (fun () -> ResultD true)) diff --git a/src/fsharp/ConstraintSolver.fsi b/src/fsharp/ConstraintSolver.fsi index b2837078737..ff710203c19 100644 --- a/src/fsharp/ConstraintSolver.fsi +++ b/src/fsharp/ConstraintSolver.fsi @@ -9,6 +9,7 @@ open Microsoft.FSharp.Compiler.AbstractIL open Microsoft.FSharp.Compiler.AbstractIL.Internal open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library open Microsoft.FSharp.Compiler +open Microsoft.FSharp.Compiler.NameResolution open Microsoft.FSharp.Compiler.AccessibilityLogic open Microsoft.FSharp.Compiler.Ast open Microsoft.FSharp.Compiler.ErrorLogger @@ -37,45 +38,67 @@ val NewErrorMeasure : unit -> Measure /// Create a list of inference type variables, one for each element in the input list val NewInferenceTypes : 'a list -> TType list +/// Freshen a trait for use at a particular location +type TraitFreshener = (TraitConstraintInfo -> TraitPossibleExtensionMemberSolutions * TraitAccessorDomain) + /// Given a set of formal type parameters and their constraints, make new inference type variables for /// each and ensure that the constraints on the new type variables are adjusted to refer to these. -val FreshenAndFixupTypars : range -> TyparRigidity -> Typars -> TType list -> Typars -> Typars * TyparInst * TType list +val FreshenAndFixupTypars : TraitFreshener option -> range -> TyparRigidity -> Typars -> TType list -> Typars -> Typars * TyparInst * TType list + +/// Make new type inference variables for the use of a generic construct at a particular location +val FreshenTypeInst : TraitFreshener option -> range -> Typars -> Typars * TyparInst * TType list -val FreshenTypeInst : range -> Typars -> Typars * TyparInst * TType list +/// Make new type inference variables for the use of a generic construct at a particular location +val FreshenTypars : TraitFreshener option -> range -> Typars -> TType list -val FreshenTypars : range -> Typars -> TType list +/// Make new type inference variables for the use of a method at a particular location +val FreshenMethInfo : TraitFreshener option -> range -> MethInfo -> TType list -val FreshenMethInfo : range -> MethInfo -> TType list +/// Get the trait freshener for a particular location +val GetTraitFreshner : AccessorDomain -> NameResolutionEnv -> TraitFreshener [] -/// Information about the context of a type equation. +/// Information about the context of a type equation, for better error reporting type ContextInfo = -/// No context was given. -| NoContext -/// The type equation comes from an IF expression. -| IfExpression of range -/// The type equation comes from an omitted else branch. -| OmittedElseBranch of range -/// The type equation comes from a type check of the result of an else branch. -| ElseBranchResult of range -/// The type equation comes from the verification of record fields. -| RecordFields -/// The type equation comes from the verification of a tuple in record fields. -| TupleInRecordFields -/// The type equation comes from a list or array constructor -| CollectionElement of bool * range -/// The type equation comes from a return in a computation expression. -| ReturnInComputationExpression -/// The type equation comes from a yield in a computation expression. -| YieldInComputationExpression -/// The type equation comes from a runtime type test. -| RuntimeTypeTest of bool -/// The type equation comes from an downcast where a upcast could be used. -| DowncastUsedInsteadOfUpcast of bool -/// The type equation comes from a return type of a pattern match clause (not the first clause). -| FollowingPatternMatchClause of range -/// The type equation comes from a pattern match guard. -| PatternMatchGuard of range + + /// No context was given. + | NoContext + + /// The type equation comes from an IF expression. + | IfExpression of range + + /// The type equation comes from an omitted else branch. + | OmittedElseBranch of range + + /// The type equation comes from a type check of the result of an else branch. + | ElseBranchResult of range + + /// The type equation comes from the verification of record fields. + | RecordFields + + /// The type equation comes from the verification of a tuple in record fields. + | TupleInRecordFields + + /// The type equation comes from a list or array constructor + | CollectionElement of bool * range + + /// The type equation comes from a return in a computation expression. + | ReturnInComputationExpression + + /// The type equation comes from a yield in a computation expression. + | YieldInComputationExpression + + /// The type equation comes from a runtime type test. + | RuntimeTypeTest of bool + + /// The type equation comes from an downcast where a upcast could be used. + | DowncastUsedInsteadOfUpcast of bool + + /// The type equation comes from a return type of a pattern match clause (not the first clause). + | FollowingPatternMatchClause of range + + /// The type equation comes from a pattern match guard. + | PatternMatchGuard of range exception ConstraintSolverTupleDiffLengths of DisplayEnv * TType list * TType list * range * range @@ -117,7 +140,10 @@ type OptionalTrace = val SimplifyMeasuresInTypeScheme : TcGlobals -> bool -> Typars -> TType -> TyparConstraint list -> Typars val SolveTyparEqualsTyp : ConstraintSolverEnv -> int -> range -> OptionalTrace -> TType -> TType -> OperationResult val SolveTypEqualsTypKeepAbbrevs : ConstraintSolverEnv -> int -> range -> OptionalTrace -> TType -> TType -> OperationResult + +/// Canonicalize constraints prior to generalization val CanonicalizeRelevantMemberConstraints : ConstraintSolverEnv -> int -> OptionalTrace -> Typars -> OperationResult + val ResolveOverloading : ConstraintSolverEnv -> OptionalTrace -> string -> ndeep: int -> TraitConstraintInfo option -> int * int -> AccessorDomain -> CalledMeth list -> bool -> TType option -> CalledMeth option * OperationResult val UnifyUniqueOverloading : ConstraintSolverEnv -> int * int -> string -> AccessorDomain -> CalledMeth list -> TType -> OperationResult val EliminateConstraintsForGeneralizedTypars : ConstraintSolverEnv -> OptionalTrace -> Typars -> unit @@ -142,8 +168,11 @@ val AddCxTypeIsUnmanaged : DisplayEnv -> ConstraintSolverSt val AddCxTypeIsEnum : DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> TType -> unit val AddCxTypeIsDelegate : DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> TType -> TType -> unit -val CodegenWitnessThatTypSupportsTraitConstraint : TcValF -> TcGlobals -> ImportMap -> range -> TraitConstraintInfo -> Expr list -> OperationResult +val CodegenWitnessThatTypSupportsTraitConstraint : TcValF -> TcGlobals -> ImportMap -> range -> traitInfo: TraitConstraintInfo -> argExprs: Expr list -> OperationResult val ChooseTyparSolutionAndSolve : ConstraintSolverState -> DisplayEnv -> Typar -> unit +/// Get the type variables that may help provide solutions to a statically resolved member trait constraint +val GetSupportOfMemberConstraint : ConstraintSolverEnv -> TraitConstraintInfo -> Typar list + val IsApplicableMethApprox : TcGlobals -> ImportMap -> range -> MethInfo -> TType -> bool diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index deeb8d5daf0..3c754104c30 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -1071,7 +1071,7 @@ lexIndentOffForML,"Consider using a file with extension '.ml' or '.mli' instead" 1212,tcOptionalArgsMustComeAfterNonOptionalArgs,"Optional arguments must come at the end of the argument list, after any non-optional arguments" 1213,tcConditionalAttributeUsage,"Attribute 'System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes" #1214,monoRegistryBugWorkaround,"Could not determine highest installed .NET framework version from Registry keys, using version 2.0" -1215,tcMemberOperatorDefinitionInExtrinsic,"Extension members cannot provide operator overloads. Consider defining the operator as part of the type definition instead." +#1215,tcMemberOperatorDefinitionInExtrinsic,"Extension members cannot provide operator overloads. Consider defining the operator as part of the type definition instead." 1216,ilwriteMDBFileNameCannotBeChangedWarning,"The name of the MDB file must be .mdb. The --pdb option will be ignored." 1217,ilwriteMDBMemberMissing,"MDB generation failed. Could not find compatible member %s" 1218,ilwriteErrorCreatingMdb,"Cannot generate MDB debug information. Failed to load the 'MonoSymbolWriter' type from the 'Mono.CompilerServices.SymbolWriter.dll' assembly." diff --git a/src/fsharp/FindUnsolved.fs b/src/fsharp/FindUnsolved.fs index 484c9af1024..9e279bad9c5 100644 --- a/src/fsharp/FindUnsolved.fs +++ b/src/fsharp/FindUnsolved.fs @@ -114,7 +114,7 @@ and accOp cenv env (op,tyargs,args,_m) = accTypeInst cenv env enclTypeArgs accTypeInst cenv env methTypeArgs accTypeInst cenv env tys - | TOp.TraitCall(TTrait(tys,_nm,_,argtys,rty,_sln)) -> + | TOp.TraitCall(TTrait(tys, _nm, _, argtys, rty, _sln, _extSlns, _ad)) -> argtys |> accTypeInst cenv env rty |> Option.iter (accTy cenv env) tys |> List.iter (accTy cenv env) diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index e0311b39529..4fd19ea37d3 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -186,7 +186,7 @@ type cenv = amap: ImportMap intraAssemblyInfo : IlxGenIntraAssemblyInfo /// Cache methods with SecurityAttribute applied to them, to prevent unnecessary calls to ExistsInEntireHierarchyOfType - casApplied : Dictionary + casApplied : Dictionary /// Used to apply forced inlining optimizations to witnesses generated late during codegen mutable optimizeDuringCodeGen : (Expr -> Expr) } diff --git a/src/fsharp/InfoReader.fs b/src/fsharp/InfoReader.fs index c6f8a7629ce..e7232aceb5b 100644 --- a/src/fsharp/InfoReader.fs +++ b/src/fsharp/InfoReader.fs @@ -8,7 +8,7 @@ open Microsoft.FSharp.Compiler.AbstractIL.IL open Microsoft.FSharp.Compiler.AbstractIL.Internal open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library -open Microsoft.FSharp.Compiler +open Microsoft.FSharp.Compiler open Microsoft.FSharp.Compiler.AccessibilityLogic open Microsoft.FSharp.Compiler.Ast open Microsoft.FSharp.Compiler.AttributeChecking @@ -20,7 +20,7 @@ open Microsoft.FSharp.Compiler.Tastops open Microsoft.FSharp.Compiler.TcGlobals /// Use the given function to select some of the member values from the members of an F# type -let private SelectImmediateMemberVals g optFilter f (tcref:TyconRef) = +let SelectImmediateMemberVals g optFilter f (tcref:TyconRef) = let chooser (vref:ValRef) = match vref.MemberInfo with // The 'when' condition is a workaround for the fact that values providing diff --git a/src/fsharp/MethodCalls.fs b/src/fsharp/MethodCalls.fs index 8221e808746..bc992e6e822 100644 --- a/src/fsharp/MethodCalls.fs +++ b/src/fsharp/MethodCalls.fs @@ -452,6 +452,9 @@ type CalledMeth<'T> member x.TotalNumUnnamedCallerArgs = x.ArgSets |> List.sumBy (fun x -> x.NumUnnamedCallerArgs) member x.TotalNumAssignedNamedArgs = x.ArgSets |> List.sumBy (fun x -> x.NumAssignedNamedArgs) + override x.ToString() = "call to " + minfo.ToString() + + let NamesOfCalledArgs (calledArgs: CalledArg list) = calledArgs |> List.choose (fun x -> x.NameOpt) @@ -630,13 +633,13 @@ let BuildFSharpMethodApp g m (vref: ValRef) vexp vexprty (args: Exprs) = retTy /// Build a call to an F# method. -let BuildFSharpMethodCall g m (typ,vref:ValRef) valUseFlags minst args = - let vexp = Expr.Val (vref,valUseFlags,m) +let BuildFSharpMethodCall g m (vref:ValRef) valUseFlags declaringTypeInst minst args = + let vexp = Expr.Val (vref, valUseFlags, m) let vexpty = vref.Type let tpsorig,tau = vref.TypeScheme - let vtinst = argsOfAppTy g typ @ minst - if tpsorig.Length <> vtinst.Length then error(InternalError("BuildFSharpMethodCall: unexpected List.length mismatch",m)) - let expr = mkTyAppExpr m (vexp,vexpty) vtinst + let vtinst = declaringTypeInst @ minst + if tpsorig.Length <> vtinst.Length then error(InternalError("BuildFSharpMethodCall: unexpected typar length mismatch",m)) + let expr = mkTyAppExpr m (vexp, vexpty) vtinst let exprty = instType (mkTyparInst tpsorig vtinst) tau BuildFSharpMethodApp g m vref expr exprty args @@ -645,15 +648,20 @@ let BuildFSharpMethodCall g m (typ,vref:ValRef) valUseFlags minst args = /// calls to the type-directed solutions to member constraints. let MakeMethInfoCall amap m minfo minst args = let valUseFlags = NormalValUse // correct unless if we allow wild trait constraints like "T has a ctor and can be used as a parent class" + match minfo with + | ILMeth(g,ilminfo,_) -> let direct = not minfo.IsVirtual let isProp = false // not necessarily correct, but this is only used post-creflect where this flag is irrelevant BuildILMethInfoCall g amap m isProp ilminfo valUseFlags minst direct args |> fst - | FSMeth(g,typ,vref,_) -> - BuildFSharpMethodCall g m (typ,vref) valUseFlags minst args |> fst + + | FSMeth(g, _, vref, _) -> + BuildFSharpMethodCall g m vref valUseFlags minfo.DeclaringTypeInst minst args |> fst + | DefaultStructCtor(_,typ) -> mkDefault (m,typ) + #if !NO_EXTENSIONTYPING | ProvidedMeth(amap,mi,_,m) -> let isProp = false // not necessarily correct, but this is only used post-creflect where this flag is irrelevant diff --git a/src/fsharp/NameResolution.fs b/src/fsharp/NameResolution.fs index a80ddbf1df6..a66edbc4695 100644 --- a/src/fsharp/NameResolution.fs +++ b/src/fsharp/NameResolution.fs @@ -269,7 +269,7 @@ let (|ItemWithInst|) (x:ItemWithInst) = (x.Item, x.TyparInst) type FieldResolution = FieldResolution of RecdFieldRef * bool /// Information about an extension member held in the name resolution environment -type ExtensionMember = +type ExtensionMember = /// F#-style Extrinsic extension member, defined in F# code | FSExtMem of ValRef * ExtensionMethodPriority @@ -279,6 +279,8 @@ type ExtensionMember = /// IL-style extension member, backed by some kind of method with an [] attribute | ILExtMem of TyconRef * MethInfo * ExtensionMethodPriority + interface TraitPossibleExtensionMemberSolution + /// Check if two extension members refer to the same definition static member Equality g e1 e2 = match e1, e2 with @@ -303,6 +305,11 @@ type ExtensionMember = match x with | FSExtMem (_,pri) -> pri | ILExtMem (_,_,pri) -> pri + + member x.LogicalName = + match x with + | FSExtMem (vref,_) -> vref.LogicalName + | ILExtMem (_,minfo,_) -> minfo.LogicalName type FullyQualifiedFlag = /// Only resolve full paths @@ -363,6 +370,9 @@ type NameResolutionEnv = /// Extension members by type and name eIndexedExtensionMembers: TyconRefMultiMap + /// Extension members by name + eExtensionMembersByName: NameMultiMap + /// Other extension members unindexed by type eUnindexedExtensionMembers: ExtensionMember list @@ -385,6 +395,7 @@ type NameResolutionEnv = eFullyQualifiedTyconsByAccessNames = LayeredMultiMap.Empty eFullyQualifiedTyconsByDemangledNameAndArity = LayeredMap.Empty eIndexedExtensionMembers = TyconRefMultiMap<_>.Empty + eExtensionMembersByName = NameMultiMap<_>.Empty eUnindexedExtensionMembers = [] eTypars = Map.empty } @@ -523,6 +534,17 @@ let AddValRefToExtensionMembers pri (eIndexedExtensionMembers: TyconRefMultiMap< else eIndexedExtensionMembers +/// Add an F# value to the table of available extension members, if necessary, as an FSharp-style extension member +let AddValRefToExtensionMembersByNameTable logicalName (eExtensionMembersByName: NameMultiMap<_>) extMemInfo = + NameMultiMap.add logicalName extMemInfo eExtensionMembersByName + +/// Add an F# value to the table of available extension members, if necessary, as an FSharp-style extension member +let AddValRefToExtensionMembersByName pri (eExtensionMembersByName: NameMultiMap<_>) (vref:ValRef) = + if vref.IsMember && vref.IsExtensionMember then + AddValRefToExtensionMembersByNameTable vref.LogicalName eExtensionMembersByName (FSExtMem (vref,pri)) + else + eExtensionMembersByName + /// This entrypoint is used to add some extra items to the environment for Visual Studio, e.g. static members let AddFakeNamedValRefToNameEnv nm nenv vref = @@ -553,6 +575,7 @@ let AddValRefsToNameEnvWithPriority bulkAddMode pri nenv (vrefs: ValRef []) = { nenv with eUnqualifiedItems = AddValRefsToItems bulkAddMode nenv.eUnqualifiedItems vrefs eIndexedExtensionMembers = (nenv.eIndexedExtensionMembers,vrefs) ||> Array.fold (AddValRefToExtensionMembers pri) + eExtensionMembersByName = (nenv.eExtensionMembersByName,vrefs) ||> Array.fold (AddValRefToExtensionMembersByName pri) ePatItems = (nenv.ePatItems,vrefs) ||> Array.fold AddValRefsToActivePatternsNameEnv } /// Add a single F# value to the environment. @@ -565,6 +588,7 @@ let AddValRefToNameEnv nenv (vref:ValRef) = else nenv.eUnqualifiedItems eIndexedExtensionMembers = AddValRefToExtensionMembers pri nenv.eIndexedExtensionMembers vref + eExtensionMembersByName = AddValRefToExtensionMembersByName pri nenv.eExtensionMembersByName vref ePatItems = AddValRefsToActivePatternsNameEnv nenv.ePatItems vref } @@ -635,12 +659,12 @@ let private AddPartsOfTyconRefToNameEnv bulkAddMode ownDefinition (g:TcGlobals) let ucrefs = if isIL then [] else tcref.UnionCasesAsList |> List.map tcref.MakeNestedUnionCaseRef let flds = if isIL then [| |] else tcref.AllFieldsArray - let eIndexedExtensionMembers, eUnindexedExtensionMembers = + let eIndexedExtensionMembers, eExtensionMembersByName, eUnindexedExtensionMembers = let ilStyleExtensionMeths = GetCSharpStyleIndexedExtensionMembersForTyconRef amap m tcref - ((nenv.eIndexedExtensionMembers,nenv.eUnindexedExtensionMembers),ilStyleExtensionMeths) ||> List.fold (fun (tab1,tab2) extMemInfo -> + ((nenv.eIndexedExtensionMembers, nenv.eExtensionMembersByName, nenv.eUnindexedExtensionMembers),ilStyleExtensionMeths) ||> List.fold (fun (tab1,tab2,tab3) extMemInfo -> match extMemInfo with - | Choice1Of2 (tcref,extMemInfo) -> tab1.Add (tcref, extMemInfo), tab2 - | Choice2Of2 extMemInfo -> tab1, extMemInfo :: tab2) + | Choice1Of2 (tcref,extMemInfo) -> tab1.Add (tcref, extMemInfo), AddValRefToExtensionMembersByNameTable extMemInfo.LogicalName tab2 extMemInfo, tab3 + | Choice2Of2 extMemInfo -> tab1, AddValRefToExtensionMembersByNameTable extMemInfo.LogicalName tab2 extMemInfo, extMemInfo :: tab3) let isILOrRequiredQualifiedAccess = isIL || (not ownDefinition && HasFSharpAttribute g g.attrib_RequireQualifiedAccessAttribute tcref.Attribs) let eFieldLabels = @@ -693,6 +717,7 @@ let private AddPartsOfTyconRefToNameEnv bulkAddMode ownDefinition (g:TcGlobals) eUnqualifiedItems = eUnqualifiedItems ePatItems = ePatItems eIndexedExtensionMembers = eIndexedExtensionMembers + eExtensionMembersByName = eExtensionMembersByName eUnindexedExtensionMembers = eUnindexedExtensionMembers } let TryFindPatternByName name {ePatItems = patternMap} = @@ -1909,6 +1934,21 @@ let IntrinsicMethInfosOfType (infoReader:InfoReader) (optFilter,ad,allowMultiInt let minfos = minfos |> ExcludeHiddenOfMethInfos g amap m minfos +let 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 +#if !NO_EXTENSIONTYPING + // // 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 @@ -1926,20 +1966,9 @@ let SelectMethInfosFromExtMembers (infoReader:InfoReader) optFilter apparentTy m | 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 minfo with - | ILMeth(_,ilminfo,_) -> - yield (MethInfo.CreateILExtensionMeth (infoReader.amap, m, apparentTy, actualParent, Some pri, ilminfo.RawMetadata)) - // F#-defined IL-style extension methods are not seen as extension methods in F# code - | FSMeth(g,_,vref,_) -> - yield (FSMeth(g, apparentTy, vref, Some pri)) -#if !NO_EXTENSIONTYPING - // // Provided extension methods are not yet supported - | ProvidedMeth(amap,providedMeth,_,m) -> - yield (ProvidedMeth(amap, providedMeth, Some pri,m)) -#endif - | DefaultStructCtor _ -> - () + match TrySelectExtensionMethInfoOfILExtMem m infoReader.amap apparentTy (actualParent, minfo, pri) with + | Some minfo -> yield minfo + | None -> () | _ -> () ] diff --git a/src/fsharp/NameResolution.fsi b/src/fsharp/NameResolution.fsi index 93f0009ff8b..5f043b27b2d 100755 --- a/src/fsharp/NameResolution.fsi +++ b/src/fsharp/NameResolution.fsi @@ -136,25 +136,86 @@ val ItemWithNoInst : Item -> ItemWithInst type FieldResolution = FieldResolution of RecdFieldRef * bool /// Information about an extension member held in the name resolution environment -[] -type ExtensionMember +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 [] attribute + | ILExtMem of TyconRef * MethInfo * ExtensionMethodPriority + + interface TraitPossibleExtensionMemberSolution + + /// The logical name, e.g. for constraint solving + member LogicalName : string + + /// 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 Priority : ExtensionMethodPriority /// The environment of information used to resolve names [] type NameResolutionEnv = - {eDisplayEnv: DisplayEnv - eUnqualifiedItems: LayeredMap - ePatItems: NameMap - eModulesAndNamespaces: NameMultiMap - eFullyQualifiedModulesAndNamespaces: NameMultiMap - eFieldLabels: NameMultiMap - eTyconsByAccessNames: LayeredMultiMap - eFullyQualifiedTyconsByAccessNames: LayeredMultiMap - eTyconsByDemangledNameAndArity: LayeredMap - eFullyQualifiedTyconsByDemangledNameAndArity: LayeredMap - eIndexedExtensionMembers: TyconRefMultiMap - eUnindexedExtensionMembers: ExtensionMember list - eTypars: NameMap } + { /// Display environment information for output + eDisplayEnv: DisplayEnv + + /// Values and Data Tags available by unqualified name + eUnqualifiedItems: LayeredMap + + /// Data Tags and Active Pattern Tags available by unqualified name + ePatItems: NameMap + + /// 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() <--- give a warning" + + eModulesAndNamespaces: NameMultiMap + + /// Fully qualified modules and namespaces. 'open' does not change this. + eFullyQualifiedModulesAndNamespaces: NameMultiMap + + /// 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 + + /// 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 + + eFullyQualifiedTyconsByAccessNames: LayeredMultiMap + + /// Tycons available by unqualified, demangled names (i.e. (List,1) --> TyconRef) + eTyconsByDemangledNameAndArity: LayeredMap + + /// Tycons available by unqualified, demangled names (i.e. (List,1) --> TyconRef) + eFullyQualifiedTyconsByDemangledNameAndArity: LayeredMap + + /// Extension members by type and name + eIndexedExtensionMembers: TyconRefMultiMap + + /// Extension members by name + eExtensionMembersByName: NameMultiMap + + /// 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 + + } static member Empty : g:TcGlobals -> NameResolutionEnv member DisplayEnv : DisplayEnv member FindUnqualifiedItem : string -> Item @@ -515,3 +576,5 @@ val ResolveCompletionsInType : NameResolver -> NameResolutionEnv -> Resolv val GetVisibleNamespacesAndModulesAtPoint : NameResolver -> NameResolutionEnv -> range -> AccessorDomain -> ModuleOrNamespaceRef list val IsItemResolvable : NameResolver -> NameResolutionEnv -> range -> AccessorDomain -> string list -> Item -> bool + +val TrySelectExtensionMethInfoOfILExtMem : range -> ImportMap -> TType -> TyconRef * MethInfo * ExtensionMethodPriority -> MethInfo option \ No newline at end of file diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index 258f12a520c..1e98ff720e2 100755 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -789,8 +789,8 @@ module private PrintTypes = cxs |> ListSet.setify (fun (_,cx1) (_,cx2) -> match cx1,cx2 with - | TyparConstraint.MayResolveMember(traitInfo1,_), - TyparConstraint.MayResolveMember(traitInfo2,_) -> traitsAEquiv denv.g TypeEquivEnv.Empty traitInfo1 traitInfo2 + | TyparConstraint.MayResolveMember(traitInfo1, _), + TyparConstraint.MayResolveMember(traitInfo2, _) -> traitsAEquiv denv.g TypeEquivEnv.Empty traitInfo1 traitInfo2 | _ -> false) let cxsL = List.collect (layoutConstraintWithInfo denv env) cxs @@ -810,7 +810,7 @@ module private PrintTypes = match tpc with | TyparConstraint.CoercesTo(tpct,_) -> [layoutTyparRefWithInfo denv env tp ^^ wordL (tagOperator ":>") --- layoutTypeWithInfo denv env tpct] - | TyparConstraint.MayResolveMember(traitInfo,_) -> + | TyparConstraint.MayResolveMember(traitInfo, _) -> [layoutTraitWithInfo denv env traitInfo] | TyparConstraint.DefaultsTo(_,ty,_) -> if denv.showTyparDefaultConstraints then [wordL (tagKeyword "default") ^^ layoutTyparRefWithInfo denv env tp ^^ WordL.colon ^^ layoutTypeWithInfo denv env ty] @@ -865,7 +865,7 @@ module private PrintTypes = WordL.arrow ^^ (layoutTyparRefWithInfo denv env tp)) |> longConstraintPrefix] - and private layoutTraitWithInfo denv env (TTrait(tys,nm,memFlags,argtys,rty,_)) = + and private layoutTraitWithInfo denv env (TTrait(tys, nm, memFlags, argtys, rty, _, _, _)) = let nm = DemangleOperatorName nm if denv.shortConstraints then WordL.keywordMember ^^ wordL (tagMember nm) @@ -877,9 +877,19 @@ module private PrintTypes = match tys with | [ty] -> layoutTypeWithInfo denv env ty | tys -> bracketL (layoutTypesWithInfoAndPrec denv env 2 (wordL (tagKeyword "or")) tys) + + let argtys = + if memFlags.IsInstance then + match argtys with + | [] | [_] -> [denv.g.unit_ty] + | _ :: rest -> rest + else argtys + + let argtysL = layoutTypesWithInfoAndPrec denv env 2 (wordL (tagPunctuation "*")) argtys + tysL ^^ wordL (tagPunctuation ":") --- bracketL (stat ++ wordL (tagMember nm) ^^ wordL (tagPunctuation ":") --- - ((layoutTypesWithInfoAndPrec denv env 2 (wordL (tagPunctuation "*")) argtys --- wordL (tagPunctuation "->")) --- (layoutTypeWithInfo denv env rty))) + ((argtysL --- wordL (tagPunctuation "->")) --- (layoutTypeWithInfo denv env rty))) /// Layout a unit expression diff --git a/src/fsharp/Optimizer.fs b/src/fsharp/Optimizer.fs index 3ea19645b6b..26733658403 100644 --- a/src/fsharp/Optimizer.fs +++ b/src/fsharp/Optimizer.fs @@ -1002,6 +1002,12 @@ let AbstractLazyModulInfoByHiding isAssemblyBoundary mhi = Zset.exists hiddenRecdField fvs.FreeRecdFields || Zset.exists hiddenUnionCase fvs.FreeUnionCases ) -> UnknownValue + + // TODO: consider what happens when the expression refers to extSlns that have become hidden + // At the moment it feels like this may lead to remap failures, where the optimization information + // for a module contains dangling references to extSlns that are no longer needed (because they have been solved). + // However, we don't save extSlns into actual pickled optimization information, so maybe this is not a problem. + // Check for escape in constant | ConstValue(_, ty) when (let ftyvs = freeInType CollectAll ty @@ -2164,7 +2170,7 @@ and OptimizeWhileLoop cenv env (spWhile, marker, e1, e2, m) = //------------------------------------------------------------------------- -and OptimizeTraitCall cenv env (traitInfo, args, m) = +and OptimizeTraitCall cenv env (traitInfo, args, m) = // Resolve the static overloading early (during the compulsory rewrite phase) so we can inline. match ConstraintSolver.CodegenWitnessThatTypSupportsTraitConstraint cenv.TcVal cenv.g cenv.amap m traitInfo args with @@ -3190,7 +3196,7 @@ let OptimizeImplFile(settings, ccu, tcGlobals, tcVal, importMap, optEnv, isIncre optimizing=true localInternalVals=Dictionary(10000) emitTailcalls=emitTailcalls - casApplied=new Dictionary() } + casApplied=new Dictionary() } let (optEnvNew, _, _, _ as results) = OptimizeImplFileInternal cenv optEnv isIncrementalFragment hidden mimpls let optimizeDuringCodeGen expr = OptimizeExpr cenv optEnvNew expr |> fst results, optimizeDuringCodeGen diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index 8906c9a4e8f..a5b5dabd012 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -213,7 +213,7 @@ let rec CheckTypeDeep ((visitTyp,visitTyconRefOpt,visitAppTyOpt,visitTraitSoluti | TType_var tp when tp.Solution.IsSome -> tp.Constraints |> List.iter (fun cx -> match cx with - | TyparConstraint.MayResolveMember((TTrait(_,_,_,_,_,soln)),_) -> + | TyparConstraint.MayResolveMember((TTrait(_, _, _, _, _, soln, _, _)), _) -> match visitTraitSolutionOpt, !soln with | Some visitTraitSolution, Some sln -> visitTraitSolution sln | _ -> () @@ -254,7 +254,7 @@ and CheckTypesDeep f g env tys = List.iter (CheckTypeDeep f g env) tys and CheckTypeConstraintDeep f g env x = match x with | TyparConstraint.CoercesTo(ty,_) -> CheckTypeDeep f g env ty - | TyparConstraint.MayResolveMember(traitInfo,_) -> CheckTraitInfoDeep f g env traitInfo + | TyparConstraint.MayResolveMember(traitInfo, _) -> CheckTraitInfoDeep f g env traitInfo | TyparConstraint.DefaultsTo(_,ty,_) -> CheckTypeDeep f g env ty | TyparConstraint.SimpleChoice(tys,_) -> CheckTypesDeep f g env tys | TyparConstraint.IsEnum(uty,_) -> CheckTypeDeep f g env uty @@ -266,7 +266,8 @@ and CheckTypeConstraintDeep f g env x = | TyparConstraint.IsUnmanaged _ | TyparConstraint.IsReferenceType _ | TyparConstraint.RequiresDefaultConstructor _ -> () -and CheckTraitInfoDeep ((_,_,_,visitTraitSolutionOpt,_) as f) g env (TTrait(typs,_,_,argtys,rty,soln)) = + +and CheckTraitInfoDeep ((_,_,_,visitTraitSolutionOpt,_) as f) g env (TTrait(typs, _, _, argtys, rty, soln, _extSlns, _ad)) = CheckTypesDeep f g env typs CheckTypesDeep f g env argtys Option.iter (CheckTypeDeep f g env) rty diff --git a/src/fsharp/TastOps.fs b/src/fsharp/TastOps.fs index d2d378508de..c8845733bfa 100644 --- a/src/fsharp/TastOps.fs +++ b/src/fsharp/TastOps.fs @@ -57,7 +57,7 @@ type TyconRefMap<'T>(imap: StampMap<'T>) = member m.Add (v: TyconRef) x = TyconRefMap (imap.Add (v.Stamp, x)) member m.Remove (v: TyconRef) = TyconRefMap (imap.Remove v.Stamp) member m.IsEmpty = imap.IsEmpty - + member m.Contents = imap static member Empty : TyconRefMap<'T> = TyconRefMap Map.empty static member OfList vs = (vs, TyconRefMap<'T>.Empty) ||> List.foldBack (fun (x, y) acc -> acc.Add x y) @@ -90,15 +90,25 @@ let emptyTyparInst = ([] : TyparInst) [] type Remap = { tpinst : TyparInst + + /// Values to remap valRemap: ValRemap + + /// TyconRefs to remap tyconRefRemap : TyconRefRemap - removeTraitSolutions: bool } + + /// Remove existing trait solutions? + removeTraitSolutions: bool + + /// A map indicating how to fill in extSlns for traits as we copy an expression. Indexed by the member name of the trait + extSlnsMap: Map } let emptyRemap = { tpinst = emptyTyparInst; tyconRefRemap = emptyTyconRefRemap valRemap = ValMap.Empty - removeTraitSolutions = false } + removeTraitSolutions = false + extSlnsMap = Map.empty } type Remap with static member Empty = emptyRemap @@ -226,16 +236,16 @@ and remapTypesAux tyenv types = List.mapq (remapTypeAux tyenv) types and remapTyparConstraintsAux tyenv cs = cs |> List.choose (fun x -> match x with - | TyparConstraint.CoercesTo(ty, m) -> - Some(TyparConstraint.CoercesTo (remapTypeAux tyenv ty, m)) + | TyparConstraint.CoercesTo(ty,m) -> + Some(TyparConstraint.CoercesTo (remapTypeAux tyenv ty,m)) | TyparConstraint.MayResolveMember(traitInfo, m) -> - Some(TyparConstraint.MayResolveMember (remapTraitAux tyenv traitInfo, m)) - | TyparConstraint.DefaultsTo(priority, ty, m) -> Some(TyparConstraint.DefaultsTo(priority, remapTypeAux tyenv ty, m)) - | TyparConstraint.IsEnum(uty, m) -> - Some(TyparConstraint.IsEnum(remapTypeAux tyenv uty, m)) - | TyparConstraint.IsDelegate(uty1, uty2, m) -> - Some(TyparConstraint.IsDelegate(remapTypeAux tyenv uty1, remapTypeAux tyenv uty2, m)) - | TyparConstraint.SimpleChoice(tys, m) -> Some(TyparConstraint.SimpleChoice(remapTypesAux tyenv tys, m)) + Some(TyparConstraint.MayResolveMember (remapTraitAux tyenv traitInfo,m)) + | TyparConstraint.DefaultsTo(priority,ty,m) -> Some(TyparConstraint.DefaultsTo(priority,remapTypeAux tyenv ty,m)) + | TyparConstraint.IsEnum(uty,m) -> + Some(TyparConstraint.IsEnum(remapTypeAux tyenv uty,m)) + | TyparConstraint.IsDelegate(uty1,uty2,m) -> + Some(TyparConstraint.IsDelegate(remapTypeAux tyenv uty1,remapTypeAux tyenv uty2,m)) + | TyparConstraint.SimpleChoice(tys,m) -> Some(TyparConstraint.SimpleChoice(remapTypesAux tyenv tys,m)) | TyparConstraint.SupportsComparison _ | TyparConstraint.SupportsEquality _ | TyparConstraint.SupportsNull _ @@ -244,7 +254,7 @@ and remapTyparConstraintsAux tyenv cs = | TyparConstraint.IsReferenceType _ | TyparConstraint.RequiresDefaultConstructor _ -> Some(x)) -and remapTraitAux tyenv (TTrait(typs, nm, mf, argtys, rty, slnCell)) = +and remapTraitAux tyenv (TTrait(typs, nm, mf, argtys, rty, slnCell, extSlns, ad)) = let slnCell = match !slnCell with | None -> None @@ -263,7 +273,14 @@ and remapTraitAux tyenv (TTrait(typs, nm, mf, argtys, rty, slnCell)) = | ClosedExprSln e -> ClosedExprSln e // no need to remap because it is a closed expression, referring only to external types Some sln - // Note: we reallocate a new solution cell on every traversal of a trait constraint + + let extSlnsNew = + if tyenv.extSlnsMap.ContainsKey nm then + tyenv.extSlnsMap.[nm] + else + extSlns // TODO: do we need to remap here??? + + // Note: we reallocate a new solution cell (though keep existing solutions unless 'removeTraitSolutions'=true) on every traversal of a trait constraint // This feels incorrect for trait constraints that are quantified: it seems we should have // formal binders for trait constraints when they are quantified, just as // we have formal binders for type variables. @@ -271,7 +288,7 @@ and remapTraitAux tyenv (TTrait(typs, nm, mf, argtys, rty, slnCell)) = // The danger here is that a solution for one syntactic occurrence of a trait constraint won't // be propagated to other, "linked" solutions. However trait constraints don't appear in any algebra // in the same way as types - TTrait(remapTypesAux tyenv typs, nm, mf, remapTypesAux tyenv argtys, Option.map (remapTypeAux tyenv) rty, ref slnCell) + TTrait(remapTypesAux tyenv typs, nm, mf, remapTypesAux tyenv argtys, Option.map (remapTypeAux tyenv) rty, ref slnCell, extSlnsNew, ad) and bindTypars tps tyargs tpinst = match tps with @@ -364,12 +381,14 @@ let mkInstRemap tpinst = { tyconRefRemap = emptyTyconRefRemap tpinst = tpinst valRemap = ValMap.Empty - removeTraitSolutions = false } + removeTraitSolutions = false + extSlnsMap = Map.empty } // entry points for "typar -> TType" instantiation let instType tpinst x = if isNil tpinst then x else remapTypeAux (mkInstRemap tpinst) x let instTypes tpinst x = if isNil tpinst then x else remapTypesAux (mkInstRemap tpinst) x let instTrait tpinst x = if isNil tpinst then x else remapTraitAux (mkInstRemap tpinst) x +let instValRef tpinst x = if isNil tpinst then x else remapValRef (mkInstRemap tpinst) x let instTyparConstraints tpinst x = if isNil tpinst then x else remapTyparConstraintsAux (mkInstRemap tpinst) x let instSlotSig tpinst ss = remapSlotSig (fun _ -> []) (mkInstRemap tpinst) ss let copySlotSig ss = remapSlotSig (fun _ -> []) Remap.Empty ss @@ -802,7 +821,7 @@ type TypeEquivEnv with static member FromEquivTypars tps1 tps2 = TypeEquivEnv.Empty.BindEquivTypars tps1 tps2 -let rec traitsAEquivAux erasureFlag g aenv (TTrait(typs1, nm, mf1, argtys, rty, _)) (TTrait(typs2, nm2, mf2, argtys2, rty2, _)) = +let rec traitsAEquivAux erasureFlag g aenv (TTrait(typs1, nm, mf1, argtys, rty, _, _, _)) (TTrait(typs2, nm2, mf2, argtys2, rty2, _, _, _)) = mf1 = mf2 && nm = nm2 && ListSet.equals (typeAEquivAux erasureFlag g aenv) typs1 typs2 && @@ -822,7 +841,7 @@ and typarConstraintsAEquivAux erasureFlag g aenv tpc1 tpc2 = TyparConstraint.CoercesTo(fcty, _) -> typeAEquivAux erasureFlag g aenv acty fcty - | TyparConstraint.MayResolveMember(trait1, _), + | TyparConstraint.MayResolveMember(trait1, _), TyparConstraint.MayResolveMember(trait2, _) -> traitsAEquivAux erasureFlag g aenv trait1 trait2 @@ -1298,6 +1317,7 @@ type TyconRefMultiMap<'T>(contents: TyconRefMap<'T list>) = | _ -> [] member m.Add (v, x) = TyconRefMultiMap<'T>(contents.Add v (x :: m.Find v)) + member m.Contents = contents static member Empty = TyconRefMultiMap<'T>(TyconRefMap<_>.Empty) static member OfList vs = (vs, TyconRefMultiMap<'T>.Empty) ||> List.foldBack (fun (x, y) acc -> acc.Add (x, y)) @@ -1515,7 +1535,7 @@ let isVoidTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> let isILAppTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tcref.IsILTycon | _ -> false) let isNativePtrTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tyconRefEq g g.nativeptr_tcr tcref | _ -> false) let isByrefTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tyconRefEq g g.byref_tcr tcref | _ -> false) -let isByrefLikeTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> isByrefLikeTyconRef g tcref | _ -> false) +let isByrefLikeTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> isByrefLikeTyconRef g tcref | _ -> false) #if !NO_EXTENSIONTYPING let extensionInfoOfTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tcref.TypeReprInfo | _ -> TNoRepr) #endif @@ -1897,7 +1917,7 @@ and accFreeInTyparConstraint opts tpc acc = | TyparConstraint.IsUnmanaged _ | TyparConstraint.RequiresDefaultConstructor _ -> acc -and accFreeInTrait opts (TTrait(typs, _, _, argtys, rty, sln)) acc = +and accFreeInTrait opts (TTrait(typs, _, _, argtys, rty, sln, _, _ad)) acc = Option.foldBack (accFreeInTraitSln opts) sln.Value (accFreeInTypes opts typs (accFreeInTypes opts argtys @@ -2002,10 +2022,11 @@ and accFreeInTyparConstraintLeftToRight g cxFlag thruFlag acc tpc = | TyparConstraint.IsReferenceType _ | TyparConstraint.RequiresDefaultConstructor _ -> acc -and accFreeInTraitLeftToRight g cxFlag thruFlag acc (TTrait(typs, _, _, argtys, rty, _)) = +and accFreeInTraitLeftToRight g cxFlag thruFlag acc (TTrait(typs, _, _, argtys, rty, _, _extSlns, _ad)) = let acc = accFreeInTypesLeftToRight g cxFlag thruFlag acc typs let acc = accFreeInTypesLeftToRight g cxFlag thruFlag acc argtys let acc = Option.fold (accFreeInTypeLeftToRight g cxFlag thruFlag) acc rty + // Note, the _extSlns are _not_ considered free. acc and accFreeTyparRefLeftToRight g cxFlag thruFlag acc (tp:Typar) = @@ -2019,7 +2040,6 @@ and accFreeTyparRefLeftToRight g cxFlag thruFlag acc (tp:Typar) = acc and accFreeInTypeLeftToRight g cxFlag thruFlag acc ty = - if verbose then dprintf "--> accFreeInTypeLeftToRight \n" match (if thruFlag then stripTyEqns g ty else stripTyparEqns ty) with | TType_tuple (tupInfo, l) -> let acc = accFreeInTupInfoLeftToRight g cxFlag thruFlag acc tupInfo @@ -2047,6 +2067,51 @@ let freeInTypesLeftToRightSkippingConstraints g ty = accFreeInTypesLeftToRight g let valOfBind (b:Binding) = b.Var let valsOfBinds (binds:Bindings) = binds |> List.map (fun b -> b.Var) +//-------------------------------------------------------------------------- +// Collect extSlns. This is done prior to beta reduction of type parameters when inlining. We take the (solved) +// type arguments and strip them for extSlns, and record those extSlns in the remapped/copied/instantiated body +// of the implementation. +//-------------------------------------------------------------------------- + +let rec accExtSlnsInTyparConstraints acc cxs = + List.fold accExtSlnsInTyparConstraint acc cxs + +and accExtSlnsInTyparConstraint acc tpc = + match tpc with + | TyparConstraint.MayResolveMember (traitInfo, _) -> accExtSlnsInTrait acc traitInfo + | _ -> acc + +and accExtSlnsInTrait acc (TTrait(_typs, nm, _, _argtys, _rty, _, extSlns, _ad)) = + // We don't traverse the contents of traits, that wouldn't terminate and is not necessary since the type variables individiaull contain the extSlns we need + //let acc = accExtSlnsInTypes g acc typs + //let acc = accExtSlnsInTypes g acc argtys + //let acc = Option.fold (accExtSlnsInType g) acc rty + // Only record the extSlns if they have been solved in a useful way + if isNil extSlns then acc else + Map.add nm extSlns acc + +and accExtSlnsTyparRef acc (tp:Typar) = + let acc = accExtSlnsInTyparConstraints acc tp.Constraints + match tp.Solution with + | None -> acc + | Some sln -> accExtSlnsInType acc sln + +and accExtSlnsInType acc ty = + // NOTE: Unlike almost everywhere else, we do NOT strip ANY equations here. + // We _must_ traverse the solved typar containing the new extSlns for the grounded typar constraint, that's the whole point + match ty with + | TType_tuple (_tupInfo, l) -> accExtSlnsInTypes acc l + | TType_app (_, tinst) -> accExtSlnsInTypes acc tinst + | TType_ucase (_, tinst) -> accExtSlnsInTypes acc tinst + | TType_fun (d, r) -> accExtSlnsInType (accExtSlnsInType acc d) r + | TType_var r -> accExtSlnsTyparRef acc r + | TType_forall (_tps, r) -> accExtSlnsInType acc r + | TType_measure unt -> List.foldBack (fun (tp, _) acc -> accExtSlnsTyparRef acc tp) (ListMeasureVarOccsWithNonZeroExponents unt) acc + +and accExtSlnsInTypes acc tys = (acc, tys) ||> List.fold accExtSlnsInType + +let extSlnsInTypes tys = accExtSlnsInTypes Map.empty tys + //-------------------------------------------------------------------------- // Values representing member functions on F# types //-------------------------------------------------------------------------- @@ -2320,8 +2385,6 @@ module PrettyTypes = computeKeep keep (tp :: change) rest let keep, change = computeKeep [] [] ftps - // change |> List.iter (fun tp -> dprintf "change typar: %s %s %d\n" tp.Name (tp.DisplayName) (stamp_of_typar tp)); - // keep |> List.iter (fun tp -> dprintf "keep typar: %s %s %d\n" tp.Name (tp.DisplayName) (stamp_of_typar tp)); let alreadyInUse = keep |> List.map (fun x -> x.Name) let names = PrettyTyparNames (fun x -> List.memq x change) alreadyInUse ftps @@ -2335,7 +2398,6 @@ module PrettyTypes = let tauThings = mapTys getTauStayTau things let prettyThings = mapTys (instType renaming) tauThings - // niceTypars |> List.iter (fun tp -> dprintf "nice typar: %d\n" (stamp_of_typar tp)); * let tpconstraints = niceTypars |> List.collect (fun tpnice -> List.map (fun tpc -> tpnice, tpc) tpnice.Constraints) prettyThings, tpconstraints @@ -3127,7 +3189,7 @@ module DebugPrint = begin and auxTraitL env (ttrait: TraitConstraintInfo) = #if DEBUG - let (TTrait(tys, nm, memFlags, argtys, rty, _)) = ttrait + let (TTrait(tys, nm, memFlags, argtys, rty, _, _extSlns, _ad)) = ttrait match !global_g with | None -> wordL (tagText "") | Some g -> @@ -3699,7 +3761,8 @@ let mkRepackageRemapping mrpi = { valRemap = ValMap.OfList (mrpi.mrpiVals |> List.map (fun (vref, x) -> vref.Deref, x)); tpinst = emptyTyparInst; tyconRefRemap = TyconRefMap.OfList mrpi.mrpiEntities - removeTraitSolutions = false } + removeTraitSolutions = false + extSlnsMap = Map.empty } //-------------------------------------------------------------------------- // Compute instances of the above for mty -> mty @@ -3775,7 +3838,6 @@ let accValRemap g aenv (msigty:ModuleOrNamespaceType) (implVal:Val) (mrpi, mhi) let vref = mkLocalValRef implVal match sigValOpt with | None -> - if verbose then dprintf "accValRemap, hide = %s#%d\n" implVal.LogicalName implVal.Stamp let mhi = { mhi with mhiVals = Zset.add implVal mhi.mhiVals } (mrpi, mhi) | Some (sigVal:Val) -> @@ -3799,7 +3861,6 @@ let rec accValRemapFromModuleOrNamespaceType g aenv (mty:ModuleOrNamespaceType) acc let ComputeRemappingFromInferredSignatureToExplicitSignature g mty msigty = - // dprintf "ComputeRemappingFromInferredSignatureToExplicitSignature, \nmty = %s\nmmsigty=%s\n" (showL(entityTypeL mty)) (showL(entityTypeL msigty)); let ((mrpi, _) as entityRemap) = accEntityRemapFromModuleOrNamespaceType mty msigty (SignatureRepackageInfo.Empty, SignatureHidingInfo.Empty) let aenv = mrpi.ImplToSigMapping let valAndEntityRemap = accValRemapFromModuleOrNamespaceType g aenv mty msigty entityRemap @@ -3860,7 +3921,6 @@ and accValRemapFromModuleOrNamespaceBind g aenv msigty x acc = and accValRemapFromModuleOrNamespaceDefs g aenv msigty mdefs acc = List.foldBack (accValRemapFromModuleOrNamespace g aenv msigty) mdefs acc let ComputeRemappingFromImplementationToSignature g mdef msigty = - //if verbose then dprintf "ComputeRemappingFromImplementationToSignature, \nmdefs = %s\nmsigty=%s\n" (showL(DebugPrint.mdefL mdef)) (showL(DebugPrint.entityTypeL msigty)); let ((mrpi, _) as entityRemap) = accEntityRemapFromModuleOrNamespace msigty mdef (SignatureRepackageInfo.Empty, SignatureHidingInfo.Empty) let aenv = mrpi.ImplToSigMapping @@ -3918,16 +3978,14 @@ let rec accModuleOrNamespaceHidingInfoAtAssemblyBoundary mty acc = acc let ComputeHidingInfoAtAssemblyBoundary mty acc = -// dprintf "ComputeRemappingFromInferredSignatureToExplicitSignature, \nmty = %s\nmmsigty=%s\n" (showL(entityTypeL mty)) (showL(entityTypeL msigty)); accModuleOrNamespaceHidingInfoAtAssemblyBoundary mty acc //-------------------------------------------------------------------------- // Compute instances of the above for mexpr -> mty //-------------------------------------------------------------------------- -let IsHidden setF accessF remapF debugF = +let IsHidden setF accessF remapF = let rec check mrmi x = - if verbose then dprintf "IsHidden %s ??\n" (showL (debugF x)); // Internal/private? not (canAccessFromEverywhere (accessF x)) || (match mrmi with @@ -3938,14 +3996,12 @@ let IsHidden setF accessF remapF debugF = // Recurse... check rest (remapF rpi x)) fun mrmi x -> - let res = check mrmi x - if verbose then dprintf "IsHidden, #mrmi = %d, %s = %b\n" mrmi.Length (showL (debugF x)) res; - res + check mrmi x -let IsHiddenTycon mrmi x = IsHidden (fun mhi -> mhi.mhiTycons) (fun tc -> tc.Accessibility) (fun rpi x -> (remapTyconRef rpi.tyconRefRemap (mkLocalTyconRef x)).Deref) DebugPrint.tyconL mrmi x -let IsHiddenTyconRepr mrmi x = IsHidden (fun mhi -> mhi.mhiTyconReprs) (fun v -> v.TypeReprAccessibility) (fun rpi x -> (remapTyconRef rpi.tyconRefRemap (mkLocalTyconRef x)).Deref) DebugPrint.tyconL mrmi x -let IsHiddenVal mrmi x = IsHidden (fun mhi -> mhi.mhiVals) (fun v -> v.Accessibility) (fun rpi x -> (remapValRef rpi (mkLocalValRef x)).Deref) DebugPrint.valL mrmi x -let IsHiddenRecdField mrmi x = IsHidden (fun mhi -> mhi.mhiRecdFields) (fun rfref -> rfref.RecdField.Accessibility) (fun rpi x -> remapRecdFieldRef rpi.tyconRefRemap x) DebugPrint.recdFieldRefL mrmi x +let IsHiddenTycon mrmi x = IsHidden (fun mhi -> mhi.mhiTycons) (fun tc -> tc.Accessibility) (fun rpi x -> (remapTyconRef rpi.tyconRefRemap (mkLocalTyconRef x)).Deref) mrmi x +let IsHiddenTyconRepr mrmi x = IsHidden (fun mhi -> mhi.mhiTyconReprs) (fun v -> v.TypeReprAccessibility) (fun rpi x -> (remapTyconRef rpi.tyconRefRemap (mkLocalTyconRef x)).Deref) mrmi x +let IsHiddenVal mrmi x = IsHidden (fun mhi -> mhi.mhiVals) (fun v -> v.Accessibility) (fun rpi x -> (remapValRef rpi (mkLocalValRef x)).Deref) mrmi x +let IsHiddenRecdField mrmi x = IsHidden (fun mhi -> mhi.mhiRecdFields) (fun rfref -> rfref.RecdField.Accessibility) (fun rpi x -> remapRecdFieldRef rpi.tyconRefRemap x) mrmi x //-------------------------------------------------------------------------- @@ -4293,7 +4349,7 @@ and accFreeInOp opts op acc = | TOp.ILAsm (_, tys) -> accFreeVarsInTys opts tys acc | TOp.Reraise -> accUsesRethrow true acc - | TOp.TraitCall(TTrait(tys, _, _, argtys, rty, sln)) -> + | TOp.TraitCall(TTrait(tys, _, _, argtys, rty, sln, _extSlns, _ad)) -> Option.foldBack (accFreeVarsInTraitSln opts) sln.Value (accFreeVarsInTys opts tys (accFreeVarsInTys opts argtys @@ -5105,7 +5161,10 @@ let copyModuleOrNamespaceType g compgen mtyp = copyAndRemapAndBindModTy g co let copyExpr g compgen e = remapExpr g compgen Remap.Empty e let copyImplFile g compgen e = remapImplFile g compgen Remap.Empty e |> fst -let instExpr g tpinst e = remapExpr g CloneAll (mkInstRemap tpinst) e +/// Copy an expression applying a type instantiation. +let instExpr g tpinst e = + let extSlnsMap = extSlnsInTypes (List.map snd tpinst) + remapExpr g CloneAll { mkInstRemap tpinst with extSlnsMap = extSlnsMap } e //-------------------------------------------------------------------------- // Replace Marks - adjust debugging marks when a lambda gets @@ -5279,7 +5338,7 @@ let rec tyOfExpr g e = | TOp.LValueOp (LByrefGet, v) -> destByrefTy g v.Type | TOp.LValueOp (LGetAddr, v) -> mkByrefTy g v.Type | TOp.RefAddrGet -> (match tinst with [ty] -> mkByrefTy g ty | _ -> failwith "bad TOp.RefAddrGet node") - | TOp.TraitCall (TTrait(_, _, _, _, ty, _)) -> GetFSharpViewOfReturnType g ty + | TOp.TraitCall traitInfo -> GetFSharpViewOfReturnType g traitInfo.ReturnType | TOp.Reraise -> (match tinst with [rtn_ty] -> rtn_ty | _ -> failwith "bad TOp.Reraise node") | TOp.Goto _ | TOp.Label _ | TOp.Return -> //assert false; @@ -6474,7 +6533,6 @@ let MultiLambdaToTupledLambdaIfNeeded g (vs, arg) body = //------------------------------------------------------------------------ let rec MakeApplicationAndBetaReduceAux g (f, fty, tyargsl : TType list list, argsl: Expr list, m) = - (* let verbose = true in *) match f with | Expr.Let(bind, body, mlet, _) -> // Lift bindings out, i.e. (let x = e in f) y --> let x = e in f y @@ -6994,7 +7052,6 @@ let typarEnc _g (gtpsType, gtpsMethod) typar = "``0" // REVIEW: this should be ERROR not WARNING? let rec typeEnc g (gtpsType, gtpsMethod) ty = - if verbose then dprintf "--> typeEnc" let stripped = stripTyEqnsAndMeasureEqns g ty match stripped with | TType_forall _ -> diff --git a/src/fsharp/TastOps.fsi b/src/fsharp/TastOps.fsi index 04410eae1c1..029beafdafd 100755 --- a/src/fsharp/TastOps.fsi +++ b/src/fsharp/TastOps.fsi @@ -298,6 +298,7 @@ type TyconRefMap<'T> = member Add : TyconRef -> 'T -> TyconRefMap<'T> member Remove : TyconRef -> TyconRefMap<'T> member IsEmpty : bool + member Contents : StampMap<'T> static member Empty : TyconRefMap<'T> static member OfList : (TyconRef * 'T) list -> TyconRefMap<'T> @@ -306,6 +307,7 @@ type TyconRefMap<'T> = type TyconRefMultiMap<'T> = member Find : TyconRef -> 'T list member Add : TyconRef * 'T -> TyconRefMultiMap<'T> + member Contents : TyconRefMap<'T list> static member Empty : TyconRefMultiMap<'T> static member OfList : (TyconRef * 'T) list -> TyconRefMultiMap<'T> @@ -337,10 +339,19 @@ type ValRemap = ValMap [] type Remap = - { tpinst : TyparInst; - valRemap: ValRemap; - tyconRefRemap : TyconRefRemap; - removeTraitSolutions: bool } + { tpinst : TyparInst + + /// Values to remap + valRemap: ValRemap + + /// TyconRefs to remap + tyconRefRemap : TyconRefRemap + + /// Remove existing trait solutions? + removeTraitSolutions: bool + + /// A map indicating how to fill in extSlns for traits as we copy an expression. Indexed by the member name of the trait + extSlnsMap: Map } static member Empty : Remap @@ -356,6 +367,7 @@ val instType : TyparInst -> TType -> TType val instTypes : TyparInst -> TypeInst -> TypeInst val instTyparConstraints : TyparInst -> TyparConstraint list -> TyparConstraint list val instTrait : TyparInst -> TraitConstraintInfo -> TraitConstraintInfo +val instValRef : TyparInst -> ValRef -> ValRef //------------------------------------------------------------------------- // From typars to types @@ -998,6 +1010,9 @@ type TypeDefMetadata = #endif val metadataOfTycon : Tycon -> TypeDefMetadata +#if EXTENSIONTYPING +val extensionInfoOfTy : TcGlobals -> TType -> TyconRepresentation +#endif val metadataOfTy : TcGlobals -> TType -> TypeDefMetadata val isStringTy : TcGlobals -> TType -> bool diff --git a/src/fsharp/TastPickle.fs b/src/fsharp/TastPickle.fs index 18307ce1559..791cfe04f5e 100755 --- a/src/fsharp/TastPickle.fs +++ b/src/fsharp/TastPickle.fs @@ -1370,7 +1370,8 @@ let p_trait_sln sln st = | FSRecdFieldSln(a,b,c) -> p_byte 4 st; p_tup3 p_typs p_rfref p_bool (a,b,c) st -let p_trait (TTrait(a,b,c,d,e,f)) st = +let p_trait (TTrait(a, b, c, d, e, f, _extSlns, _ad)) st = + // The _extSlns do not get pickled. We are assuming this is a generic or solved constraint p_tup6 p_typs p_string p_MemberFlags p_typs (p_option p_typ) (p_option p_trait_sln) (a,b,c,d,e,!f) st // We have to store trait solutions since they can occur in optimization data @@ -1394,7 +1395,8 @@ let u_trait_sln st = let u_trait st = let a,b,c,d,e,f = u_tup6 u_typs u_string u_MemberFlags u_typs (u_option u_typ) (u_option u_trait_sln) st - TTrait (a,b,c,d,e,ref f) + // extSlns starts empty. TODO: check the ramifications of this when inlining solved trait calls from other assemblies + TTrait (a, b, c, d, e, ref f, [], None) let p_rational q st = p_int32 (GetNumerator q) st; p_int32 (GetDenominator q) st diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index c193ce6fc86..3a48afcf4bd 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -240,7 +240,7 @@ type UngeneralizableItem(computeFreeTyvars : (unit -> FreeTyvars)) = [] type TcEnv = { /// Name resolution information - eNameResEnv : NameResolutionEnv + eNameEnv : NameResolutionEnv /// The list of items in the environment that may contain free inference /// variables (which may not be generalized). The relevant types may @@ -263,6 +263,7 @@ type TcEnv = ePath: Ident list eCompPath: CompilationPath eAccessPath: CompilationPath + /// This field is computed from other fields, but we amortize the cost of computing it. eAccessRights: AccessorDomain @@ -284,17 +285,19 @@ type TcEnv = eCallerMemberName : string option } - member tenv.DisplayEnv = tenv.eNameResEnv.DisplayEnv - member tenv.NameEnv = tenv.eNameResEnv + member tenv.DisplayEnv = tenv.eNameEnv.DisplayEnv + member tenv.NameEnv = tenv.eNameEnv member tenv.AccessRights = tenv.eAccessRights + member tenv.TraitFreshner = Some (GetTraitFreshner tenv.AccessRights tenv.NameEnv) + /// Compute the value of this computed, cached field let computeAccessRights eAccessPath eInternalsVisibleCompPaths eFamilyType = - AccessibleFrom (eAccessPath :: eInternalsVisibleCompPaths, eFamilyType) // env.eAccessRights + AccessibleFrom (eAccessPath :: eInternalsVisibleCompPaths, eFamilyType) // env.AccessRights let emptyTcEnv g = let cpath = compPathInternal // allow internal access initially - { eNameResEnv = NameResolutionEnv.Empty g + { eNameEnv = NameResolutionEnv.Empty g eUngeneralizableItems = [] ePath = [] eCompPath = cpath // dummy @@ -384,7 +387,7 @@ let addInternalsAccessibility env (ccu:CcuThunk) = eAccessRights = computeAccessRights env.eAccessPath eInternalsVisibleCompPaths env.eFamilyType // update this computed field eInternalsVisibleCompPaths = compPath :: env.eInternalsVisibleCompPaths } -let ModifyNameResEnv f env = { env with eNameResEnv = f env.eNameResEnv } +let ModifyNameResEnv f env = { env with eNameEnv = f env.NameEnv } let AddLocalValPrimitive (v:Val) env = let env = ModifyNameResEnv (fun nenv -> AddValRefToNameEnv nenv (mkLocalValRef v)) env @@ -398,7 +401,7 @@ let AddLocalValMap tcSink scopem (vals:Val NameMap) env = else let env = ModifyNameResEnv (AddValMapToNameEnv vals) env { env with eUngeneralizableItems = NameMap.foldBackRange (typeOfVal >> addFreeItemOfTy) vals env.eUngeneralizableItems } - CallEnvSink tcSink (scopem, env.NameEnv, env.eAccessRights) + CallEnvSink tcSink (scopem, env.NameEnv, env.AccessRights) env let AddLocalVals tcSink scopem (vals:Val list) env = @@ -408,20 +411,20 @@ let AddLocalVals tcSink scopem (vals:Val list) env = else let env = ModifyNameResEnv (AddValListToNameEnv vals) env { env with eUngeneralizableItems = List.foldBack (typeOfVal >> addFreeItemOfTy) vals env.eUngeneralizableItems } - CallEnvSink tcSink (scopem, env.NameEnv, env.eAccessRights) + CallEnvSink tcSink (scopem, env.NameEnv, env.AccessRights) env let AddLocalVal tcSink scopem v env = let env = ModifyNameResEnv (fun nenv -> AddValRefToNameEnv nenv (mkLocalValRef v)) env let env = {env with eUngeneralizableItems = addFreeItemOfTy v.Type env.eUngeneralizableItems } - CallEnvSink tcSink (scopem, env.NameEnv, env.eAccessRights) + CallEnvSink tcSink (scopem, env.NameEnv, env.AccessRights) env let AddLocalExnDefnAndReport tcSink scopem env (exnc:Tycon) = let env = ModifyNameResEnv (fun nenv -> AddExceptionDeclsToNameEnv BulkAdd.No nenv (mkLocalEntityRef exnc)) env (* Also make VisualStudio think there is an identifier in scope at the range of the identifier text of its binding location *) - CallEnvSink tcSink (exnc.Range, env.NameEnv, env.eAccessRights) - CallEnvSink tcSink (scopem, env.NameEnv, env.eAccessRights) + CallEnvSink tcSink (exnc.Range, env.NameEnv, env.AccessRights) + CallEnvSink tcSink (scopem, env.NameEnv, env.AccessRights) env let AddLocalTyconRefs ownDefinition g amap m tcrefs env = @@ -434,7 +437,7 @@ let AddLocalTycons g amap m (tycons: Tycon list) env = let AddLocalTyconsAndReport tcSink scopem g amap m tycons env = let env = AddLocalTycons g amap m tycons env - CallEnvSink tcSink (scopem, env.NameEnv, env.eAccessRights) + CallEnvSink tcSink (scopem, env.NameEnv, env.AccessRights) env //------------------------------------------------------------------------- @@ -444,8 +447,8 @@ let AddLocalTyconsAndReport tcSink scopem g amap m tycons env = let OpenModulesOrNamespaces tcSink g amap scopem root env mvvs openDeclaration = let env = if isNil mvvs then env else - ModifyNameResEnv (fun nenv -> AddModulesAndNamespacesContentsToNameEnv g amap env.eAccessRights scopem root nenv mvvs) env - CallEnvSink tcSink (scopem, env.NameEnv, env.eAccessRights) + ModifyNameResEnv (fun nenv -> AddModulesAndNamespacesContentsToNameEnv g amap env.AccessRights scopem root nenv mvvs) env + CallEnvSink tcSink (scopem, env.NameEnv, env.AccessRights) CallOpenDeclarationSink tcSink openDeclaration match openDeclaration.Range with | None -> () @@ -471,7 +474,7 @@ let OpenModulesOrNamespaces tcSink g amap scopem root env mvvs openDeclaration = let AddRootModuleOrNamespaceRefs g amap m env modrefs = if isNil modrefs then env else - ModifyNameResEnv (fun nenv -> AddModuleOrNamespaceRefsToNameEnv g amap m true env.eAccessRights nenv modrefs) env + ModifyNameResEnv (fun nenv -> AddModuleOrNamespaceRefsToNameEnv g amap m true env.AccessRights nenv modrefs) env let AddNonLocalCcu g amap scopem env assemblyName (ccu:CcuThunk, internalsVisibleToAttributes) = @@ -493,7 +496,7 @@ let AddNonLocalCcu g amap scopem env assemblyName (ccu:CcuThunk, internalsVisib let env = if isNil tcrefs then env else ModifyNameResEnv (fun nenv -> AddTyconRefsToNameEnv BulkAdd.Yes false g amap scopem true nenv tcrefs) env - //CallEnvSink tcSink (scopem, env.NameEnv, env.eAccessRights) + //CallEnvSink tcSink (scopem, env.NameEnv, env.AccessRights) env let AddLocalRootModuleOrNamespace tcSink g amap scopem env (mtyp:ModuleOrNamespaceType) = @@ -506,16 +509,16 @@ let AddLocalRootModuleOrNamespace tcSink g amap scopem env (mtyp:ModuleOrNamespa if isNil tcrefs then env else ModifyNameResEnv (fun nenv -> AddTyconRefsToNameEnv BulkAdd.No false g amap scopem true nenv tcrefs) env let env = { env with eUngeneralizableItems = addFreeItemOfModuleTy mtyp env.eUngeneralizableItems } - CallEnvSink tcSink (scopem, env.NameEnv, env.eAccessRights) + CallEnvSink tcSink (scopem, env.NameEnv, env.AccessRights) env let AddModuleAbbreviationAndReport tcSink scopem id modrefs env = let env = if isNil modrefs then env else ModifyNameResEnv (fun nenv -> AddModuleAbbrevToNameEnv id nenv modrefs) env - CallEnvSink tcSink (scopem, env.NameEnv, env.eAccessRights) + CallEnvSink tcSink (scopem, env.NameEnv, env.AccessRights) let item = Item.ModuleOrNamespaces modrefs - CallNameResolutionSink tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.AccessRights) env let AddLocalSubModule g amap m env (modul:ModuleOrNamespace) = @@ -525,7 +528,7 @@ let AddLocalSubModule g amap m env (modul:ModuleOrNamespace) = let AddLocalSubModuleAndReport tcSink scopem g amap m env (modul:ModuleOrNamespace) = let env = AddLocalSubModule g amap m env modul - CallEnvSink tcSink (scopem, env.NameEnv, env.eAccessRights) + CallEnvSink tcSink (scopem, env.NameEnv, env.AccessRights) env let RegisterDeclaredTypars typars env = @@ -591,7 +594,7 @@ type cenv = static member Create (g, isScript, niceNameGen, amap, topCcu, isSig, haveSig, conditionalDefines, tcSink, tcVal) = let infoReader = new InfoReader(g, amap) - let instantiationGenerator m tpsorig = ConstraintSolver.FreshenTypars m tpsorig + let instantiationGenerator m tpsorig = ConstraintSolver.FreshenTypars None m tpsorig // TODO: check 'None' here for env.TraitFreshner let nameResolver = new NameResolver(g, amap, infoReader, instantiationGenerator) { g = g amap = amap @@ -611,8 +614,8 @@ type cenv = compilingCanonicalFslibModuleType = (isSig || not haveSig) && g.compilingFslib conditionalDefines = conditionalDefines } -let CopyAndFixupTypars m rigid tpsorig = - ConstraintSolver.FreshenAndFixupTypars m rigid [] [] tpsorig +let CopyAndFixupTypars traitFreshner m rigid tpsorig = + ConstraintSolver.FreshenAndFixupTypars traitFreshner m rigid [] [] tpsorig let UnifyTypes cenv (env: TcEnv) m expectedTy actualTy = ConstraintSolver.AddCxTypeEqualsType env.eContextInfo env.DisplayEnv cenv.css m (tryNormalizeMeasureInType cenv.g expectedTy) (tryNormalizeMeasureInType cenv.g actualTy) @@ -635,7 +638,7 @@ let MakeInnerEnvWithAcc env nm mtypeAcc modKind = eCompPath = cpath eAccessPath = cpath eAccessRights = computeAccessRights cpath env.eInternalsVisibleCompPaths env.eFamilyType // update this computed field - eNameResEnv = { env.eNameResEnv with eDisplayEnv = env.DisplayEnv.AddOpenPath (pathOfLid path) } + eNameEnv = { env.NameEnv with eDisplayEnv = env.DisplayEnv.AddOpenPath (pathOfLid path) } eModuleOrNamespaceTypeAccumulator = mtypeAcc } let MakeInnerEnv env nm modKind = @@ -711,7 +714,7 @@ let ImplicitlyOpenOwnNamespace tcSink g amap scopem enclosingNamespacePath env = | None -> enclosingNamespacePath let ad = env.eAccessRights - match ResolveLongIndentAsModuleOrNamespace ResultCollectionSettings.AllResults amap scopem OpenQualified env.eNameResEnv ad enclosingNamespacePathToOpen with + match ResolveLongIndentAsModuleOrNamespace ResultCollectionSettings.AllResults amap scopem OpenQualified env.eNameEnv ad enclosingNamespacePathToOpen with | Result modrefs -> let modrefs = List.map p23 modrefs let openDecl = OpenDeclaration.Create (enclosingNamespacePathToOpen, modrefs, scopem, true) @@ -879,7 +882,7 @@ module AttributeTargets = let ForNewConstructors tcSink (env:TcEnv) mObjTy methodName meths = let origItem = Item.CtorGroup(methodName, meths) - let callSink (item, minst) = CallNameResolutionSink tcSink (mObjTy, env.NameEnv, item, origItem, minst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) + let callSink (item, minst) = CallNameResolutionSink tcSink (mObjTy, env.NameEnv, item, origItem, minst, ItemOccurence.Use, env.DisplayEnv, env.AccessRights) let sendToSink minst refinedMeths = callSink (Item.CtorGroup(methodName, refinedMeths), minst) match meths with | [] -> @@ -905,7 +908,7 @@ let TcConst cenv ty m env c = | SynMeasure.One -> Measure.One | SynMeasure.Named(tc, m) -> let ad = env.eAccessRights - let tcref = ForceRaise(ResolveTypeLongIdent cenv.tcSink cenv.nameResolver ItemOccurence.Use OpenQualified env.eNameResEnv ad tc TypeNameResolutionStaticArgsInfo.DefiniteEmpty PermitDirectReferenceToGeneratedType.No) + let tcref = ForceRaise(ResolveTypeLongIdent cenv.tcSink cenv.nameResolver ItemOccurence.Use OpenQualified env.eNameEnv ad tc TypeNameResolutionStaticArgsInfo.DefiniteEmpty PermitDirectReferenceToGeneratedType.No) match tcref.TypeOrMeasureKind with | TyparKind.Type -> error(Error(FSComp.SR.tcExpectedUnitOfMeasureNotType(), m)) | TyparKind.Measure -> Measure.Con tcref @@ -1099,9 +1102,6 @@ let MakeMemberDataAndMangledNameForMemberVal(g, tcref, isExtrinsic, attrs, optIm if n<>3 && opTakesThreeArgs then warning(Error(FSComp.SR.memberOperatorDefinitionWithNonTripleArgument(name, n), m)) if not (isNil otherArgs) then warning(Error(FSComp.SR.memberOperatorDefinitionWithCurriedArguments(name), m)) - if isExtrinsic && IsMangledOpName id.idText then - warning(Error(FSComp.SR.tcMemberOperatorDefinitionInExtrinsic(), id.idRange)) - ValMemberInfoTransient(memberInfo, logicalName, compiledName) @@ -1330,7 +1330,7 @@ let PublishModuleDefn cenv env mspec = if intoFslibCcu then mty else mty.AddEntity mspec) let item = Item.ModuleOrNamespaces([mkLocalModRef mspec]) - CallNameResolutionSink cenv.tcSink (mspec.Range, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Binding, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (mspec.Range, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Binding, env.DisplayEnv, env.AccessRights) let PublishTypeDefn cenv env tycon = UpdateAccModuleOrNamespaceType cenv env (fun _ mty -> @@ -1553,9 +1553,9 @@ let MakeAndPublishVal cenv env (altActualParent, inSig, declKind, vrec, (ValSche | None when vspec.BaseOrThisInfo = ValBaseOrThisInfo.MemberThisVal && vspec.LogicalName = "__" -> () | _ -> let nenv = AddFakeNamedValRefToNameEnv vspec.DisplayName env.NameEnv (mkLocalValRef vspec) - CallEnvSink cenv.tcSink (vspec.Range, nenv, env.eAccessRights) + CallEnvSink cenv.tcSink (vspec.Range, nenv, env.AccessRights) let item = Item.Value(mkLocalValRef vspec) - CallNameResolutionSink cenv.tcSink (vspec.Range, nenv, item, item, emptyTyparInst, ItemOccurence.Binding, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (vspec.Range, nenv, item, item, emptyTyparInst, ItemOccurence.Binding, env.DisplayEnv, env.AccessRights) vspec let MakeAndPublishVals cenv env (altActualParent, inSig, declKind, vrec, valSchemes, attrs, doc, konst) = @@ -1925,33 +1925,33 @@ let MakeAndPublishSimpleVals cenv env m names mergeNamesInOneNameresEnv = // to C<_> occurs then generate C for a fresh type inference variable ?ty. //------------------------------------------------------------------------- -let FreshenTyconRef m rigid (tcref:TyconRef) declaredTyconTypars = +let FreshenTyconRef traitFreshner m rigid (tcref:TyconRef) declaredTyconTypars = let tpsorig = declaredTyconTypars let tps = copyTypars tpsorig if rigid <> TyparRigidity.Rigid then tps |> List.iter (fun tp -> tp.SetRigidity rigid) - let renaming, tinst = FixupNewTypars m [] [] tpsorig tps + let renaming, tinst = FixupNewTypars traitFreshner m [] [] tpsorig tps (TType_app(tcref, List.map mkTyparTy tpsorig), tps, renaming, TType_app(tcref, tinst)) -let FreshenPossibleForallTy g m rigid ty = +let FreshenPossibleForallTy traitFreshner g m rigid ty = let tpsorig, tau = tryDestForallTy g ty if isNil tpsorig then [], [], [], tau else // tps may be have been equated to other tps in equi-recursive type inference and units-of-measure type inference. Normalize them here let tpsorig = NormalizeDeclaredTyparsForEquiRecursiveInference g tpsorig - let tps, renaming, tinst = CopyAndFixupTypars m rigid tpsorig + let tps, renaming, tinst = CopyAndFixupTypars traitFreshner m rigid tpsorig tpsorig, tps, tinst, instType renaming tau -let infoOfTyconRef m (tcref:TyconRef) = - let tps, renaming, tinst = FreshenTypeInst m (tcref.Typars m) +let FreshenTyconRef2 traitFreshner m (tcref:TyconRef) = + let tps, renaming, tinst = FreshenTypeInst traitFreshner m (tcref.Typars m) tps, renaming, tinst, TType_app (tcref, tinst) /// Given a abstract method, which may be a generic method, freshen the type in preparation /// to apply it as a constraint to the method that implements the abstract slot -let FreshenAbstractSlot g amap m synTyparDecls absMethInfo = +let FreshenAbstractSlot traitFreshner g amap m synTyparDecls absMethInfo = // Work out if an explicit instantiation has been given. If so then the explicit type // parameters will be made rigid and checked for generalization. If not then auto-generalize @@ -1973,7 +1973,7 @@ let FreshenAbstractSlot g amap m synTyparDecls absMethInfo = let ttps = absMethInfo.GetFormalTyparsOfDeclaringType m let ttinst = argsOfAppTy g absMethInfo.EnclosingType let rigid = if typarsFromAbsSlotAreRigid then TyparRigidity.Rigid else TyparRigidity.Flexible - ConstraintSolver.FreshenAndFixupTypars m rigid ttps ttinst fmtps + ConstraintSolver.FreshenAndFixupTypars traitFreshner m rigid ttps ttinst fmtps // Work out the required type of the member let argTysFromAbsSlot = argtys |> List.mapSquared (instType typarInstFromAbsSlot) @@ -1993,7 +1993,7 @@ let BuildFieldMap cenv env isPartial ty flds m = let allFields = flds |> List.map (fun ((_, ident), _) -> ident) flds |> List.map (fun (fld, fldExpr) -> - let frefSet = ResolveField cenv.tcSink cenv.nameResolver env.eNameResEnv ad ty fld allFields + let frefSet = ResolveField cenv.tcSink cenv.nameResolver env.eNameEnv ad ty fld allFields fld, frefSet, fldExpr) let relevantTypeSets = @@ -2024,7 +2024,7 @@ let BuildFieldMap cenv env isPartial ty flds m = // Record the precise resolution of the field for intellisense let item = FreshenRecdFieldRef cenv.nameResolver m fref2 - CallNameResolutionSink cenv.tcSink ((snd fld).idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, ad) + CallNameResolutionSink cenv.tcSink ((snd fld).idRange, env.eNameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, ad) CheckRecdFieldAccessible cenv.amap m env.eAccessRights fref2 |> ignore CheckFSharpAttributes cenv.g fref2.PropertyAttribs m |> CommitOperationResult @@ -2080,9 +2080,9 @@ let UnionCaseOrExnCheck (env: TcEnv) nargtys nargs m = if nargs <> nargtys then error (UnionCaseWrongArguments(env.DisplayEnv, nargtys, nargs, m)) let TcUnionCaseOrExnField cenv (env: TcEnv) ty1 m c n funcs = - let ad = env.eAccessRights + let ad = env.AccessRights let mkf, argtys, _argNames = - match ResolvePatternLongIdent cenv.tcSink cenv.nameResolver AllIdsOK false m ad env.eNameResEnv TypeNameResolutionInfo.Default c with + match ResolvePatternLongIdent cenv.tcSink cenv.nameResolver AllIdsOK false m ad env.NameEnv TypeNameResolutionInfo.Default c with | (Item.UnionCase _ | Item.ExnCase _) as item -> ApplyUnionCaseOrExn funcs m cenv env ty1 item | _ -> error(Error(FSComp.SR.tcUnknownUnion(), m)) @@ -2131,24 +2131,24 @@ module GeneralizationHelpers = let ComputeUnabstractableTycons env = - let acc_in_free_item acc (item: UngeneralizableItem) = + let accInFreeItem acc (item: UngeneralizableItem) = let ftycs = if item.WillNeverHaveFreeTypars then item.CachedFreeLocalTycons else let ftyvs = item.GetFreeTyvars() ftyvs.FreeTycons if ftycs.IsEmpty then acc else unionFreeTycons ftycs acc - List.fold acc_in_free_item emptyFreeTycons env.eUngeneralizableItems + List.fold accInFreeItem emptyFreeTycons env.eUngeneralizableItems let ComputeUnabstractableTraitSolutions env = - let acc_in_free_item acc (item: UngeneralizableItem) = + let accInFreeItem acc (item: UngeneralizableItem) = let ftycs = if item.WillNeverHaveFreeTypars then item.CachedFreeTraitSolutions else let ftyvs = item.GetFreeTyvars() ftyvs.FreeTraitSolutions if ftycs.IsEmpty then acc else unionFreeLocals ftycs acc - List.fold acc_in_free_item emptyFreeLocals env.eUngeneralizableItems + List.fold accInFreeItem emptyFreeLocals env.eUngeneralizableItems let rec IsGeneralizableValue g t = match t with @@ -2296,17 +2296,17 @@ module GeneralizationHelpers = (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) |> RaiseOperationResult - let ComputeAndGeneralizeGenericTypars (cenv, - denv:DisplayEnv, - m, - freeInEnv:FreeTypars, - canInferTypars, - genConstrainedTyparFlag, - inlineFlag, - exprOpt, - allDeclaredTypars: Typars, - maxInferredTypars: Typars, - tauTy, + let ComputeAndGeneralizeGenericTypars (cenv, + denv:DisplayEnv, + m, + freeInEnv:FreeTypars, + canInferTypars, + genConstrainedTyparFlag, + inlineFlag, + exprOpt, + allDeclaredTypars:Typars, + maxInferredTypars:Typars, + tauTy, resultFirst) = let allDeclaredTypars = NormalizeDeclaredTyparsForEquiRecursiveInference cenv.g allDeclaredTypars @@ -2539,7 +2539,7 @@ module BindingNormalization = | _ -> MakeNormalizedInstanceMemberBinding cenv thisId memberId toolId vis m typars args rhsExpr valSynData let private NormalizeBindingPattern cenv nameResolver isObjExprBinding (env: TcEnv) valSynData pat rhsExpr = - let ad = env.eAccessRights + let ad = env.AccessRights let (SynValData(memberFlagsOpt, _, _)) = valSynData let rec normPattern pat = // One major problem with versions of F# prior to 1.9.x was that data constructors easily 'pollute' the namespace @@ -2550,7 +2550,7 @@ module BindingNormalization = let typars = match tyargs with None -> inferredTyparDecls | Some typars -> typars match memberFlagsOpt with | None -> - match ResolvePatternLongIdent cenv.tcSink nameResolver AllIdsOK true m ad env.eNameResEnv TypeNameResolutionInfo.Default longId with + match ResolvePatternLongIdent cenv.tcSink nameResolver AllIdsOK true m ad env.NameEnv TypeNameResolutionInfo.Default longId with | Item.NewDef id -> if id.idText = opNameCons then NormalizedBindingPat(pat, rhsExpr, valSynData, typars) @@ -2682,11 +2682,11 @@ module EventDeclarationNormalization = /// Make a copy of the "this" type for a generic object type, e.g. List<'T> --> List<'?> for a fresh inference variable. /// Also adjust the "this" type to take into account whether the type is a struct. -let FreshenObjectArgType cenv m rigid tcref isExtrinsic declaredTyconTypars = +let FreshenObjectArgType cenv traitFreshner m rigid tcref isExtrinsic declaredTyconTypars = #if EXTENDED_EXTENSION_MEMBERS // indicates if extension members can add additional constraints to type parameters let tcrefObjTy, enclosingDeclaredTypars, renaming, objTy = FreshenTyconRef m (if isExtrinsic then TyparRigidity.Flexible else rigid) tcref declaredTyconTypars #else - let tcrefObjTy, enclosingDeclaredTypars, renaming, objTy = FreshenTyconRef m rigid tcref declaredTyconTypars + let tcrefObjTy, enclosingDeclaredTypars, renaming, objTy = FreshenTyconRef traitFreshner m rigid tcref declaredTyconTypars #endif // Struct members have a byref 'this' type (unless they are extrinsic extension members) let thisTy = @@ -2753,7 +2753,7 @@ let TcValEarlyGeneralizationConsistencyCheck cenv (env:TcEnv) (v:Val, vrec, tins /// | CtorValUsedAsSuperInit "inherit Panel()" /// | CtorValUsedAsSelfInit "new() = new OwnType(3)" /// | VSlotDirectCall "base.OnClick(eventArgs)" -let TcVal checkAttributes cenv env tpenv (vref:ValRef) optInst optAfterResolution m = +let TcVal traitFreshner checkAttributes cenv env tpenv (vref:ValRef) optInst optAfterResolution m = let (tpsorig, _, _, _, tinst, _) as res = let v = vref.Deref let vrec = v.RecursiveValInfo @@ -2774,7 +2774,7 @@ let TcVal checkAttributes cenv env tpenv (vref:ValRef) optInst optAfterResolutio // The value may still be generic, e.g. // [] // let Null = null - let tpsorig, _, tinst, tau = FreshenPossibleForallTy cenv.g m TyparRigidity.Flexible vty + let tpsorig, _, tinst, tau = FreshenPossibleForallTy traitFreshner cenv.g m TyparRigidity.Flexible vty tpsorig, Expr.Const(c, m, tau), isSpecial, tau, tinst, tpenv | None -> @@ -2804,8 +2804,8 @@ let TcVal checkAttributes cenv env tpenv (vref:ValRef) optInst optAfterResolutio tpsorig, NormalValUse, tinst, tau, tpenv | ValInRecScope true | ValNotInRecScope -> - let tpsorig, _, tinst, tau = FreshenPossibleForallTy cenv.g m TyparRigidity.Flexible vty - tpsorig, NormalValUse, tinst, tau, tpenv + let tpsorig, _, tptys, tau = FreshenPossibleForallTy traitFreshner cenv.g m TyparRigidity.Flexible vty + tpsorig, NormalValUse, tptys, tau, tpenv // If we have got an explicit instantiation then use that | Some(vrefFlags, checkTys) -> @@ -2825,7 +2825,7 @@ let TcVal checkAttributes cenv env tpenv (vref:ValRef) optInst optAfterResolutio tpsorig, vrefFlags, tinst, tau2, tpenv | ValInRecScope true | ValNotInRecScope -> - let tpsorig, tps, tptys, tau = FreshenPossibleForallTy cenv.g m TyparRigidity.Flexible vty + let tpsorig, tps, tptys, tau = FreshenPossibleForallTy traitFreshner cenv.g m TyparRigidity.Flexible vty //dprintfn "After Freshen: tau = %s" (Layout.showL (typeL tau)) let (tinst:TypeInst), tpenv = checkTys tpenv (tps |> List.map (fun tp -> tp.Kind)) checkInst tinst @@ -2835,7 +2835,7 @@ let TcVal checkAttributes cenv env tpenv (vref:ValRef) optInst optAfterResolutio TcValEarlyGeneralizationConsistencyCheck cenv env (v, vrec, tinst, vty, tau, m) //dprintfn "After Unify: tau = %s" (Layout.showL (typeL tau)) - tpsorig, vrefFlags, tinst, tau, tpenv + tpsorig, vrefFlags, tptys, tau, tpenv let exprForVal = Expr.Val (vref, vrefFlags, m) let exprForVal = mkTyAppExpr m (exprForVal, vty) tinst @@ -2864,13 +2864,13 @@ let LightweightTcValForUsingInBuildMethodCall g (vref:ValRef) vrefFlags (vrefTyp else match v.LiteralValue with | Some c -> - let _, _, _, tau = FreshenPossibleForallTy g m TyparRigidity.Flexible vty + let _, _, _, tau = FreshenPossibleForallTy None g m TyparRigidity.Flexible vty Expr.Const(c, m, tau), tau | None -> // Instantiate the value let tau = // If we have got an explicit instantiation then use that - let _, tps, tptys, tau = FreshenPossibleForallTy g m TyparRigidity.Flexible vty + let _, tps, tptys, tau = FreshenPossibleForallTy None g m TyparRigidity.Flexible vty if tptys.Length <> vrefTypeInst.Length then error(Error(FSComp.SR.tcTypeParameterArityMismatch(tps.Length, vrefTypeInst.Length), m)); instType (mkTyparInst tps vrefTypeInst) tau @@ -3043,7 +3043,7 @@ let BuildPossiblyConditionalMethodCall cenv env isMutable m isProp minfo valUseF | _ -> #endif let tcVal valref valUse ttypes m = - let _, a, _, b, _, _ = TcVal true cenv env emptyUnscopedTyparEnv valref (Some (valUse, (fun x _ -> ttypes, x))) None m + let _, a, _, b, _, _ = TcVal env.TraitFreshner true cenv env emptyUnscopedTyparEnv valref (Some (valUse, (fun x _ -> ttypes, x))) None m a, b BuildMethodCall tcVal cenv.g cenv.amap isMutable m isProp minfo valUseFlags minst objArgs args @@ -3169,7 +3169,7 @@ let (|JoinRelation|_|) cenv env (e:SynExpr) = let isOpName opName vref s = (s = opName) && - match ResolveExprLongIdent cenv.tcSink cenv.nameResolver m ad env.eNameResEnv TypeNameResolutionInfo.Default [ident(opName, m)] with + match ResolveExprLongIdent cenv.tcSink cenv.nameResolver m ad env.eNameEnv TypeNameResolutionInfo.Default [ident(opName, m)] with | Item.Value vref2, [] -> valRefEq cenv.g vref vref2 | _ -> false @@ -3261,7 +3261,7 @@ let CompilePatternForMatchClauses cenv env mExpr matchm warnOnUnused actionOnFai // localAlloc is relevant if the enumerator is a mutable struct and indicates // if the enumerator can be allocated as a mutable local variable let AnalyzeArbitraryExprAsEnumerable cenv (env: TcEnv) localAlloc m exprty expr = - let ad = env.eAccessRights + let ad = env.AccessRights let err k ty = let txt = NicePrint.minimalStringOfType env.DisplayEnv ty @@ -3285,7 +3285,7 @@ let AnalyzeArbitraryExprAsEnumerable cenv (env: TcEnv) localAlloc m exprty expr | Exception e -> Exception e | Result getEnumerator_minfo -> - let getEnumerator_minst = FreshenMethInfo m getEnumerator_minfo + let getEnumerator_minst = FreshenMethInfo env.TraitFreshner m getEnumerator_minfo let retTypeOfGetEnumerator = getEnumerator_minfo.GetFSharpReturnTy(cenv.amap, m, getEnumerator_minst) if hasArgs getEnumerator_minfo getEnumerator_minst then err true tyToSearchForGetEnumeratorAndItem else @@ -3293,7 +3293,7 @@ let AnalyzeArbitraryExprAsEnumerable cenv (env: TcEnv) localAlloc m exprty expr | Exception e -> Exception e | Result moveNext_minfo -> - let moveNext_minst = FreshenMethInfo m moveNext_minfo + let moveNext_minst = FreshenMethInfo env.TraitFreshner m moveNext_minfo let retTypeOfMoveNext = moveNext_minfo.GetFSharpReturnTy(cenv.amap, m, moveNext_minst) if not (typeEquiv cenv.g cenv.g.bool_ty retTypeOfMoveNext) then err false retTypeOfGetEnumerator else if hasArgs moveNext_minfo moveNext_minst then err false retTypeOfGetEnumerator else @@ -3302,7 +3302,7 @@ let AnalyzeArbitraryExprAsEnumerable cenv (env: TcEnv) localAlloc m exprty expr | Exception e -> Exception e | Result get_Current_minfo -> - let get_Current_minst = FreshenMethInfo m get_Current_minfo + let get_Current_minst = FreshenMethInfo env.TraitFreshner m get_Current_minfo if hasArgs get_Current_minfo get_Current_minst then err false retTypeOfGetEnumerator else let enumElemTy = get_Current_minfo.GetFSharpReturnTy(cenv.amap, m, get_Current_minst) @@ -4261,7 +4261,7 @@ let rec TcTyparConstraint ridx cenv newOk checkCxs occ (env: TcEnv) tpenv c = | WhereTyparSupportsMember(tps, memSpfn, m) -> let traitInfo, tpenv = TcPseudoMemberSpec cenv newOk env tps tpenv memSpfn m match traitInfo with - | TTrait(objtys, ".ctor", memberFlags, argtys, returnTy, _) when memberFlags.MemberKind = MemberKind.Constructor -> + | TTrait(objtys, ".ctor", memberFlags, argtys, returnTy, _, _, _) when memberFlags.MemberKind = MemberKind.Constructor -> match objtys, argtys with | [ty], [] when typeEquiv cenv.g ty (GetFSharpViewOfReturnType cenv.g returnTy) -> AddCxTypeMustSupportDefaultCtor env.DisplayEnv cenv.css m NoTrace ty @@ -4295,10 +4295,14 @@ and TcPseudoMemberSpec cenv newOk env synTypes tpenv memSpfn m = let logicalCompiledName = ComputeLogicalName id memberFlags let item = Item.ArgName (id, memberConstraintTy, None) - CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.AccessRights) + + // extSlns starts off empty because the trait has some support + // ad starts off as None because the trait has some support + TTrait(tys, logicalCompiledName, memberFlags, argtys, returnTy, ref None, [], None), tpenv - TTrait(tys, logicalCompiledName, memberFlags, argtys, returnTy, ref None), tpenv | _ -> error(Error(FSComp.SR.tcInvalidConstraint(), m)) + | _ -> error(Error(FSComp.SR.tcInvalidConstraint(), m)) @@ -4311,7 +4315,7 @@ and TcValSpec cenv env declKind newOk containerInfo memFlagsOpt thisTyOpt tpenv match tcrefContainerInfo with | Some(MemberOrValContainerInfo(tcref, _, _, _, declaredTyconTypars)) -> let isExtrinsic = (declKind = ExtrinsicExtensionBinding) - let _, enclosingDeclaredTypars, _, _, thisTy = FreshenObjectArgType cenv m TyparRigidity.Rigid tcref isExtrinsic declaredTyconTypars + let _, enclosingDeclaredTypars, _, _, thisTy = FreshenObjectArgType cenv env.TraitFreshner m TyparRigidity.Rigid tcref isExtrinsic declaredTyconTypars // An implemented interface type is in terms of the type's type parameters. // We need a signature in terms of the values' type parameters. // let optIntfSlotTy = Option.map (instType renaming) optIntfSlotTy in @@ -4456,12 +4460,12 @@ and TcTyparOrMeasurePar optKind cenv (env:TcEnv) newOk tpenv (Typar(id, _, _) as | Some TyparKind.Type, TyparKind.Measure -> error (Error(FSComp.SR.tcExpectedTypeParameter(), id.idRange)); res, tpenv | _, _ -> let item = Item.TypeVar(id.idText, res) - CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.UseInType, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.UseInType, env.DisplayEnv, env.AccessRights) // record the ' as well for tokenization - // CallNameResolutionSink cenv.tcSink (tp.Range.StartRange, env.NameEnv, item, item, ItemOccurence.UseInType, env.DisplayEnv, env.eAccessRights) + // CallNameResolutionSink cenv.tcSink (tp.Range.StartRange, env.NameEnv, item, item, ItemOccurence.UseInType, env.DisplayEnv, env.AccessRights) res, tpenv let key = id.idText - match env.eNameResEnv.eTypars.TryFind key with + match env.NameEnv.eTypars.TryFind key with | Some res -> checkRes res | None -> match TryFindUnscopedTypar key tpenv with @@ -4470,7 +4474,7 @@ and TcTyparOrMeasurePar optKind cenv (env:TcEnv) newOk tpenv (Typar(id, _, _) as if newOk = NoNewTypars then let predictTypeParameters() = let predictions1 = - env.eNameResEnv.eTypars + env.NameEnv.eTypars |> Seq.map (fun p -> "'" + p.Key) let predictions2 = @@ -4490,7 +4494,7 @@ and TcTyparOrMeasurePar optKind cenv (env:TcEnv) newOk tpenv (Typar(id, _, _) as // The kind defaults to Type let tp' = NewTypar ((match optKind with None -> TyparKind.Type | Some kind -> kind), TyparRigidity.WarnIfNotRigid, tp, false, TyparDynamicReq.Yes, [], false, false) let item = Item.TypeVar(id.idText, tp') - CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.UseInType, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.UseInType, env.DisplayEnv, env.AccessRights) tp', AddUnscopedTypar key tp' tpenv and TcTypar cenv env newOk tpenv tp = @@ -4509,7 +4513,7 @@ and TcTyparDecl cenv env (TyparDecl(synAttrs, (Typar(id, _, _) as stp))) = | None -> () let item = Item.TypeVar(id.idText, tp) - CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.UseInType, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.UseInType, env.DisplayEnv, env.AccessRights) tp @@ -4528,7 +4532,7 @@ and TcTypeOrMeasure optKind cenv newOk checkCxs occ env (tpenv:SyntacticUnscoped | SynType.LongIdent(LongIdentWithDots(tc, _) as lidwd) -> let m = lidwd.Range let ad = env.eAccessRights - let tcref = ForceRaise(ResolveTypeLongIdent cenv.tcSink cenv.nameResolver occ OpenQualified env.eNameResEnv ad tc TypeNameResolutionStaticArgsInfo.DefiniteEmpty PermitDirectReferenceToGeneratedType.No) + let tcref = ForceRaise(ResolveTypeLongIdent cenv.tcSink cenv.nameResolver occ OpenQualified env.NameEnv ad tc TypeNameResolutionStaticArgsInfo.DefiniteEmpty PermitDirectReferenceToGeneratedType.No) match optKind, tcref.TypeOrMeasureKind with | Some TyparKind.Type, TyparKind.Measure -> error(Error(FSComp.SR.tcExpectedTypeNotUnitOfMeasure(), m)) @@ -4543,7 +4547,7 @@ and TcTypeOrMeasure optKind cenv newOk checkCxs occ env (tpenv:SyntacticUnscoped | SynType.App (SynType.LongIdent(LongIdentWithDots(tc, _)), _, args, _commas, _, postfix, m) -> let ad = env.eAccessRights - let tcref = ForceRaise(ResolveTypeLongIdent cenv.tcSink cenv.nameResolver ItemOccurence.UseInType OpenQualified env.eNameResEnv ad tc (TypeNameResolutionStaticArgsInfo.FromTyArgs args.Length) PermitDirectReferenceToGeneratedType.No) + let tcref = ForceRaise(ResolveTypeLongIdent cenv.tcSink cenv.nameResolver ItemOccurence.UseInType OpenQualified env.eNameEnv ad tc (TypeNameResolutionStaticArgsInfo.FromTyArgs args.Length) PermitDirectReferenceToGeneratedType.No) match optKind, tcref.TypeOrMeasureKind with | Some TyparKind.Type, TyparKind.Measure -> error(Error(FSComp.SR.tcExpectedTypeNotUnitOfMeasure(), m)) @@ -4570,7 +4574,7 @@ and TcTypeOrMeasure optKind cenv newOk checkCxs occ env (tpenv:SyntacticUnscoped let ltyp, tpenv = TcType cenv newOk checkCxs occ env tpenv ltyp match ltyp with | AppTy cenv.g (tcref, tinst) -> - let tcref = ResolveTypeLongIdentInTyconRef cenv.tcSink cenv.nameResolver env.eNameResEnv (TypeNameResolutionInfo.ResolveToTypeRefs (TypeNameResolutionStaticArgsInfo.FromTyArgs args.Length)) ad m tcref longId + let tcref = ResolveTypeLongIdentInTyconRef cenv.tcSink cenv.nameResolver env.eNameEnv (TypeNameResolutionInfo.ResolveToTypeRefs (TypeNameResolutionStaticArgsInfo.FromTyArgs args.Length)) ad m tcref longId TcTypeApp cenv newOk checkCxs occ env tpenv m tcref tinst args | _ -> error(Error(FSComp.SR.tcTypeHasNoNestedTypes(), m)) @@ -4740,7 +4744,7 @@ and TcStaticConstantParameter cenv (env:TcEnv) tpenv kind (v:SynType) idOpt cont match idOpt with | Some id -> let item = Item.ArgName (id, ttype, Some container) - CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.AccessRights) | _ -> () match v with @@ -4919,7 +4923,7 @@ and TcProvidedTypeApp cenv env tpenv tcref args m = /// In this case, 'args' is only the instantiation of the suffix type arguments, and pathTypeArgs gives /// the prefix of type arguments. and TcTypeApp cenv newOk checkCxs occ env tpenv m tcref pathTypeArgs (synArgTys: SynType list) = - CheckTyconAccessible cenv.amap m env.eAccessRights tcref |> ignore + CheckTyconAccessible cenv.amap m env.AccessRights tcref |> ignore CheckEntityAttributes cenv.g tcref m |> CommitOperationResult #if !NO_EXTENSIONTYPING @@ -4928,7 +4932,7 @@ and TcTypeApp cenv newOk checkCxs occ env tpenv m tcref pathTypeArgs (synArgTys: if tcref.Deref.IsProvided then TcProvidedTypeApp cenv env tpenv tcref synArgTys m else #endif - let tps, _, tinst, _ = infoOfTyconRef m tcref + let tps, _, tinst, _ = FreshenTyconRef2 env.TraitFreshner m tcref // If we're not checking constraints, i.e. when we first assert the super/interfaces of a type definition, then just // clear the constraint lists of the freshly generated type variables. A little ugly but fairly localized. @@ -4985,7 +4989,7 @@ and TcNestedTypeApplication cenv newOk checkCxs occ env tpenv mWholeTypeApp typ and TryAdjustHiddenVarNameToCompGenName cenv env (id:Ident) altNameRefCellOpt = match altNameRefCellOpt with | Some ({contents = Undecided altId } as altNameRefCell) -> - match ResolvePatternLongIdent cenv.tcSink cenv.nameResolver AllIdsOK false id.idRange env.eAccessRights env.eNameResEnv TypeNameResolutionInfo.Default [id] with + match ResolvePatternLongIdent cenv.tcSink cenv.nameResolver AllIdsOK false id.idRange env.eAccessRights env.eNameEnv TypeNameResolutionInfo.Default [id] with | Item.NewDef _ -> None // the name is not in scope as a pattern identifier (e.g. union case), so do not use the alternate ID | _ -> altNameRefCell := Decided altId; Some altId // the name is in scope as a pattern identifier, so use the alternate ID | Some ({contents = Decided altId }) -> Some altId @@ -5099,7 +5103,7 @@ and TcPatBindingName cenv env id ty isMemberThis vis1 topValData (inlineFlag, de | Some value -> let name = id.idText if not (String.IsNullOrEmpty name) && Char.IsLower(name.[0]) then - match TryFindPatternByName name env.eNameResEnv with + match TryFindPatternByName name env.NameEnv with | Some (Item.Value vref) when vref.LiteralValue.IsSome -> warning(Error(FSComp.SR.checkLowercaseLiteralBindingInPattern(id.idText), id.idRange)) | Some _ | None -> () @@ -5111,7 +5115,7 @@ and TcPatBindingName cenv env id ty isMemberThis vis1 topValData (inlineFlag, de // For non-left-most paths, we register the name resolutions here if not isLeftMost && not vspec.IsCompilerGenerated && not (String.hasPrefix vspec.LogicalName "_") then let item = Item.Value(mkLocalValRef vspec) - CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Binding, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Binding, env.DisplayEnv, env.AccessRights) PBind(vspec, typeScheme)), names, takenNames @@ -5136,7 +5140,7 @@ and TcPatAndRecover warnOnUpper cenv (env:TcEnv) topValInfo vFlags (tpenv, names /// the second-phase function in terms of a List.map from names to actual /// value specifications. and TcPat warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) ty pat = - let ad = env.eAccessRights + let ad = env.AccessRights match pat with | SynPat.Const (c, m) -> match c with @@ -5215,7 +5219,7 @@ and TcPat warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) ty p | SynConstructorArgs.NamePatPairs (pairs, _) -> pairs.Length if nargs <> 0 then error(Error(FSComp.SR.tcLiteralDoesNotTakeArguments(), m)) - match ResolvePatternLongIdent cenv.tcSink cenv.nameResolver warnOnUpperForId false m ad env.eNameResEnv TypeNameResolutionInfo.Default longId with + match ResolvePatternLongIdent cenv.tcSink cenv.nameResolver warnOnUpperForId false m ad env.NameEnv TypeNameResolutionInfo.Default longId with | Item.NewDef id -> match args with | SynConstructorArgs.Pats [] @@ -5225,7 +5229,7 @@ and TcPat warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) ty p | Item.ActivePatternCase(APElemRef(apinfo, vref, idx)) as item -> let args = match args with SynConstructorArgs.Pats args -> args | _ -> error(Error(FSComp.SR.tcNamedActivePattern(apinfo.ActiveTags.[idx]), m)) // TOTAL/PARTIAL ACTIVE PATTERNS - let _, vexp, _, _, tinst, _ = TcVal true cenv env tpenv vref None None m + let _, vexp, _, _, tinst, _ = TcVal env.TraitFreshner true cenv env tpenv vref None None m let vexp = MakeApplicableExprWithFlex cenv env vexp let vexpty = vexp.Type @@ -5286,7 +5290,7 @@ and TcPat warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) ty p let activePatIdentity = if isNil activePatArgsAsSynExprs then Some (vref, tinst) else None (fun values -> // Report information about the 'active recognizer' occurrence to IDE - CallNameResolutionSink cenv.tcSink (rangeOfLid longId, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Pattern, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (rangeOfLid longId, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Pattern, env.DisplayEnv, env.AccessRights) TPat_query((activePatExpr, activePatResTys, activePatIdentity, idx, apinfo), arg' values, m)), (tpenv, names, takenNames) @@ -5351,12 +5355,12 @@ and TcPat warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) ty p let args', acc = TcPatterns warnOnUpper cenv env vFlags (tpenv, names, takenNames) argtys args (fun values -> // Report information about the case occurrence to IDE - CallNameResolutionSink cenv.tcSink (rangeOfLid longId, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Pattern, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (rangeOfLid longId, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Pattern, env.DisplayEnv, env.AccessRights) mkf m (List.map (fun f -> f values) args')), acc | Item.ILField finfo -> // LITERAL .NET FIELDS - CheckILFieldInfoAccessible cenv.g cenv.amap m env.eAccessRights finfo + CheckILFieldInfoAccessible cenv.g cenv.amap m env.AccessRights finfo if not finfo.IsStatic then errorR (Error (FSComp.SR.tcFieldIsNotStatic(finfo.FieldName), m)) CheckILFieldAttributes cenv.g finfo m match finfo.LiteralValue with @@ -5371,7 +5375,7 @@ and TcPat warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) ty p | Item.RecdField rfinfo -> // LITERAL F# FIELDS - CheckRecdFieldInfoAccessible cenv.amap m env.eAccessRights rfinfo + CheckRecdFieldInfoAccessible cenv.amap m env.AccessRights rfinfo if not rfinfo.IsStatic then errorR (Error (FSComp.SR.tcFieldIsNotStatic(rfinfo.Name), m)) CheckRecdFieldInfoAttributes cenv.g rfinfo m |> CommitOperationResult match rfinfo.LiteralValue with @@ -5389,8 +5393,8 @@ and TcPat warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) ty p match vref.LiteralValue with | None -> error (Error(FSComp.SR.tcNonLiteralCannotBeUsedInPattern(), m)) | Some lit -> - let _, _, _, vexpty, _, _ = TcVal true cenv env tpenv vref None None m - CheckValAccessible m env.eAccessRights vref + let _, _, _, vexpty, _, _ = TcVal env.TraitFreshner true cenv env tpenv vref None None m + CheckValAccessible m env.AccessRights vref CheckFSharpAttributes cenv.g vref.Attribs m |> CommitOperationResult checkNoArgsForLiteral() UnifyTypes cenv env m ty vexpty @@ -5429,7 +5433,7 @@ and TcPat warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) ty p | SynPat.Record (flds, m) -> let tcref, fldsmap, _fldsList = BuildFieldMap cenv env true ty flds m // REVIEW: use _fldsList to type check pattern in code order not field defn order - let _, inst, tinst, gtyp = infoOfTyconRef m tcref + let _, inst, tinst, gtyp = FreshenTyconRef2 env.TraitFreshner m tcref UnifyTypes cenv env m ty gtyp let fields = tcref.TrueInstanceFieldsAsList let ftys = fields |> List.map (fun fsp -> actualTyOfRecdField inst fsp, fsp) @@ -5453,6 +5457,7 @@ and TcPat warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) ty p | SynPat.InstanceMember (_, _, _, _, m) -> errorR(Error(FSComp.SR.tcIllegalPattern(), pat.Range)) (fun _ -> TPat_wild m), (tpenv, names, takenNames) + | SynPat.FromParseError (pat, _) -> suppressErrorReporting (fun () -> TcPatAndRecover warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) (NewErrorType()) pat) @@ -5664,7 +5669,7 @@ and TcExprUndelayed cenv overallTy env tpenv (expr: SynExpr) = | SynExpr.Paren (expr2, _, _, mWholeExprIncludingParentheses) -> // We invoke CallExprHasTypeSink for every construct which is atomic in the syntax, i.e. where a '.' immediately following the // construct is a dot-lookup for the result of the construct. - CallExprHasTypeSink cenv.tcSink (mWholeExprIncludingParentheses, env.NameEnv, overallTy, env.DisplayEnv, env.eAccessRights) + CallExprHasTypeSink cenv.tcSink (mWholeExprIncludingParentheses, env.NameEnv, overallTy, env.DisplayEnv, env.AccessRights) let env = ShrinkContext env mWholeExprIncludingParentheses expr2.Range TcExpr cenv overallTy env tpenv expr2 @@ -5672,11 +5677,11 @@ and TcExprUndelayed cenv overallTy env tpenv (expr: SynExpr) = | SynExpr.TypeApp _ | SynExpr.Ident _ | SynExpr.LongIdent _ | SynExpr.App _ | SynExpr.DotGet _ -> error(Error(FSComp.SR.tcExprUndelayed(), expr.Range)) | SynExpr.Const (SynConst.String (s, m), _) -> - CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.DisplayEnv, env.eAccessRights) + CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.DisplayEnv, env.AccessRights) TcConstStringExpr cenv overallTy env m tpenv s | SynExpr.Const (c, m) -> - CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.DisplayEnv, env.eAccessRights) + CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.DisplayEnv, env.AccessRights) TcConstExpr cenv overallTy env m tpenv c | SynExpr.Lambda _ -> TcIteratedLambdas cenv true env overallTy Set.empty tpenv expr @@ -5747,7 +5752,7 @@ and TcExprUndelayed cenv overallTy env tpenv (expr: SynExpr) = overallTy, tpenv | _ -> failwith "upcast" TcStaticUpcast cenv env.DisplayEnv m tgty srcTy - mkCoerceExpr(e', tgty, m, srcTy), tpenv + mkCoerceExpr(e', tgty, m, srcTy),tpenv | SynExpr.Downcast(e, _, m) | SynExpr.InferredDowncast (e, m) -> let e', srcTy, tpenv = TcExprOfUnknownType cenv env tpenv e @@ -5791,7 +5796,7 @@ and TcExprUndelayed cenv overallTy env tpenv (expr: SynExpr) = mkAnyTupled cenv.g m tupInfoStruct args' argtys, tpenv | SynExpr.ArrayOrList (isArray, args, m) -> - CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.DisplayEnv, env.eAccessRights) + CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.DisplayEnv, env.AccessRights) let argty = NewInferenceType () UnifyTypes cenv env m overallTy (if isArray then mkArrayType cenv.g argty else Tastops.mkListTy cenv.g argty) @@ -5819,11 +5824,11 @@ and TcExprUndelayed cenv overallTy env tpenv (expr: SynExpr) = TcNewExpr cenv env tpenv objTy (Some synObjTy.Range) superInit arg mNewExpr | SynExpr.ObjExpr(objTy, argopt, binds, extraImpls, mNewExpr, m) -> - CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.DisplayEnv, env.eAccessRights) + CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.DisplayEnv, env.AccessRights) TcObjectExpr cenv overallTy env tpenv (objTy, argopt, binds, extraImpls, mNewExpr, m) | SynExpr.Record (inherits, optOrigExpr, flds, mWholeExpr) -> - CallExprHasTypeSink cenv.tcSink (mWholeExpr, env.NameEnv, overallTy, env.DisplayEnv, env.eAccessRights) + CallExprHasTypeSink cenv.tcSink (mWholeExpr, env.NameEnv, overallTy, env.DisplayEnv, env.AccessRights) TcRecdExpr cenv overallTy env tpenv (inherits, optOrigExpr, flds, mWholeExpr) | SynExpr.While (spWhile, e1, e2, m) -> @@ -5841,7 +5846,7 @@ and TcExprUndelayed cenv overallTy env tpenv (expr: SynExpr) = // notify name resolution sink about loop variable let item = Item.Value(mkLocalValRef idv) - CallNameResolutionSink cenv.tcSink (idv.Range, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Binding, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (idv.Range, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Binding, env.DisplayEnv, env.AccessRights) let bodyExpr, tpenv = TcStmt cenv envinner tpenv body mkFastForLoop cenv.g (spBind, m, idv, startExpr, dir, finishExpr, bodyExpr), tpenv @@ -5867,7 +5872,7 @@ and TcExprUndelayed cenv overallTy env tpenv (expr: SynExpr) = TcComputationOrSequenceExpression cenv env overallTy m None tpenv comp | SynExpr.ArrayOrListOfSeqExpr (isArray, comp, m) -> - CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.DisplayEnv, env.eAccessRights) + CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.DisplayEnv, env.AccessRights) match comp with | SynExpr.CompExpr(_, _, (SimpleSemicolonSequence true elems as body), _) -> @@ -6033,11 +6038,13 @@ and TcExprUndelayed cenv overallTy env tpenv (expr: SynExpr) = | SynExpr.TraitCall(tps, memSpfn, arg, m) -> let synTypes = tps |> List.map (fun tp -> SynType.Var(tp, m)) - let (TTrait(_, logicalCompiledName, _, argtys, returnTy, _) as traitInfo), tpenv = TcPseudoMemberSpec cenv NewTyparsOK env synTypes tpenv memSpfn m - if BakedInTraitConstraintNames.Contains logicalCompiledName then - warning(BakedInMemberConstraintName(logicalCompiledName, m)) + let traitInfo, tpenv = TcPseudoMemberSpec cenv NewTyparsOK env synTypes tpenv memSpfn m + + if BakedInTraitConstraintNames.Contains traitInfo.MemberName then + warning(BakedInMemberConstraintName(traitInfo.MemberName, m)) - let returnTy = GetFSharpViewOfReturnType cenv.g returnTy + let argtys = traitInfo.ArgumentTypes + let returnTy = GetFSharpViewOfReturnType cenv.g traitInfo.ReturnType let args, namedCallerArgs = GetMethodArgs arg if not (isNil namedCallerArgs) then errorR(Error(FSComp.SR.tcNamedArgumentsCannotBeUsedInMemberTraits(), m)) // Subsumption at trait calls if arguments have nominal type prior to unification of any arguments or return type @@ -6084,7 +6091,7 @@ and TcExprUndelayed cenv overallTy env tpenv (expr: SynExpr) = mkAsmExpr(Array.toList s, tyargs', args', rtys', m), tpenv | SynExpr.Quote(oper, raw, ast, isFromQueryExpression, m) -> - CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.DisplayEnv, env.eAccessRights) + CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.DisplayEnv, env.AccessRights) TcQuotationExpr cenv overallTy env tpenv (oper, raw, ast, isFromQueryExpression, m) | SynExpr.YieldOrReturn ((isTrueYield, _), _, m) @@ -6127,7 +6134,7 @@ and TcIteratedLambdas cenv isFirst (env: TcEnv) overallTy takenNames tpenv e = // .NET metadata. This means we manually typecheck 'e1' and look to see if it has a nominal type. We then // do the right thing in each case. and TcIndexerThen cenv env overallTy mWholeExpr mDot tpenv wholeExpr e1 indexArgs delayed = - let ad = env.eAccessRights + let ad = env.AccessRights let e1', e1ty, tpenv = TcExprOfUnknownType cenv env tpenv e1 // Find the first type in the effective hierarchy that either has a DefaultMember attribute OR @@ -6241,7 +6248,7 @@ and TcIndexerThen cenv env overallTy mWholeExpr mDot tpenv wholeExpr e1 indexArg /// For 'inherit Type(args)', mWholeExprOrObjTy is the whole expression /// For an implicit inherit from System.Object or a default constructor, mWholeExprOrObjTy is the type name of the type being defined and TcNewExpr cenv env tpenv objTy mObjTyOpt superInit arg mWholeExprOrObjTy = - let ad = env.eAccessRights + let ad = env.AccessRights // Handle the case 'new 'a()' if (isTyparTy cenv.g objTy) then if superInit then error(Error(FSComp.SR.tcCannotInheritFromVariableType(), mWholeExprOrObjTy)) @@ -6260,7 +6267,7 @@ and TcNewExpr cenv env tpenv objTy mObjTyOpt superInit arg mWholeExprOrObjTy = /// Check an 'inheritedTys declaration in an implicit or explicit class and TcCtorCall isNaked cenv env tpenv overallTy objTy mObjTyOpt item superInit args mWholeCall delayed afterTcOverloadResolutionOpt = - let ad = env.eAccessRights + let ad = env.AccessRights let isSuperInit = (if superInit then CtorValUsedAsSuperInit else NormalValUse) let mItem = match mObjTyOpt with Some m -> m | None -> mWholeCall @@ -6289,7 +6296,7 @@ and TcCtorCall isNaked cenv env tpenv overallTy objTy mObjTyOpt item superInit a | Item.DelegateCtor typ, [arg] -> // Re-record the name resolution since we now know it's a constructor call match mObjTyOpt with - | Some mObjTy -> CallNameResolutionSink cenv.tcSink (mObjTy, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) + | Some mObjTy -> CallNameResolutionSink cenv.tcSink (mObjTy, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.AccessRights) | None -> () TcNewDelegateThen cenv objTy env tpenv mItem mWholeCall typ arg ExprAtomicFlag.NonAtomic delayed @@ -6372,7 +6379,7 @@ and TcRecordConstruction cenv overallTy env tpenv optOrigExpr objTy fldsList m = // Check accessibility: this is also done in BuildFieldMap, but also need to check // for fields in { new R with a=1 and b=2 } constructions and { r with a=1 } copy-and-update expressions rfrefs |> List.iter (fun rfref -> - CheckRecdFieldAccessible cenv.amap m env.eAccessRights rfref |> ignore + CheckRecdFieldAccessible cenv.amap m env.AccessRights rfref |> ignore CheckFSharpAttributes cenv.g rfref.PropertyAttribs m |> CommitOperationResult) let args = List.map snd fldsList @@ -6469,8 +6476,7 @@ and FreshenObjExprAbstractSlot cenv (env: TcEnv) (implty:TType) virtNameAndArity | [(_, absSlot)] -> - let typarsFromAbsSlotAreRigid, typarsFromAbsSlot, argTysFromAbsSlot, retTyFromAbsSlot - = FreshenAbstractSlot cenv.g cenv.amap mBinding synTyparDecls absSlot + let typarsFromAbsSlotAreRigid, typarsFromAbsSlot, argTysFromAbsSlot, retTyFromAbsSlot = FreshenAbstractSlot env.TraitFreshner cenv.g cenv.amap mBinding synTyparDecls absSlot // Work out the required type of the member let bindingTy = implty --> (mkMethodTy cenv.g argTysFromAbsSlot retTyFromAbsSlot) @@ -6635,7 +6641,7 @@ and TcObjectExpr cenv overallTy env tpenv (synObjTy, argopt, binds, extraImpls, // Object expression members can access protected members of the implemented type let env = EnterFamilyRegion tcref env - let ad = env.eAccessRights + let ad = env.AccessRights if // record construction ? isRecordTy || @@ -6677,7 +6683,7 @@ and TcObjectExpr cenv overallTy env tpenv (synObjTy, argopt, binds, extraImpls, | Item.CtorGroup(methodName, minfos), Some (arg, baseIdOpt) -> let meths = minfos |> List.map (fun minfo -> minfo, None) let afterResolution = ForNewConstructors cenv.tcSink env synObjTy.Range methodName minfos - let ad = env.eAccessRights + let ad = env.AccessRights let expr, tpenv = TcMethodApplicationThen cenv env objTy None tpenv None [] mWholeExpr mObjTy methodName ad PossiblyMutates false meths afterResolution CtorValUsedAsSuperInit [arg] ExprAtomicFlag.Atomic [] // The 'base' value is always bound @@ -6801,8 +6807,8 @@ and TcConstExpr cenv overallTy env m tpenv c = | SynConst.UserNum (s, suffix) -> let expr = let modName = "NumericLiteral" + suffix - let ad = env.eAccessRights - match ResolveLongIndentAsModuleOrNamespace ResultCollectionSettings.AtMostOneResult cenv.amap m OpenQualified env.eNameResEnv ad [ident (modName, m)] with + let ad = env.AccessRights + match ResolveLongIndentAsModuleOrNamespace ResultCollectionSettings.AtMostOneResult cenv.amap m OpenQualified env.NameEnv ad [ident (modName, m)] with | Result [] | Exception _ -> error(Error(FSComp.SR.tcNumericLiteralRequiresModule(modName), m)) | Result ((_, mref, _) :: _) -> @@ -6889,7 +6895,7 @@ and TcRecdExpr cenv overallTy env tpenv (inherits, optOrigExpr, flds, mWholeExpr | [] -> [] | _ -> let tcref, _, fldsList = BuildFieldMap cenv env hasOrigExpr overallTy flds mWholeExpr - let _, _, _, gtyp = infoOfTyconRef mWholeExpr tcref + let _, _, _, gtyp = FreshenTyconRef2 env.TraitFreshner mWholeExpr tcref UnifyTypes cenv env mWholeExpr overallTy gtyp [ for n, v in fldsList do @@ -7083,7 +7089,7 @@ and IgnoreAttribute _ = None and TcComputationExpression cenv env overallTy mWhole interpExpr builderTy tpenv comp = //dprintfn "TcComputationOrSequenceExpression, comp = \n%A\n-------------------\n" comp - let ad = env.eAccessRights + let ad = env.AccessRights let mkSynDelay2 (e: SynExpr) = mkSynDelay (e.Range.MakeSynthetic()) e @@ -7095,7 +7101,7 @@ and TcComputationExpression cenv env overallTy mWhole interpExpr builderTy tpenv match interpExpr with | Expr.Val(vf, _, m) -> let item = Item.CustomBuilder (vf.DisplayName, vf) - CallNameResolutionSink cenv.tcSink (m, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (m, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.AccessRights) valRefEq cenv.g vf cenv.g.query_value_vref | _ -> false @@ -7302,7 +7308,7 @@ and TcComputationExpression cenv env overallTy mWhole interpExpr builderTy tpenv match e with | SynExpr.App(_, _, SynExpr.App(_, _, e1, SingleIdent opName, _), e2, _) when opName.idText = customOperationJoinConditionWord nm -> let item = Item.CustomOperation (opName.idText, (fun () -> None), None) - CallNameResolutionSink cenv.tcSink (opName.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (opName.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.AccessRights) Some (e1, e2) | _ -> None @@ -7321,7 +7327,7 @@ and TcComputationExpression cenv env overallTy mWhole interpExpr builderTy tpenv | IntoSuffix (x, intoWordRange, intoPat) -> // record the "into" as a custom operation for colorization let item = Item.CustomOperation ("into", (fun () -> None), None) - CallNameResolutionSink cenv.tcSink (intoWordRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (intoWordRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.AccessRights) (x, intoPat, alreadyGivenError) | _ -> if not alreadyGivenError then @@ -7455,7 +7461,7 @@ and TcComputationExpression cenv env overallTy mWhole interpExpr builderTy tpenv match optInto with | Some (intoWordRange, optInfo) -> let item = Item.CustomOperation ("into", (fun () -> None), None) - CallNameResolutionSink cenv.tcSink (intoWordRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (intoWordRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.AccessRights) Some optInfo | None -> None @@ -7590,7 +7596,7 @@ and TcComputationExpression cenv env overallTy mWhole interpExpr builderTy tpenv // FUTURE: consider whether we can do better than emptyTyparInst here, in order to display instantiations // of type variables in the quick info provided in the IDE. - CallNameResolutionSink cenv.tcSink (nm.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (nm.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.AccessRights) let mkJoinExpr keySelector1 keySelector2 innerPat e = let mSynthetic = mOpCore.MakeSynthetic() @@ -7784,7 +7790,7 @@ and TcComputationExpression cenv env overallTy mWhole interpExpr builderTy tpenv // FUTURE: consider whether we can do better than emptyTyparInst here, in order to display instantiations // of type variables in the quick info provided in the IDE. - CallNameResolutionSink cenv.tcSink (nm.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (nm.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.AccessRights) if isLikeZip || isLikeJoin || isLikeGroupJoin then errorR(Error(FSComp.SR.tcBinaryOperatorRequiresBody(nm.idText, Option.get (customOpUsageText nm)), nm.idRange)) @@ -8351,7 +8357,7 @@ and TcDelayed cenv overallTy env tpenv mExpr expr exprty (atomicFlag:ExprAtomicF // OK, we've typechecked the thing on the left of the delayed lookup chain. // We can now record for posterity the type of this expression and the location of the expression. if (atomicFlag = ExprAtomicFlag.Atomic) then - CallExprHasTypeSink cenv.tcSink (mExpr, env.NameEnv, exprty, env.DisplayEnv, env.eAccessRights) + CallExprHasTypeSink cenv.tcSink (mExpr, env.NameEnv, exprty, env.DisplayEnv, env.AccessRights) match delayed with | [] @@ -8429,7 +8435,7 @@ and TcFunctionApplicationThen cenv overallTy env tpenv mExprAndArg expr exprty ( and TcLongIdentThen cenv overallTy env tpenv (LongIdentWithDots(longId, _)) delayed = - let ad = env.eAccessRights + let ad = env.AccessRights let typeNameResInfo = // Given 'MyOverloadedType.MySubType...' use arity of #given type arguments to help // resolve type name lookup of 'MyOverloadedType' @@ -8446,7 +8452,7 @@ and TcLongIdentThen cenv overallTy env tpenv (LongIdentWithDots(longId, _)) dela | _ -> TypeNameResolutionInfo.Default - let nameResolutionResult = ResolveLongIdentAsExprAndComputeRange cenv.tcSink cenv.nameResolver (rangeOfLid longId) ad env.eNameResEnv typeNameResInfo longId + let nameResolutionResult = ResolveLongIdentAsExprAndComputeRange cenv.tcSink cenv.nameResolver (rangeOfLid longId) ad env.NameEnv typeNameResInfo longId TcItemThen cenv overallTy env tpenv nameResolutionResult delayed //------------------------------------------------------------------------- @@ -8455,7 +8461,7 @@ and TcLongIdentThen cenv overallTy env tpenv (LongIdentWithDots(longId, _)) dela // mItem is the textual range covered by the long identifiers that make up the item and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) delayed = let delayed = delayRest rest mItem delayed - let ad = env.eAccessRights + let ad = env.AccessRights match item with // x where x is a union case or active pattern result tag. | (Item.UnionCase _ | Item.ExnCase _ | Item.ActivePatternResult _) as item -> @@ -8471,7 +8477,7 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del mkConstrApp, [ucaseAppTy], [ for (s, m) in apinfo.ActiveTagsWithRanges -> mkSynId m s ] | _ -> let ucref = mkChoiceCaseRef cenv.g mItem aparity n - let _, _, tinst, _ = infoOfTyconRef mItem ucref.TyconRef + let _, _, tinst, _ = FreshenTyconRef2 env.TraitFreshner mItem ucref.TyconRef let ucinfo = UnionCaseInfo(tinst, ucref) ApplyUnionCaseOrExnTypes mItem cenv env ucaseAppTy (Item.UnionCase(ucinfo, false)) | _ -> @@ -8610,14 +8616,14 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del // Report information about the whole expression including type arguments to VS let item = Item.Types(nm, [typ]) - CallNameResolutionSink cenv.tcSink (mExprAndTypeArgs, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) - TcItemThen cenv overallTy env tpenv (ResolveExprDotLongIdentAndComputeRange cenv.tcSink cenv.nameResolver (unionRanges mExprAndTypeArgs mLongId) ad env.eNameResEnv typ longId IgnoreOverrides true) otherDelayed + CallNameResolutionSink cenv.tcSink (mExprAndTypeArgs, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.AccessRights) + TcItemThen cenv overallTy env tpenv (ResolveExprDotLongIdentAndComputeRange cenv.tcSink cenv.nameResolver (unionRanges mExprAndTypeArgs mLongId) ad env.NameEnv typ longId IgnoreOverrides true) otherDelayed | ((DelayedTypeApp(tyargs, _mTypeArgs, mExprAndTypeArgs))::_delayed') -> // A case where we have an incomplete name e.g. 'Foo.' - we still want to report it to VS! let typ, _ = TcNestedTypeApplication cenv NewTyparsOK CheckCxs ItemOccurence.UseInType env tpenv mExprAndTypeArgs typ tyargs let item = Item.Types(nm, [typ]) - CallNameResolutionSink cenv.tcSink (mExprAndTypeArgs, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (mExprAndTypeArgs, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.AccessRights) // Same error as in the following case error(Error(FSComp.SR.tcInvalidUseOfTypeName(), mItem)) @@ -8643,7 +8649,7 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del // Replace the resolution including the static parameters, plus the extra information about the original method info let item = Item.MethodGroup(methodName, [minfoAfterStaticArguments], Some minfos.[0]) - CallNameResolutionSinkReplacing cenv.tcSink (mItem, env.NameEnv, item, item, [], ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSinkReplacing cenv.tcSink (mItem, env.NameEnv, item, item, [], ItemOccurence.Use, env.DisplayEnv, env.AccessRights) match otherDelayed with | DelayedApp(atomicFlag, arg, mExprAndArg) :: otherDelayed -> @@ -8659,7 +8665,7 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del // FUTURE: can we do better than emptyTyparInst here, in order to display instantiations // of type variables in the quick info provided in the IDE? But note we haven't yet even checked if the // number of type arguments is correct... - CallNameResolutionSink cenv.tcSink (mExprAndTypeArgs, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (mExprAndTypeArgs, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.AccessRights) match otherDelayed with | DelayedApp(atomicFlag, arg, mExprAndArg) :: otherDelayed -> @@ -8682,13 +8688,13 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del match delayed with | ((DelayedApp (_, arg, mExprAndArg))::otherDelayed) -> - CallExprHasTypeSink cenv.tcSink (mExprAndArg, env.NameEnv, objTy, env.DisplayEnv, env.eAccessRights) + CallExprHasTypeSink cenv.tcSink (mExprAndArg, env.NameEnv, objTy, env.DisplayEnv, env.AccessRights) TcCtorCall true cenv env tpenv overallTy objTy (Some mItem) item false [arg] mExprAndArg otherDelayed (Some afterResolution) | ((DelayedTypeApp(tyargs, _mTypeArgs, mExprAndTypeArgs))::(DelayedApp (_, arg, mExprAndArg))::otherDelayed) -> let objTyAfterTyArgs, tpenv = TcNestedTypeApplication cenv NewTyparsOK CheckCxs ItemOccurence.UseInType env tpenv mExprAndTypeArgs objTy tyargs - CallExprHasTypeSink cenv.tcSink (mExprAndArg, env.NameEnv, objTyAfterTyArgs, env.DisplayEnv, env.eAccessRights) + CallExprHasTypeSink cenv.tcSink (mExprAndArg, env.NameEnv, objTyAfterTyArgs, env.DisplayEnv, env.AccessRights) let itemAfterTyArgs, minfosAfterTyArgs = #if !NO_EXTENSIONTYPING // If the type is provided and took static arguments then the constructor will have changed @@ -8712,7 +8718,7 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del // A case where we have an incomplete name e.g. 'Foo.' - we still want to report it to VS! let resolvedItem = Item.Types(nm, [objTy]) - CallNameResolutionSink cenv.tcSink (mExprAndTypeArgs, env.NameEnv, resolvedItem, resolvedItem, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (mExprAndTypeArgs, env.NameEnv, resolvedItem, resolvedItem, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.AccessRights) minfos |> List.iter (fun minfo -> UnifyTypes cenv env mExprAndTypeArgs minfo.EnclosingType objTy) TcCtorCall true cenv env tpenv overallTy objTy (Some mExprAndTypeArgs) item false [] mExprAndTypeArgs otherDelayed (Some afterResolution) @@ -8723,6 +8729,7 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del | Item.FakeInterfaceCtor _ -> error(Error(FSComp.SR.tcInvalidUseOfInterfaceType(), mItem)) + | Item.ImplicitOp(id, sln) -> let isPrefix = PrettyNaming.IsPrefixOperator id.idText @@ -8749,7 +8756,9 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del let memberFlags = StaticMemberFlags MemberKind.Member let logicalCompiledName = ComputeLogicalName id memberFlags - let traitInfo = TTrait(argTys, logicalCompiledName, memberFlags, argTys, Some retTy, sln) + + let traitInfo = TTrait(argTys, logicalCompiledName, memberFlags, argTys, Some retTy, sln, [], None) + let traitInfo = FreshenTrait env.TraitFreshner traitInfo let expr = Expr.Op(TOp.TraitCall(traitInfo), [], ves, mItem) let expr = mkLambdas mItem [] vs (expr, retTy) @@ -8848,7 +8857,7 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del // Report information about the whole expression including type arguments to VS let item = Item.DelegateCtor typ - CallNameResolutionSink cenv.tcSink (mItemAndTypeArgs, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (mItemAndTypeArgs, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.AccessRights) TcNewDelegateThen cenv overallTy env tpenv mItem mItemAndArg typ arg atomicFlag otherDelayed | _ -> error(Error(FSComp.SR.tcInvalidUseOfDelegate(), mItem)) @@ -8861,7 +8870,7 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del if not (isNil otherDelayed) then error(Error(FSComp.SR.tcInvalidAssignment(), mStmt)) UnifyTypes cenv env mStmt overallTy cenv.g.unit_ty vref.Deref.SetHasBeenReferenced() - CheckValAccessible mItem env.eAccessRights vref + CheckValAccessible mItem env.AccessRights vref CheckValAttributes cenv.g vref mItem |> CommitOperationResult let vty = vref.Type let vty2 = @@ -8887,7 +8896,7 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del // - it isn't a CtorValUsedAsSelfInit // - it isn't a VSlotDirectCall (uses of base values do not take type arguments let checkTys tpenv kinds = TcTypesOrMeasures (Some kinds) cenv NewTyparsOK CheckCxs ItemOccurence.UseInType env tpenv tys mItem - let _, vexp, isSpecial, _, _, tpenv = TcVal true cenv env tpenv vref (Some (NormalValUse, checkTys)) (Some afterResolution) mItem + let _, vexp, isSpecial, _, _, tpenv = TcVal env.TraitFreshner true cenv env tpenv vref (Some (NormalValUse, checkTys)) (Some afterResolution) mItem let vexpFlex = (if isSpecial then MakeApplicableExprNoFlex cenv vexp else MakeApplicableExprWithFlex cenv env vexp) // We need to eventually record the type resolution for an expression, but this is done // inside PropagateThenTcDelayed, so we don't have to explicitly call 'CallExprHasTypeSink' here @@ -8895,7 +8904,7 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del // Value get | _ -> - let _, vexp, isSpecial, _, _, tpenv = TcVal true cenv env tpenv vref None (Some afterResolution) mItem + let _, vexp, isSpecial, _, _, tpenv = TcVal env.TraitFreshner true cenv env tpenv vref None (Some afterResolution) mItem let vexpFlex = (if isSpecial then MakeApplicableExprNoFlex cenv vexp else MakeApplicableExprWithFlex cenv env vexp) PropagateThenTcDelayed cenv overallTy env tpenv mItem vexpFlex vexpFlex.Type ExprAtomicFlag.Atomic delayed @@ -9031,7 +9040,7 @@ and GetMemberApplicationArgs delayed cenv env tpenv = and TcLookupThen cenv overallTy env tpenv mObjExpr objExpr objExprTy longId delayed mExprAndLongId = let objArgs = [objExpr] - let ad = env.eAccessRights + let ad = env.AccessRights // 'base' calls use a different resolution strategy when finding methods. let findFlag = @@ -9042,7 +9051,7 @@ and TcLookupThen cenv overallTy env tpenv mObjExpr objExpr objExprTy longId dela if isTyparTy cenv.g objExprTy then GeneralizationHelpers.CanonicalizePartialInferenceProblem (cenv, env.DisplayEnv, mExprAndLongId) (freeInTypeLeftToRight cenv.g false objExprTy) - let item, mItem, rest, afterResolution = ResolveExprDotLongIdentAndComputeRange cenv.tcSink cenv.nameResolver mExprAndLongId ad env.eNameResEnv objExprTy longId findFlag false + let item, mItem, rest, afterResolution = ResolveExprDotLongIdentAndComputeRange cenv.tcSink cenv.nameResolver mExprAndLongId ad env.NameEnv objExprTy longId findFlag false let mExprAndItem = unionRanges mObjExpr mItem let delayed = delayRest rest mExprAndItem delayed @@ -9058,7 +9067,7 @@ and TcLookupThen cenv overallTy env tpenv mObjExpr objExpr objExprTy longId dela | Some minfoAfterStaticArguments -> // Replace the resolution including the static parameters, plus the extra information about the original method info let item = Item.MethodGroup(methodName, [minfoAfterStaticArguments], Some minfos.[0]) - CallNameResolutionSinkReplacing cenv.tcSink (mExprAndItem, env.NameEnv, item, item, [], ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSinkReplacing cenv.tcSink (mExprAndItem, env.NameEnv, item, item, [], ItemOccurence.Use, env.DisplayEnv, env.AccessRights) TcMethodApplicationThen cenv env overallTy None tpenv None objArgs mExprAndItem mItem methodName ad mutates false [(minfoAfterStaticArguments, None)] afterResolution NormalValUse args atomicFlag delayed | None -> @@ -9151,7 +9160,7 @@ and TcLookupThen cenv overallTy env tpenv mObjExpr objExpr objExprTy longId dela and TcEventValueThen cenv overallTy env tpenv mItem mExprAndItem objDetails (einfo:EventInfo) delayed = // Instance IL event (fake up event-as-value) let nm = einfo.EventName - let ad = env.eAccessRights + let ad = env.AccessRights match objDetails, einfo.IsStatic with | Some _, true -> error (Error (FSComp.SR.tcEventIsStatic(nm), mItem)) | None, false -> error (Error (FSComp.SR.tcEventIsNotStatic(nm), mItem)) @@ -9160,7 +9169,7 @@ and TcEventValueThen cenv overallTy env tpenv mItem mExprAndItem objDetails (ein let delegateType = einfo.GetDelegateType(cenv.amap, mItem) let (SigOfFunctionForDelegate(invokeMethInfo, compiledViewOfDelArgTys, _, _)) = GetSigOfFunctionForDelegate cenv.infoReader delegateType mItem ad let objArgs = Option.toList (Option.map fst objDetails) - MethInfoChecks cenv.g cenv.amap true None objArgs env.eAccessRights mItem invokeMethInfo + MethInfoChecks cenv.g cenv.amap true None objArgs env.AccessRights mItem invokeMethInfo // This checks for and drops the 'object' sender let argsTy = ArgsTypOfEventInfo cenv.infoReader mItem ad einfo @@ -9457,12 +9466,12 @@ and TcMethodApplication let callerArgs = List.zip unnamedCurriedCallerArgs namedCurriedCallerArgs let makeOneCalledMeth (minfo, pinfoOpt, usesParamArrayConversion) = - let minst = FreshenMethInfo mItem minfo + let minst = FreshenMethInfo env.TraitFreshner mItem minfo let callerTyArgs = match tyargsOpt with | Some tyargs -> minfo.AdjustUserTypeInstForFSharpStyleIndexedExtensionMembers(tyargs) | None -> minst - CalledMeth(cenv.infoReader, Some(env.NameEnv), isCheckingAttributeCall, FreshenMethInfo, mMethExpr, ad, minfo, minst, callerTyArgs, pinfoOpt, callerObjArgTys, callerArgs, usesParamArrayConversion, true, objTyOpt) + CalledMeth(cenv.infoReader, Some(env.NameEnv), isCheckingAttributeCall, FreshenMethInfo env.TraitFreshner, mMethExpr, ad, minfo, minst, callerTyArgs, pinfoOpt, callerObjArgTys, callerArgs, usesParamArrayConversion, true, objTyOpt) let preArgumentTypeCheckingCalledMethGroup = [ for (minfo, pinfoOpt) in candidateMethsAndProps do @@ -9471,7 +9480,7 @@ and TcMethodApplication if meth.UsesParamArrayConversion then yield makeOneCalledMeth (minfo, pinfoOpt, false) ] - let uniquelyResolved = + let uniquelyResolved = let csenv = MakeConstraintSolverEnv ContextInfo.NoContext cenv.css mMethExpr denv let res = UnifyUniqueOverloading csenv callerArgCounts methodName ad preArgumentTypeCheckingCalledMethGroup returnTy @@ -9561,7 +9570,7 @@ and TcMethodApplication match tyargsOpt with | Some tyargs -> minfo.AdjustUserTypeInstForFSharpStyleIndexedExtensionMembers(tyargs) | None -> minst - CalledMeth(cenv.infoReader, Some(env.NameEnv), isCheckingAttributeCall, FreshenMethInfo, mMethExpr, ad, minfo, minst, callerTyArgs, pinfoOpt, callerObjArgTys, callerArgs, usesParamArrayConversion, true, objTyOpt)) + CalledMeth(cenv.infoReader, Some(env.NameEnv), isCheckingAttributeCall, FreshenMethInfo env.TraitFreshner, mMethExpr, ad, minfo, minst, callerTyArgs, pinfoOpt, callerObjArgTys, callerArgs, usesParamArrayConversion, true, objTyOpt)) let callerArgCounts = (unnamedCurriedCallerArgs.Length, namedCurriedCallerArgs.Length) let csenv = MakeConstraintSolverEnv ContextInfo.NoContext cenv.css mMethExpr denv @@ -10091,11 +10100,11 @@ and TcMethodArg cenv env (lambdaPropagationInfo, tpenv) (lambdaPropagationInfo /// Typecheck "new Delegate(fun x y z -> ...)" constructs and TcNewDelegateThen cenv overallTy env tpenv mDelTy mExprAndArg delegateTy arg atomicFlag delayed = - let ad = env.eAccessRights + let ad = env.AccessRights UnifyTypes cenv env mExprAndArg overallTy delegateTy let (SigOfFunctionForDelegate(invokeMethInfo, delArgTys, _, fty)) = GetSigOfFunctionForDelegate cenv.infoReader delegateTy mDelTy ad // We pass isInstance = true here because we're checking the rights to access the "Invoke" method - MethInfoChecks cenv.g cenv.amap true None [] env.eAccessRights mExprAndArg invokeMethInfo + MethInfoChecks cenv.g cenv.amap true None [] env.AccessRights mExprAndArg invokeMethInfo let args = GetMethodArgs arg match args with | [farg], [] -> @@ -10407,7 +10416,7 @@ and TcNormalizedBinding declKind (cenv:cenv) env tpenv overallTy safeThisValOpt apinfo.ActiveTagsWithRanges |> List.iteri (fun i (_tag, tagRange) -> let item = Item.ActivePatternResult(apinfo, cenv.g.unit_ty, i, tagRange) - CallNameResolutionSink cenv.tcSink (tagRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Binding, env.DisplayEnv, env.eAccessRights)) + CallNameResolutionSink cenv.tcSink (tagRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Binding, env.DisplayEnv, env.AccessRights)) ModifyNameResEnv (fun nenv -> AddActivePatternResultTagsToNameEnv apinfo nenv ty m) envinner | None -> @@ -10527,13 +10536,13 @@ and TcAttribute canFail cenv (env: TcEnv) attrTgt (synAttr: SynAttribute) = let try1 n = let tyid = mkSynId tyid.idRange n let tycon = (typath @ [tyid]) - let ad = env.eAccessRights - match ResolveTypeLongIdent cenv.tcSink cenv.nameResolver ItemOccurence.UseInAttribute OpenQualified env.eNameResEnv ad tycon TypeNameResolutionStaticArgsInfo.DefiniteEmpty PermitDirectReferenceToGeneratedType.No with + let ad = env.AccessRights + match ResolveTypeLongIdent cenv.tcSink cenv.nameResolver ItemOccurence.UseInAttribute OpenQualified env.NameEnv ad tycon TypeNameResolutionStaticArgsInfo.DefiniteEmpty PermitDirectReferenceToGeneratedType.No with | Exception err -> raze(err) | _ -> success(TcTypeAndRecover cenv NoNewTypars CheckCxs ItemOccurence.UseInAttribute env tpenv (SynType.App(SynType.LongIdent(LongIdentWithDots(tycon, [])), None, [], [], None, false, mAttr)) ) ForceRaise ((try1 (tyid.idText + "Attribute")) |> ResultOrException.otherwise (fun () -> (try1 tyid.idText))) - let ad = env.eAccessRights + let ad = env.AccessRights if not (IsTypeAccessible cenv.g cenv.amap mAttr ad ty) then errorR(Error(FSComp.SR.tcTypeIsInaccessible(), mAttr)) @@ -10878,7 +10887,7 @@ and ComputeIsComplete enclosingDeclaredTypars declaredTypars ty = /// it implements. Apply the inferred slotsig. and ApplyAbstractSlotInference (cenv:cenv) (envinner:TcEnv) (bindingTy, m, synTyparDecls, declaredTypars, memberId, tcrefObjTy, renaming, _objTy, optIntfSlotTy, valSynData, memberFlags, attribs) = - let ad = envinner.eAccessRights + let ad = envinner.AccessRights let typToSearchForAbstractMembers = match optIntfSlotTy with | Some (ty, abstractSlots) -> @@ -10931,7 +10940,7 @@ and ApplyAbstractSlotInference (cenv:cenv) (envinner:TcEnv) (bindingTy, m, synTy let uniqueAbstractMeth = uniqueAbstractMeth.Instantiate(cenv.amap, m, renaming) let typarsFromAbsSlotAreRigid, typarsFromAbsSlot, argTysFromAbsSlot, retTyFromAbsSlot = - FreshenAbstractSlot cenv.g cenv.amap m synTyparDecls uniqueAbstractMeth + FreshenAbstractSlot None cenv.g cenv.amap m synTyparDecls uniqueAbstractMeth let declaredTypars = (if typarsFromAbsSlotAreRigid then typarsFromAbsSlot else declaredTypars) @@ -10988,7 +10997,7 @@ and ApplyAbstractSlotInference (cenv:cenv) (envinner:TcEnv) (bindingTy, m, synTy let uniqueAbstractMeth = uniqueAbstractMeth.Instantiate(cenv.amap, m, renaming) let _, typarsFromAbsSlot, argTysFromAbsSlot, retTyFromAbsSlot = - FreshenAbstractSlot cenv.g cenv.amap m synTyparDecls uniqueAbstractMeth + FreshenAbstractSlot None cenv.g cenv.amap m synTyparDecls uniqueAbstractMeth if not (isNil typarsFromAbsSlot) then errorR(InternalError("Unexpected generic property", memberId.idRange)) @@ -11056,7 +11065,7 @@ and AnalyzeRecursiveStaticMemberOrValDecl (cenv, envinner: TcEnv, tpenv, declKin error(Error(FSComp.SR.tcConstructorsDisallowedInExceptionAugmentation(), id.idRange)) let isExtrinsic = (declKind = ExtrinsicExtensionBinding) - let _, enclosingDeclaredTypars, _, objTy, thisTy = FreshenObjectArgType cenv mBinding TyparRigidity.WillBeRigid tcref isExtrinsic declaredTyconTypars + let _, enclosingDeclaredTypars, _, objTy, thisTy = FreshenObjectArgType cenv None mBinding TyparRigidity.WillBeRigid tcref isExtrinsic declaredTyconTypars let envinner = AddDeclaredTypars CheckForDuplicateTypars enclosingDeclaredTypars envinner let envinner = MakeInnerEnvForTyconRef cenv envinner tcref isExtrinsic @@ -11121,7 +11130,7 @@ and AnalyzeRecursiveInstanceMemberDecl (cenv, envinner: TcEnv, tpenv, declKind, // The type being augmented tells us the type of 'this' let isExtrinsic = (declKind = ExtrinsicExtensionBinding) - let tcrefObjTy, enclosingDeclaredTypars, renaming, objTy, thisTy = FreshenObjectArgType cenv mBinding TyparRigidity.WillBeRigid tcref isExtrinsic declaredTyconTypars + let tcrefObjTy, enclosingDeclaredTypars, renaming, objTy, thisTy = FreshenObjectArgType cenv None mBinding TyparRigidity.WillBeRigid tcref isExtrinsic declaredTyconTypars let envinner = AddDeclaredTypars CheckForDuplicateTypars enclosingDeclaredTypars envinner @@ -11273,7 +11282,7 @@ and AnalyzeAndMakeAndPublishRecursiveValue overridesOK isGeneratedEventVal cenv match toolIdOpt with | Some tid when not tid.idRange.IsSynthetic && tid.idRange <> bindingId.idRange -> let item = Item.Value (mkLocalValRef vspec) - CallNameResolutionSink cenv.tcSink (tid.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.RelatedText, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (tid.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.RelatedText, env.DisplayEnv, env.AccessRights) | _ -> () @@ -11597,7 +11606,7 @@ and TcLetrecComputeAndGeneralizeGenericTyparsForBinding cenv denv freeInEnv (pgr let maxInferredTypars = freeInTypeLeftToRight cenv.g false tau let canGeneralizeConstrained = GeneralizationHelpers.CanGeneralizeConstrainedTyparsForDecl rbinfo.DeclKind - let generalizedTypars = GeneralizationHelpers.ComputeAndGeneralizeGenericTypars (cenv, denv, m, freeInEnv, canInferTypars, canGeneralizeConstrained, inlineFlag, Some(expr), allDeclaredTypars, maxInferredTypars, tau, isCtor) + let generalizedTypars = GeneralizationHelpers.ComputeAndGeneralizeGenericTypars (cenv, denv, m, freeInEnv, canInferTypars, canGeneralizeConstrained, inlineFlag, Some(expr), allDeclaredTypars, maxInferredTypars,tau,isCtor) generalizedTypars /// Compute the type variables which may have member constraints that need to be canonicalized prior to generalization @@ -11839,7 +11848,7 @@ let TcAndPublishValSpec (cenv, env, containerInfo: ContainerInfo, declKind, memF let flex = ExplicitTyparInfo(declaredTypars, declaredTypars, synCanInferTypars) - let generalizedTypars = GeneralizationHelpers.ComputeAndGeneralizeGenericTypars(cenv, denv, id.idRange, emptyFreeTypars, canInferTypars, CanGeneralizeConstrainedTypars, inlineFlag, None, allDeclaredTypars, freeInType, ty, false) + let generalizedTypars = GeneralizationHelpers.ComputeAndGeneralizeGenericTypars(cenv, denv, id.idRange, emptyFreeTypars, canInferTypars, CanGeneralizeConstrainedTypars, inlineFlag, None, allDeclaredTypars,freeInType, ty, false) let valscheme1 = PrelimValScheme1(id, flex, ty, Some(partialValReprInfo), memberInfoOpt, mutableFlag, inlineFlag, NormalVal, noArgOrRetAttribs, vis, false) @@ -12073,7 +12082,7 @@ let TcTyconMemberSpecs cenv env containerInfo declKind tpenv (augSpfn: SynMember let TcModuleOrNamespaceLidAndPermitAutoResolve env amap (longId : Ident list) = let ad = env.eAccessRights let m = longId |> List.map (fun id -> id.idRange) |> List.reduce unionRanges - match ResolveLongIndentAsModuleOrNamespace ResultCollectionSettings.AllResults amap m OpenQualified env.eNameResEnv ad longId with + match ResolveLongIndentAsModuleOrNamespace ResultCollectionSettings.AllResults amap m OpenQualified env.eNameEnv ad longId with | Result res -> Result res | Exception err -> raze err @@ -13038,7 +13047,7 @@ module MutRecBindingChecking = AddLocalTyconRefs true cenv.g cenv.amap tcref.Range [tcref] innitalEnvForTycon // Make fresh version of the class type for type checking the members and lets * - let _, copyOfTyconTypars, _, objTy, thisTy = FreshenObjectArgType cenv tcref.Range TyparRigidity.WillBeRigid tcref isExtrinsic declaredTyconTypars + let _, copyOfTyconTypars, _, objTy, thisTy = FreshenObjectArgType cenv None tcref.Range TyparRigidity.WillBeRigid tcref isExtrinsic declaredTyconTypars // The basic iteration over the declarations in a single type definition @@ -13307,7 +13316,7 @@ module MutRecBindingChecking = let nm = bind.Var.DisplayName let ty = generalizedTyconRef tcref - let ad = envNonRec.eAccessRights + let ad = envNonRec.AccessRights match TryFindIntrinsicMethInfo cenv.infoReader bind.Var.Range ad nm ty, TryFindPropInfo cenv.infoReader bind.Var.Range ad nm ty with | [], [] -> () @@ -13570,7 +13579,7 @@ module MutRecBindingChecking = /// Check a "module X = A.B.C" module abbreviation declaration let TcModuleAbbrevDecl (cenv:cenv) scopem env (id, p, m) = let ad = env.eAccessRights - let mvvs = ForceRaise (ResolveLongIndentAsModuleOrNamespace ResultCollectionSettings.AllResults cenv.amap m OpenQualified env.eNameResEnv ad p) + let mvvs = ForceRaise (ResolveLongIndentAsModuleOrNamespace ResultCollectionSettings.AllResults cenv.amap m OpenQualified env.eNameEnv ad p) let modrefs = mvvs |> List.map p23 if modrefs.Length > 0 && modrefs |> List.forall (fun modref -> modref.IsNamespace) then errorR(Error(FSComp.SR.tcModuleAbbreviationForNamespace(fullDisplayTextOfModRef (List.head modrefs)), m)) @@ -13755,7 +13764,7 @@ module MutRecBindingChecking = for tp in unsolvedTyparsForRecursiveBlockInvolvingGeneralizedVariables do //printfn "solving unsolvedTyparsInvolvingGeneralizedVariable : %s #%d" tp.DisplayName tp.Stamp if (tp.Rigidity <> TyparRigidity.Rigid) && not tp.IsSolved then - ConstraintSolver.ChooseTyparSolutionAndSolve cenv.css denv tp + ConstraintSolver.ChooseTyparSolutionAndSolve cenv.css denv tp // Now that we know what we've generalized we can adjust the recursive references let defnsCs = TcMutRecBindings_Phase2C_FixupRecursiveReferences cenv (denv, defnsBs, generalizedTyparsForRecursiveBlock, generalizedRecBinds, scopem) @@ -14306,9 +14315,9 @@ module TcExceptionDeclarations = let repr = match reprIdOpt with | Some longId -> - match ResolveExprLongIdent cenv.tcSink cenv.nameResolver m ad env.eNameResEnv TypeNameResolutionInfo.Default longId with + match ResolveExprLongIdent cenv.tcSink cenv.nameResolver m ad env.NameEnv TypeNameResolutionInfo.Default longId with | Item.ExnCase exnc, [] -> - CheckTyconAccessible cenv.amap m env.eAccessRights exnc |> ignore + CheckTyconAccessible cenv.amap m env.AccessRights exnc |> ignore if not (isNil args') then errorR (Error(FSComp.SR.tcExceptionAbbreviationsShouldNotHaveArgumentList(), m)) TExnAbbrevRepr exnc @@ -14339,7 +14348,7 @@ module TcExceptionDeclarations = exnc.entity_exn_info <- repr let item = Item.ExnCase(mkLocalTyconRef exnc) - CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Binding, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Binding, env.DisplayEnv, env.AccessRights) args' let private TcExnDefnCore cenv env parent synExnDefnRepr = @@ -14450,7 +14459,7 @@ module EstablishTypeDefinitionCores = | SynTypeDefnSimpleRepr.TypeAbbrev(_, SynType.LongIdent(LongIdentWithDots([unionCaseName], _)), m) when (not hasMeasureAttr && - (isNil (LookupTypeNameInEnvNoArity OpenQualified unionCaseName.idText envinner.eNameResEnv) || + (isNil (LookupTypeNameInEnvNoArity OpenQualified unionCaseName.idText envinner.eNameEnv) || id.idText = unionCaseName.idText)) -> Some(unionCaseName, m) | _ -> @@ -14734,7 +14743,7 @@ module EstablishTypeDefinitionCores = | None -> None | Some (tc, args, m) -> let ad = envinner.eAccessRights - match ResolveTypeLongIdent cenv.tcSink cenv.nameResolver ItemOccurence.UseInType OpenQualified envinner.eNameResEnv ad tc TypeNameResolutionStaticArgsInfo.DefiniteEmpty PermitDirectReferenceToGeneratedType.Yes with + match ResolveTypeLongIdent cenv.tcSink cenv.nameResolver ItemOccurence.UseInType OpenQualified envinner.eNameEnv ad tc TypeNameResolutionStaticArgsInfo.DefiniteEmpty PermitDirectReferenceToGeneratedType.Yes with | Result tcrefBeforeStaticArguments when tcrefBeforeStaticArguments.IsProvided && not tcrefBeforeStaticArguments.IsErased -> @@ -15159,7 +15168,7 @@ module EstablishTypeDefinitionCores = // Notify the Language Service about field names in record/class declaration - let ad = envinner.eAccessRights + let ad = envinner.AccessRights let writeFakeRecordFieldsToSink (fields:RecdField list) = let nenv = envinner.NameEnv // Record fields should be visible from IntelliSense, so add fake names for them (similarly to "let a = ..") @@ -15807,14 +15816,14 @@ module TcDeclarations = // This records a name resolution of the type at the location let resInfo = TypeNameResolutionStaticArgsInfo.FromTyArgs synTypars.Length - ResolveTypeLongIdent cenv.tcSink cenv.nameResolver ItemOccurence.Binding OpenQualified envForDecls.eNameResEnv ad longPath resInfo PermitDirectReferenceToGeneratedType.No + ResolveTypeLongIdent cenv.tcSink cenv.nameResolver ItemOccurence.Binding OpenQualified envForDecls.eNameEnv ad longPath resInfo PermitDirectReferenceToGeneratedType.No |> ignore mkLocalTyconRef tycon | _ -> let resInfo = TypeNameResolutionStaticArgsInfo.FromTyArgs synTypars.Length - match ResolveTypeLongIdent cenv.tcSink cenv.nameResolver ItemOccurence.Binding OpenQualified envForDecls.eNameResEnv ad longPath resInfo PermitDirectReferenceToGeneratedType.No with + match ResolveTypeLongIdent cenv.tcSink cenv.nameResolver ItemOccurence.Binding OpenQualified envForDecls.eNameEnv ad longPath resInfo PermitDirectReferenceToGeneratedType.No with | Result res -> res | res when inSig && longPath.Length = 1 -> errorR(Deprecated(FSComp.SR.tcReservedSyntaxForAugmentation(), m)) @@ -16352,8 +16361,8 @@ let rec TcSignatureElementNonMutRec cenv parent typeNames endm (env: TcEnv) synS return env | SynModuleSigDecl.ModuleAbbrev (id, p, m) -> - let ad = env.eAccessRights - let mvvs = ForceRaise (ResolveLongIndentAsModuleOrNamespace ResultCollectionSettings.AllResults cenv.amap m OpenQualified env.eNameResEnv ad p) + let ad = env.AccessRights + let mvvs = ForceRaise (ResolveLongIndentAsModuleOrNamespace ResultCollectionSettings.AllResults cenv.amap m OpenQualified env.NameEnv ad p) let scopem = unionRanges m endm let unfilteredModrefs = mvvs |> List.map p23 diff --git a/src/fsharp/TypeRelations.fs b/src/fsharp/TypeRelations.fs index ceb8ca810b0..9f29b97cf84 100755 --- a/src/fsharp/TypeRelations.fs +++ b/src/fsharp/TypeRelations.fs @@ -143,8 +143,8 @@ let ChooseTyparSolutionAndRange (g: TcGlobals) amap (tp:Typar) = match tpc with | TyparConstraint.CoercesTo(x,m) -> join m x,m - | TyparConstraint.MayResolveMember(TTrait(_,nm,_,_,_,_),m) -> - errorR(Error(FSComp.SR.typrelCannotResolveAmbiguityInOverloadedOperator(DemangleOperatorName nm),m)) + | TyparConstraint.MayResolveMember(traitInfo, m) -> + errorR(Error(FSComp.SR.typrelCannotResolveAmbiguityInOverloadedOperator(DemangleOperatorName traitInfo.MemberName),m)) maxSoFar,m | TyparConstraint.SimpleChoice(_,m) -> errorR(Error(FSComp.SR.typrelCannotResolveAmbiguityInPrintf(),m)) diff --git a/src/fsharp/fsc.fs b/src/fsharp/fsc.fs index e18f782dc21..1b9bbfbb3d7 100644 --- a/src/fsharp/fsc.fs +++ b/src/fsharp/fsc.fs @@ -1896,7 +1896,7 @@ let main1OfAst (ctok, legacyReferenceResolver, openBinariesInMemory, assemblyNam use unwindParsePhase = PushThreadBuildPhaseUntilUnwind (BuildPhase.TypeCheck) let tcEnv0 = GetInitialTcEnv (assemblyName, rangeStartup, tcConfig, tcImports, tcGlobals) - let tcState,topAttrs,typedAssembly,_tcEnvAtEnd = + let tcState, topAttrs, typedAssembly, _tcEnvAtEnd = TypeCheck(ctok, tcConfig, tcImports, tcGlobals, errorLogger, assemblyName, NiceNameGenerator(), tcEnv0, inputs,exiter) let generatedCcu = tcState.Ccu @@ -1937,7 +1937,7 @@ let main2a(Args (ctok, tcConfig, tcImports, frameworkTcImports: TcImports, tcGlo use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Optimize let optEnv0 = GetInitialOptimizationEnv (tcImports, tcGlobals) - + let importMap = tcImports.GetImportMap() let metadataVersion = match tcConfig.metadataVersion with diff --git a/src/fsharp/infos.fs b/src/fsharp/infos.fs index 5ac157c8d42..c58eb53bde7 100755 --- a/src/fsharp/infos.fs +++ b/src/fsharp/infos.fs @@ -296,6 +296,23 @@ let ImportReturnTypeFromMetaData amap m ty scoref tinst minst = | ILType.Void -> None | retTy -> Some (ImportILTypeFromMetadata amap m scoref tinst minst retTy) + +/// Search for the relevant extension values again if a name resolution environment is provided +/// Basically, if you use a generic thing, then the extension members in scope at the point of _use_ +/// are the ones available to solve the constraint +let FreshenTrait traitFreshner traitInfo = + let (TTrait(typs, nm, mf, argtys, rty, slnCell, extSlns, ad)) = traitInfo + + // Call the trait freshner if it is provided + let extSlns2, ad2 = + match traitFreshner with + | None -> extSlns, ad + | Some f -> + let extSlns2, ad2 = f traitInfo + extSlns2, Some ad2 + + TTrait(typs, nm, mf, argtys, rty, slnCell, extSlns2, ad2) + /// Copy constraints. If the constraint comes from a type parameter associated /// with a type constructor then we are simply renaming type variables. If it comes /// from a generic method in a generic class (e.g. typ.M<_>) then we may be both substituting the @@ -304,7 +321,7 @@ let ImportReturnTypeFromMetaData amap m ty scoref tinst minst = /// /// Note: this now looks identical to constraint instantiation. -let CopyTyparConstraints m tprefInst (tporig:Typar) = +let CopyTyparConstraints traitFreshner m tprefInst (tporig:Typar) = tporig.Constraints |> List.map (fun tpc -> match tpc with @@ -332,12 +349,13 @@ let CopyTyparConstraints m tprefInst (tporig:Typar) = TyparConstraint.SimpleChoice (List.map (instType tprefInst) tys,m) | TyparConstraint.RequiresDefaultConstructor _ -> TyparConstraint.RequiresDefaultConstructor m - | TyparConstraint.MayResolveMember(traitInfo,_) -> - TyparConstraint.MayResolveMember (instTrait tprefInst traitInfo,m)) + | TyparConstraint.MayResolveMember(traitInfo, _) -> + let traitInfo2 = FreshenTrait traitFreshner traitInfo + TyparConstraint.MayResolveMember (instTrait tprefInst traitInfo2, m)) /// The constraints for each typar copied from another typar can only be fixed up once /// we have generated all the new constraints, e.g. f List, B :> List> ... -let FixupNewTypars m (formalEnclosingTypars:Typars) (tinst: TType list) (tpsorig: Typars) (tps: Typars) = +let FixupNewTypars traitFreshner m (formalEnclosingTypars:Typars) (tinst: TType list) (tpsorig: Typars) (tps: Typars) = // Checks.. These are defensive programming against early reported errors. let n0 = formalEnclosingTypars.Length let n1 = tinst.Length @@ -349,7 +367,7 @@ let FixupNewTypars m (formalEnclosingTypars:Typars) (tinst: TType list) (tpsorig // The real code.. let renaming,tptys = mkTyparToTyparRenaming tpsorig tps let tprefInst = mkTyparInst formalEnclosingTypars tinst @ renaming - (tpsorig,tps) ||> List.iter2 (fun tporig tp -> tp.FixupConstraints (CopyTyparConstraints m tprefInst tporig)) + (tpsorig,tps) ||> List.iter2 (fun tporig tp -> tp.FixupConstraints (CopyTyparConstraints traitFreshner m tprefInst tporig)) renaming,tptys @@ -843,9 +861,7 @@ type ILMethInfo = // MethInfo -#if DEBUG [] -#endif /// Describes an F# use of a method [] type MethInfo = @@ -921,7 +937,6 @@ type MethInfo = /// over extension members. member x.ExtensionMemberPriority = defaultArg x.ExtensionMemberPriorityOption System.UInt64.MaxValue -#if DEBUG /// Get the method name in DebuggerDisplayForm member x.DebuggerDisplayName = match x with @@ -931,7 +946,6 @@ type MethInfo = | ProvidedMeth(_,mi,_,m) -> "ProvidedMeth: " + mi.PUntaint((fun mi -> mi.Name),m) #endif | DefaultStructCtor _ -> ".ctor" -#endif /// Get the method name in LogicalName form, i.e. the name as it would be stored in .NET metadata member x.LogicalName = @@ -1455,9 +1469,9 @@ type MethInfo = let tcref = tcrefOfAppTy g x.EnclosingType let formalEnclosingTyparsOrig = tcref.Typars(m) let formalEnclosingTypars = copyTypars formalEnclosingTyparsOrig - let _,formalEnclosingTyparTys = FixupNewTypars m [] [] formalEnclosingTyparsOrig formalEnclosingTypars + let _,formalEnclosingTyparTys = FixupNewTypars None m [] [] formalEnclosingTyparsOrig formalEnclosingTypars let formalMethTypars = copyTypars x.FormalMethodTypars - let _,formalMethTyparTys = FixupNewTypars m formalEnclosingTypars formalEnclosingTyparTys x.FormalMethodTypars formalMethTypars + let _,formalMethTyparTys = FixupNewTypars None m formalEnclosingTypars formalEnclosingTyparTys x.FormalMethodTypars formalMethTypars let formalRetTy, formalParams = match x with | ILMeth(_,ilminfo,_) -> @@ -2116,6 +2130,8 @@ type PropInfo = | ProvidedProp(_,pi,_) -> ProvidedPropertyInfo.TaintedGetHashCode(pi) #endif + override x.ToString() = "property " + x.PropertyName + //------------------------------------------------------------------------- // ILEventInfo @@ -2324,6 +2340,7 @@ type EventInfo = #if !NO_EXTENSIONTYPING | ProvidedEvent (_,ei,_) -> ProvidedEventInfo.TaintedGetHashCode(ei) #endif + override x.ToString() = "event " + x.EventName //------------------------------------------------------------------------- // Helpers associated with getting and comparing method signatures diff --git a/src/fsharp/symbols/Exprs.fs b/src/fsharp/symbols/Exprs.fs index 76f3dad6d7c..e6074325bca 100644 --- a/src/fsharp/symbols/Exprs.fs +++ b/src/fsharp/symbols/Exprs.fs @@ -639,7 +639,7 @@ module FSharpExprConvert = let typR = ConvType cenv (mkAppTy tycr tyargs) E.UnionCaseTag(ConvExpr cenv env arg1, typR) - | TOp.TraitCall (TTrait(tys, nm, memFlags, argtys, _rty, _colution)), _, _ -> + | TOp.TraitCall (TTrait(tys, nm, memFlags, argtys, _rty, _solution, _extSlns, _ad)), _, _ -> let tysR = ConvTypes cenv tys let tyargsR = ConvTypes cenv tyargs let argtysR = ConvTypes cenv argtys diff --git a/src/fsharp/symbols/Symbols.fs b/src/fsharp/symbols/Symbols.fs index c97b62e9d48..da006d88463 100644 --- a/src/fsharp/symbols/Symbols.fs +++ b/src/fsharp/symbols/Symbols.fs @@ -1037,7 +1037,8 @@ and FSharpAbstractSignature(cenv, info: SlotSig) = member __.DeclaringType = FSharpType(cenv, info.ImplementedType) and FSharpGenericParameterMemberConstraint(cenv, info: TraitConstraintInfo) = - let (TTrait(tys, nm, flags, atys, rty, _)) = info + let (TTrait(tys, nm, flags, atys, rty, _, _extSlns, _ad)) = info + member __.MemberSources = tys |> List.map (fun ty -> FSharpType(cenv, ty)) |> makeReadOnlyCollection @@ -1095,7 +1096,7 @@ and FSharpGenericParameterConstraint(cenv, cx: TyparConstraint) = member __.MemberConstraintData = match cx with - | TyparConstraint.MayResolveMember(info, _) -> FSharpGenericParameterMemberConstraint(cenv, info) + | TyparConstraint.MayResolveMember(info, _) -> FSharpGenericParameterMemberConstraint(cenv, info) | _ -> invalidOp "not a member constraint" member __.IsNonNullableValueTypeConstraint = diff --git a/src/fsharp/tast.fs b/src/fsharp/tast.fs index 8e5ba69dcd7..d09bd18cc2a 100755 --- a/src/fsharp/tast.fs +++ b/src/fsharp/tast.fs @@ -2029,6 +2029,14 @@ and override x.ToString() = x.Name +and TraitPossibleExtensionMemberSolutions = TraitPossibleExtensionMemberSolution list + +/// Only satisfied by type 'ExtensionMember'. Not stored in TastPickle. +and TraitPossibleExtensionMemberSolution = interface end + +/// Only satisfied by 'AccessorDomain'. Not stored in TastPickle. +and TraitAccessorDomain = interface end + and [] TyparConstraint = @@ -2042,7 +2050,7 @@ and | SupportsNull of range /// Indicates a constraint that a type has a member with the given signature - | MayResolveMember of TraitConstraintInfo * range + | MayResolveMember of TraitConstraintInfo * range /// Indicates a constraint that a type is a non-Nullable value type /// These are part of .NET's model of generic constraints, and in order to @@ -2078,20 +2086,36 @@ and [] TraitConstraintInfo = - /// TTrait(tys,nm,memFlags,argtys,rty,colution) + /// TTrait(tys, nm, memFlags, argtys, rty, solutionCell, extSlns, ad) /// /// Indicates the signature of a member constraint. Contains a mutable solution cell /// to store the inferred solution of the constraint. - | TTrait of TTypes * string * MemberFlags * TTypes * TType option * TraitConstraintSln option ref + | TTrait of TTypes * string * MemberFlags * TTypes * TType option * TraitConstraintSln option ref * extSlns: TraitPossibleExtensionMemberSolutions * ad: TraitAccessorDomain option + + /// Get the support types that can help provide members to solve the constraint + member x.SupportTypes= (let (TTrait(tys,_,_,_,_,_,_,_)) = x in tys) /// Get the member name associated with the member constraint. - member x.MemberName = (let (TTrait(_,nm,_,_,_,_)) = x in nm) + member x.MemberName = (let (TTrait(_,nm,_,_,_,_,_,_)) = x in nm) + + /// Get the argument types required of a member in order to solve the constraint + member x.ArgumentTypes = (let (TTrait(_,_,_,argtys,_,_,_,_)) = x in argtys) + /// Get the return type recorded in the member constraint. - member x.ReturnType = (let (TTrait(_,_,_,_,ty,_)) = x in ty) + member x.ReturnType = (let (TTrait(_,_,_,_,rty,_,_,_)) = x in rty) + /// Get or set the solution of the member constraint during inference member x.Solution - with get() = (let (TTrait(_,_,_,_,_,sln)) = x in sln.Value) - and set v = (let (TTrait(_,_,_,_,_,sln)) = x in sln.Value <- v) + with get() = (let (TTrait(_,_,_,_,_,sln,_,_)) = x in sln.Value) + and set v = (let (TTrait(_,_,_,_,_,sln,_,_)) = x in sln.Value <- v) + + /// Get possible extension member solutions available for a use of a trait at a particular location + member x.PossibleExtensionSolutions = (let (TTrait(_,_,_,_,_,_,extSlns,_)) = x in extSlns) + + /// Get access rights for a use of a trait at a particular location + member x.AccessorDomain = (let (TTrait(_,_,_,_,_,_,_,ad)) = x in ad) + + override x.ToString() = "trait " + x.MemberName and [] @@ -3531,7 +3555,7 @@ and + String.concat "," (List.map string tinst) + ")" | TType_fun (d,r) -> "(" + string d + " -> " + string r + ")" | TType_ucase (uc,tinst) -> "union case type " + uc.CaseName + (match tinst with [] -> "" | tys -> "<" + String.concat "," (List.map string tys) + ">") - | TType_var tp -> tp.DisplayName + | TType_var tp -> match tp.Solution with None -> tp.DisplayName | Some sln -> "�"+sln.ToString() | TType_measure ms -> sprintf "%A" ms /// For now, used only as a discriminant in error message. @@ -4177,7 +4201,7 @@ and | Label of ILCodeLabel /// Pseudo method calls. This is used for overloaded operations like op_Addition. - | TraitCall of TraitConstraintInfo + | TraitCall of TraitConstraintInfo /// Operation nodes representing C-style operations on byrefs and mutable vals (l-values) | LValueOp of LValueOperation * ValRef diff --git a/testfiles/test.fs b/testfiles/test.fs new file mode 100644 index 00000000000..a8862ead5e9 --- /dev/null +++ b/testfiles/test.fs @@ -0,0 +1,219 @@ +module Test + +type MyType = + | MyType of int + +/// Extending a .NET primitive type with new operator +module DotNetPrimtiveWithNewOperator = + type System.Int32 with + static member (++)(a: int, b: int) = a + + let result = 1 ++ 2 + +/// Extending a .NET primitive type with new operator +module DotNetPrimtiveWithAmbiguousNewOperator = + [] + module Extensions = + type System.Int32 with + static member (++)(a: int, b: int) = a + + [] + module Extensions2 = + type System.Int32 with + static member (++)(a: int, b: string) = a + + let f x = 1 ++ x + +/// Extending a .NET primitive type with new _internal_ operator +module DotNetPrimtiveWithInternalOperator1 = + type System.Int32 with + static member internal (++)(a: int, b: int) = a + + let result = 1 ++ 2 // this is now allowed + + +/// Extending a .NET primitive type with new _private_ operator where that operator is accessible at point-of-use +module DotNetPrimtiveWithAccessibleOperator2 = + type System.Int32 with + static member private (++)(a: int, b: int) = a + + let result = 1 ++ 2 // this is now allowed. + + + +#if NEGATIVE_TESTS +module DotNetPrimtiveWithInaccessibleOperator = + [] + module Extensions = + type System.Int32 with + static member private (++)(a: int, b: int) = a + + let result = 1 ++ 2 // This should fail to compile because the private member is not accessible from here +#endif + + +/// Locally extending an F# type with a wide range of standard operators +module FSharpTypeWithExtrinsicOperators = + + [] + module Extensions = + type MyType with + static member (+)(MyType x, MyType y) = MyType (x + y) + static member (*)(MyType x, MyType y) = MyType (x * y) + static member (/)(MyType x, MyType y) = MyType (x / y) + static member (-)(MyType x, MyType y) = MyType (x - y) + static member (~-)(MyType x) = MyType (-x) + static member (|||)(MyType x, MyType y) = MyType (x ||| y) + static member (&&&)(MyType x, MyType y) = MyType (x &&& y) + static member (^^^)(MyType x, MyType y) = MyType (x &&& y) + static member Zero = MyType 0 + static member One = MyType 1 + member this.Sign = let (MyType x) = this in sign x + static member Abs (MyType x) = MyType (abs x) + static member Sqrt (MyType x) = MyType (int (sqrt (float x))) + static member Sin (MyType x) = MyType (int (sin (float x))) + static member Cos (MyType x) = MyType (int (cos (float x))) + static member Tan (MyType x) = MyType (int (tan (float x))) + static member DivideByInt (MyType x, n: int) = MyType (x / n) + + let v = MyType 3 + let result1 = v + v + let result2 = v * v + let result3 = v - v + let result4 = v / v + let result5 = -v + let result6 = v ||| v + let result7 = v &&& v + let result8 = v ^^^ v + let result9 = LanguagePrimitives.GenericZero + let result10 = LanguagePrimitives.GenericOne + let result11 = sign v + let result12 = abs v + let result13 = sqrt v + let result14 = sin v + let result15 = cos v + let result16 = tan v + let result17 = LanguagePrimitives.DivideByInt v 4 + + +/// Extending two types with the static member 'Add' +module TwoTypesWithExtensionOfSameName = + + [] + module Extensions = + type System.Int32 with + static member Add(a: int, b: int) = a + + type MyType with + static member Add(MyType x, MyType y) = MyType (x + y) + + let inline addGeneric< ^A when ^A : (static member Add : ^A * ^A -> ^A) > (a,b) : ^A = + (^A : (static member Add : ^A * ^A -> ^A) (a,b)) + + let inline (+++) a b = addGeneric(a,b) + + let inline addGeneric2 (a,b) : ^A when ^A : (static member Add : ^A * ^A -> ^A) = + (^A : (static member Add : ^A * ^A -> ^A) (a,b)) + + let inline (++++) a b = addGeneric2(a,b) + + + let f () = + let v1 = addGeneric (MyType(1), MyType(2)) + let v2 = addGeneric (1,1) + () + + let f2 () = + let v1 = MyType(1) +++ MyType(2) + let v2 = 1 +++ 1 + 1 + + let f3 () = + let v1 = addGeneric2 (MyType(1), MyType(2)) + let v2 = addGeneric2 (1,1) + () + + let f4 () = + let v1 = MyType(1) ++++ MyType(2) + let v2 = 1 ++++ 1 + () + + +/// Extending a generic type with a property +module ExtendingGenericTypeWithProperty = + + type List<'T> with + member x.Count = x.Length + + let inline count (a : ^A when ^A : (member Count : int)) = + (^A : (member Count : int) (a)) + + let v0 = [3].Count // sanity check + + let v3 = count [3] + + let v5 = count (ResizeArray [| 3 |]) + +/// Extending a generic type with a property +/// Extending the .NET array type with a property +module ExtendingGenericTypeAndArrayWithProperty = + + type List<'T> with + member x.Count = x.Length + + type ``[]``<'T> with + member x.Count = x.Length + + let inline count (a : ^A when ^A : (member Count : int)) = + (^A : (member Count : int) (a)) + + let v0 = [3].Count // sanity check + + let v1 = [|3|].Count // sanity check + + let v3 = count [3] + + let v4 = count [| 3 |] + + let v5 = count (dict [| 1,3 |]) + + let v6 = count (ResizeArray [| 3 |]) // intrinsic from .NET + + + + +/// Solving using LINQ extensions +module LinqExtensionMethodsProvideSolutions_Count = + + open System.Linq + + // Note this looks for a _method_ called `Count` taking a single argument + // It is _not_ considered the same as a proprty called `Count` + let inline countm (a : ^A when ^A : (member Count : unit -> int)) = + (^A : (member Count : unit -> int) (a)) + + let seqv : seq = Seq.singleton 1 + + let v0 = seqv.Count // sanity check + + let v1 = countm seqv + +/// A random example +module ContainsKeyExample = + let inline containsKey (k: ^Key) (a : ^A when ^A : (member ContainsKey : ^Key -> bool)) = + (^A : (member ContainsKey : ^Key -> bool) (a,k)) + + let v5 = containsKey 1 (dict [| 1,3 |]) + + // Note that without 'inline' this doesn't become generic + let inline f x = containsKey x (dict [| (x,1) |]) + +(* +/// Not implemented +module MapExample = + let inline map (f: ^T -> ^U) (a : ^A when ^A : (val map : (^T -> ^U) -> ^A -> ^A2)) = + (^A : (val map : (^T -> ^U) -> ^A -> ^A2) (f, a)) + + let v5 = map (fun x -> x + 1) [ 1 .. 100 ] + +*) diff --git a/tests/fsharp/core/members/basics-hw-mutrec/test.fs b/tests/fsharp/core/members/basics-hw-mutrec/test.fs index c3421cee247..cf57a0a5929 100644 --- a/tests/fsharp/core/members/basics-hw-mutrec/test.fs +++ b/tests/fsharp/core/members/basics-hw-mutrec/test.fs @@ -1606,9 +1606,9 @@ module MultipleOverloadedOperatorTests = begin let f1 (x:DateTime) (y:TimeSpan) : DateTime = x - y let g1 (x:DateTime) (y:DateTime) : TimeSpan = x - y - // Return type is also sufficient: - let f2 (x:DateTime) y : DateTime = x - y - let g2 (x:DateTime) y : TimeSpan = x - y + // // Return type is not sufficient: + // let f2 (x:DateTime) y : DateTime = x - y + // let g2 (x:DateTime) y : TimeSpan = x - y // Just argument types are also sufficient: let f3 (x:DateTime) (y:TimeSpan) = x - y let g3 (x:DateTime) (y:DateTime) = x - y @@ -5549,7 +5549,7 @@ module Devdiv2_Bug_5385 = g "1" |> ignore; // note, use of non-generic 'g' within a generic, generalized memoized function 2 - and g : string -> int = memoize f // note, computed function value using generic “f” at an instance + and g : string -> int = memoize f // note, computed function value using generic �f� at an instance g "1" let res = test3e() diff --git a/tests/fsharp/core/members/basics-hw/test.fsx b/tests/fsharp/core/members/basics-hw/test.fsx index 2b807659d9a..bb01d42de51 100644 --- a/tests/fsharp/core/members/basics-hw/test.fsx +++ b/tests/fsharp/core/members/basics-hw/test.fsx @@ -1621,9 +1621,9 @@ module MultipleOverloadedOperatorTests = begin let f1 (x:DateTime) (y:TimeSpan) : DateTime = x - y let g1 (x:DateTime) (y:DateTime) : TimeSpan = x - y - // Return type is also sufficient: - let f2 (x:DateTime) y : DateTime = x - y - let g2 (x:DateTime) y : TimeSpan = x - y + // // Return type is not sufficient: + // let f2 (x:DateTime) y : DateTime = x - y + // let g2 (x:DateTime) y : TimeSpan = x - y // Just argument types are also sufficient: let f3 (x:DateTime) (y:TimeSpan) = x - y let g3 (x:DateTime) (y:DateTime) = x - y @@ -5584,7 +5584,7 @@ module Devdiv2_Bug_5385 = g "1" |> ignore; // note, use of non-generic 'g' within a generic, generalized memoized function 2 - and g : string -> int = memoize f // note, computed function value using generic “f” at an instance + and g : string -> int = memoize f // note, computed function value using generic �f� at an instance g "1" let res = test3e() diff --git a/tests/fsharp/core/members/basics/test.fs b/tests/fsharp/core/members/basics/test.fs index 5066bdf6ad0..267087eb51d 100644 --- a/tests/fsharp/core/members/basics/test.fs +++ b/tests/fsharp/core/members/basics/test.fs @@ -1910,9 +1910,9 @@ module MultipleOverloadedOperatorTests = begin let f1 (x:DateTime) (y:TimeSpan) : DateTime = x - y let g1 (x:DateTime) (y:DateTime) : TimeSpan = x - y - // Return type is also sufficient: - let f2 (x:DateTime) y : DateTime = x - y - let g2 (x:DateTime) y : TimeSpan = x - y + // Return type is not sufficient: + //let f2 (x:DateTime) y : DateTime = x - y + //let g2 (x:DateTime) y : TimeSpan = x - y // Just argument types are also sufficient: let f3 (x:DateTime) (y:TimeSpan) = x - y let g3 (x:DateTime) (y:DateTime) = x - y diff --git a/tests/fsharp/core/members/ops-mutrec/test.fs b/tests/fsharp/core/members/ops-mutrec/test.fs index 1fa82e5c373..b944fcc2d77 100644 --- a/tests/fsharp/core/members/ops-mutrec/test.fs +++ b/tests/fsharp/core/members/ops-mutrec/test.fs @@ -214,19 +214,18 @@ module BasicOverloadTests = // This gets type int -> int let f5 x = 1 - x - // This gets type DateTime -> DateTime -> TimeSpan, through non-conservative resolution. - let f6 x1 (x2:System.DateTime) = x1 - x2 + // // This gets type DateTime -> DateTime -> TimeSpan, through non-conservative resolution. + // let f6 x1 (x2:System.DateTime) = x1 - x2 - // This gets type TimeSpan -> TimeSpan -> TimeSpan, through non-conservative resolution. + // This gets type TimeSpan -> TimeSpan -> TimeSpan, through default type propagation let f7 x1 (x2:System.TimeSpan) = x1 - x2 - // This gets type TimeSpan -> TimeSpan -> TimeSpan, through non-conservative resolution. + // This gets type TimeSpan -> TimeSpan -> TimeSpan, through default type propagation let f8 x1 (x2:System.TimeSpan) = x2 - x1 - // This gets type TimeSpan -> TimeSpan -> TimeSpan, through non-conservative resolution. + // This gets type TimeSpan -> TimeSpan -> TimeSpan, through default type propagation let f9 (x1:System.TimeSpan) x2 = x1 - x2 - // This gets type TimeSpan -> TimeSpan -> TimeSpan let f10 x1 (x2:System.TimeSpan) = x1 + x2 diff --git a/tests/fsharp/core/members/ops/test.fsx b/tests/fsharp/core/members/ops/test.fsx index d4756db4233..6f943dce8f2 100644 --- a/tests/fsharp/core/members/ops/test.fsx +++ b/tests/fsharp/core/members/ops/test.fsx @@ -219,16 +219,16 @@ module BasicOverloadTests = // This gets type int -> int let f5 x = 1 - x - // This gets type DateTime -> DateTime -> TimeSpan, through non-conservative resolution. - let f6 x1 (x2:System.DateTime) = x1 - x2 + // // This gets type DateTime -> DateTime -> TimeSpan, through non-conservative resolution. + // let f6 x1 (x2:System.DateTime) = x1 - x2 - // This gets type TimeSpan -> TimeSpan -> TimeSpan, through non-conservative resolution. + // This gets type TimeSpan -> TimeSpan -> TimeSpan, through default type propagation let f7 x1 (x2:System.TimeSpan) = x1 - x2 - // This gets type TimeSpan -> TimeSpan -> TimeSpan, through non-conservative resolution. + // This gets type TimeSpan -> TimeSpan -> TimeSpan, through default type propagation let f8 x1 (x2:System.TimeSpan) = x2 - x1 - // This gets type TimeSpan -> TimeSpan -> TimeSpan, through non-conservative resolution. + // This gets type TimeSpan -> TimeSpan -> TimeSpan, through default type propagation let f9 (x1:System.TimeSpan) x2 = x1 - x2 diff --git a/tests/fsharp/core/subtype/test.fsx b/tests/fsharp/core/subtype/test.fsx index db98179a6d7..1aaa90a4fb5 100644 --- a/tests/fsharp/core/subtype/test.fsx +++ b/tests/fsharp/core/subtype/test.fsx @@ -232,8 +232,31 @@ module SomeRandomOperatorConstraints = begin let f2 x : float = x * x let f3 x (y:float) = x * y + //let neg4 x (y:System.DateTime) = x + y + + // This example resolves the type of "y" to "TimeSpam". It checks that a single "+" overload between + // two different types DateTime andd TimeSpan gets resolved via + // vis weak SRTP resolution using a DateTime constraint alone. let f5 (x:DateTime) y = x + y + + // This example checks a use of TimeSpan/DateTime overloads + let f5b (x:DateTime) (y:DateTime) = (x - y) + + + // This example checks a use of TimeSpan/DateTime overloads + let f5b2 (x:DateTime) (y:TimeSpan) = (x - y) + + // This example coincidentally checks that the return type is not taken into account before th list of method overloads + // is prepared in SRTP resolution. That is the type of (a - b) is immediately known (and we can use it for + // dot-notation name resolution of .TotalSeconds) _immediately_ that the types of a and b are + // known and _prior_ to generalization. + let f5c (x: DateTime) (y:DateTime) = + (x - y).TotalSeconds |> int + + let f5c2 (x: DateTime) (y:TimeSpan) = + (x - y).Second |> int + let f6 (x:int64) y = x + y let f7 x y : int64 = x + y let f8 x = Seq.reduce (+) x @@ -1744,6 +1767,40 @@ module GenericPropertyConstraintSolvedByRecord = let v = print_foo_memb { foo=1 } + +/// In this case, the presence of the Method(obj) overload meant overload resolution was being applied and resolving to that +/// overload, even before the full signature of the trait constraint was known. +module MethodOverloadingForTraitConstraintsIsNotDeterminedUntilSignatureIsKnnown = + type X = + static member Method (a: obj) = 1 + static member Method (a: int) = 2 + static member Method (a: int64) = 3 + + + let inline Test< ^t, ^a when ^t: (static member Method: ^a -> int)> (value: ^a) = + ( ^t: (static member Method: ^a -> int)(value)) + + let inline Test2< ^t> a = Test a + + check "slvde0vver90u" (Test2 0) 2 + +/// In this case, the presence of the "Equals" method on System.Object was causing method overloading to be resolved too +/// early, when ^t was not yet known. The underlying problem was that we were proceeding with weak resolution +/// even for a single-support-type trait constraint. +module MethodOverloadingForTraitConstraintsWhereSomeMethodsComeFromObjectTypeIsNotDeterminedTooEarly = + type Test() = + member __.Equals (_: Test) = true + + let inline Equals(a: obj) (b: ^t) = + match a with + | :? ^t as x -> (^t: (member Equals: ^t -> bool) (b, x)) + | _-> false + + let a = Test() + let b = Test() + + check "cewjewcwec09ew" (Equals a b) true + module SRTPFix = open System diff --git a/tests/fsharp/typecheck/sigs/neg99.bsl b/tests/fsharp/typecheck/sigs/neg99.bsl index 9f6010f249d..40bea962e9c 100644 --- a/tests/fsharp/typecheck/sigs/neg99.bsl +++ b/tests/fsharp/typecheck/sigs/neg99.bsl @@ -3,4 +3,4 @@ neg99.fs(19,16,19,64): typecheck error FS0077: Member constraints with the name neg99.fs(22,18,22,64): typecheck error FS0077: Member constraints with the name 'op_Explicit' are given special status by the F# compiler as certain .NET types are implicitly augmented with this member. This may result in runtime failures if you attempt to invoke the member constraint from your own code. -neg99.fs(25,39,25,43): typecheck error FS0043: The type 'CrashFSC.OhOh.MyByte' does not support a conversion to the type 'CrashFSC.OhOh.MyByte' +neg99.fs(25,39,25,43): typecheck error FS0043: The type 'CrashFSC.OhOh.MyByte' does not support a conversion to the type ''a' \ No newline at end of file diff --git a/tests/fsharp/typecheck/sigs/neg99.fs b/tests/fsharp/typecheck/sigs/neg99.fs index 6c3007c74ab..b7d248f13ab 100644 --- a/tests/fsharp/typecheck/sigs/neg99.fs +++ b/tests/fsharp/typecheck/sigs/neg99.fs @@ -12,7 +12,7 @@ module OhOh = static member inline op_Explicit (x: int64): MyByte = MyByte (byte x) static member inline op_Explicit (x: float): MyByte = MyByte (byte x) - static member inline op_Explicit (MyByte x): 'a = failwith "cannot convert" + //static member inline op_Explicit (MyByte x): 'a = failwith "cannot convert" /// testing testing let inline ( !>>> ) (a: ^a) min: ^b option = diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/TypeExtensions/basic/E_ExtensionOperator01.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/TypeExtensions/basic/E_ExtensionOperator01.fs index e038022643b..a2d10e07e4a 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/TypeExtensions/basic/E_ExtensionOperator01.fs +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/TypeExtensions/basic/E_ExtensionOperator01.fs @@ -1,26 +1,26 @@ // #Regression #Conformance #ObjectOrientedTypes #TypeExtensions // Regression for FSHARP1.0:3592 // Can't use extension methods to define operators -//Extension members cannot provide operator overloads\. Consider defining the operator as part of the type definition instead\. -//Extension members cannot provide operator overloads\. Consider defining the operator as part of the type definition instead\. //The type 'Exception' does not support the operator '\+'$ //The type 'Exception' does not support the operator '\+'$ //The type 'MyType' does not support the operator '\+'$ //The type 'MyType' does not support the operator '\+'$ + + open System type MyType() = member this.X = 1 -module TestExtensions = - type MyType with - static member (+) (e1: MyType, e2: MyType) = - new MyType() - - type System.Exception with - static member (+) (e1: Exception, e2: Exception) = - new Exception(e1.Message + " " + e2.Message) +//module TestExtensions = +// type MyType with +// static member (+) (e1: MyType, e2: MyType) = +// new MyType() +// +// type System.Exception with +// static member (+) (e1: Exception, e2: Exception) = +// new Exception(e1.Message + " " + e2.Message) let e1 = Exception() let e2 = Exception()