From 2faa6f30e593797e3d22635276c9aaf3054971c3 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 15 Mar 2019 23:43:09 +0000 Subject: [PATCH 01/77] witness passing draft --- src/fsharp/ConstraintSolver.fs | 119 ++------- src/fsharp/ConstraintSolver.fsi | 2 + src/fsharp/IlxGen.fs | 377 +++++++++++++++++------------ src/fsharp/MethodCalls.fs | 122 ++++++++++ src/fsharp/MethodOverrides.fs | 5 +- src/fsharp/NicePrint.fs | 2 +- src/fsharp/Optimizer.fs | 1 - src/fsharp/PostInferenceChecks.fs | 16 +- src/fsharp/PostInferenceChecks.fsi | 2 +- src/fsharp/QuotationTranslator.fs | 36 ++- src/fsharp/QuotationTranslator.fsi | 2 +- src/fsharp/TastOps.fs | 90 +++++-- src/fsharp/TastOps.fsi | 24 +- src/fsharp/TypeChecker.fs | 11 +- src/fsharp/infos.fs | 11 +- src/fsharp/tast.fs | 12 + 16 files changed, 520 insertions(+), 312 deletions(-) diff --git a/src/fsharp/ConstraintSolver.fs b/src/fsharp/ConstraintSolver.fs index dbe2feee9c6..72395fca76d 100644 --- a/src/fsharp/ConstraintSolver.fs +++ b/src/fsharp/ConstraintSolver.fs @@ -2752,112 +2752,29 @@ let AddCxTypeIsDelegate denv css m trace ty aty bty = (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) |> RaiseOperationResult -let CodegenWitnessThatTypeSupportsTraitConstraint tcVal g amap m (traitInfo:TraitConstraintInfo) argExprs = trackErrors { - let css = - { g = g - amap = amap - TcVal = tcVal - ExtraCxs = HashMultiMap(10, HashIdentity.Structural) - InfoReader = new InfoReader(g, amap) } +let CreateCodegenState tcVal g amap = + { g = g + amap = amap + TcVal = tcVal + ExtraCxs = HashMultiMap(10, HashIdentity.Structural) + InfoReader = new InfoReader(g, amap) } +let CodegenWitnessThatTypeSupportsTraitConstraint tcVal g amap m (traitInfo:TraitConstraintInfo) argExprs = trackErrors { + let css = CreateCodegenState tcVal g amap let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m (DisplayEnv.Empty g) let! _res = SolveMemberConstraint csenv true true 0 m NoTrace traitInfo - let sln = - match traitInfo.Solution with - | None -> Choice5Of5() - | Some sln -> - match sln with - | ILMethSln(origTy, extOpt, mref, minst) -> - let metadataTy = convertToTypeWithMetadataIfPossible g origTy - let tcref = tcrefOfAppTy g metadataTy - let mdef = IL.resolveILMethodRef tcref.ILTyconRawMetadata mref - let ilMethInfo = - match extOpt with - | None -> MethInfo.CreateILMeth(amap, m, origTy, mdef) - | Some ilActualTypeRef -> - let actualTyconRef = Import.ImportILTypeRef amap m ilActualTypeRef - MethInfo.CreateILExtensionMeth(amap, m, origTy, actualTyconRef, None, mdef) - Choice1Of5 (ilMethInfo, minst) - | FSMethSln(ty, vref, minst) -> - Choice1Of5 (FSMeth(g, ty, vref, None), minst) - | FSRecdFieldSln(tinst, rfref, isSetProp) -> - Choice2Of5 (tinst, rfref, isSetProp) - | FSAnonRecdFieldSln(anonInfo, tinst, i) -> - Choice3Of5 (anonInfo, tinst, i) - | BuiltInSln -> - Choice5Of5 () - | ClosedExprSln expr -> - Choice4Of5 expr - return! - match sln with - | Choice1Of5(minfo, methArgTys) -> - 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 - // fix - apply coercion for the arguments (excluding 'receiver' argument in instance calls) - - // 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) - |> List.concat - // do not apply coercion to the 'receiver' argument - let receiverArgOpt, argExprs = - if minfo.IsInstance then - match argExprs with - | 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 - | None -> convertedArgs - - // Fix bug 1281: If we resolve to an instance method on a struct and we haven't yet taken - // the address of the object then go do that - if minfo.IsStruct && minfo.IsInstance && (match argExprs with [] -> false | h :: _ -> not (isByrefTy g (tyOfExpr g h))) then - let h, t = List.headAndTail argExprs - let wrap, h', _readonly, _writeonly = 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 )) - - | Choice2Of5 (tinst, rfref, isSet) -> - let res = - match isSet, rfref.RecdField.IsStatic, argExprs.Length with - | true, true, 1 -> - Some (mkStaticRecdFieldSet (rfref, tinst, argExprs.[0], m)) - | true, false, 2 -> - // If we resolve to an instance field on a struct and we haven't yet taken - // the address of the object then go do that - if rfref.Tycon.IsStructOrEnumTycon && not (isByrefTy g (tyOfExpr g argExprs.[0])) then - let h = List.head argExprs - let wrap, h', _readonly, _writeonly = mkExprAddrOfExpr g true false DefinitelyMutates h None m - Some (wrap (mkRecdFieldSetViaExprAddr (h', rfref, tinst, argExprs.[1], m))) - else - Some (mkRecdFieldSetViaExprAddr (argExprs.[0], rfref, tinst, argExprs.[1], m)) - | false, true, 0 -> - Some (mkStaticRecdFieldGet (rfref, tinst, m)) - | false, false, 1 -> - if rfref.Tycon.IsStructOrEnumTycon && isByrefTy g (tyOfExpr g argExprs.[0]) then - Some (mkRecdFieldGetViaExprAddr (argExprs.[0], rfref, tinst, m)) - else - Some (mkRecdFieldGet g (argExprs.[0], rfref, tinst, m)) - | _ -> None - ResultD res - | Choice3Of5 (anonInfo, tinst, i) -> - let res = - let tupInfo = anonInfo.TupInfo - if evalTupInfoIsStruct tupInfo && isByrefTy g (tyOfExpr g argExprs.[0]) then - Some (mkAnonRecdFieldGetViaExprAddr (anonInfo, argExprs.[0], tinst, i, m)) - else - Some (mkAnonRecdFieldGet g (anonInfo, argExprs.[0], tinst, i, m)) - ResultD res - - | Choice4Of5 expr -> ResultD (Some (MakeApplicationAndBetaReduce g (expr, tyOfExpr g expr, [], argExprs, m))) - - | Choice5Of5 () -> ResultD None + let sln = GenWitnessExpr amap g m traitInfo argExprs + return sln } +let CodegenWitnessesForTyparInst tcVal g amap m typars tyargs = trackErrors { + let css = CreateCodegenState tcVal g amap + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m (DisplayEnv.Empty g) + let ftps, _renaming, tinst = FreshenTypeInst m typars + let cxs = GetTraitConstraintInfosOfTypars g ftps + do! SolveTypeEqualsTypeEqns csenv 0 m NoTrace None tinst tyargs + return MethodCalls.GenWitnessArgs amap g m cxs + } let ChooseTyparSolutionAndSolve css denv tp = let g = css.g diff --git a/src/fsharp/ConstraintSolver.fsi b/src/fsharp/ConstraintSolver.fsi index 4626c736bdb..92c642889bd 100644 --- a/src/fsharp/ConstraintSolver.fsi +++ b/src/fsharp/ConstraintSolver.fsi @@ -142,6 +142,8 @@ val AddCxTypeIsDelegate : DisplayEnv -> ConstraintSolverSt val CodegenWitnessThatTypeSupportsTraitConstraint : TcValF -> TcGlobals -> ImportMap -> range -> TraitConstraintInfo -> Expr list -> OperationResult +val CodegenWitnessesForTyparInst : TcValF -> TcGlobals -> ImportMap -> range -> Typars -> TType list -> OperationResult + val ChooseTyparSolutionAndSolve : ConstraintSolverState -> DisplayEnv -> Typar -> unit val IsApplicableMethApprox : TcGlobals -> ImportMap -> range -> MethInfo -> TType -> bool diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 1d503c8d767..7fb12462b84 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -9,6 +9,7 @@ module internal FSharp.Compiler.IlxGen open System.IO open System.Reflection open System.Collections.Generic +open System.Collections.Immutable open Internal.Utilities open Internal.Utilities.Collections @@ -229,9 +230,9 @@ type cenv = /// The ImportMap for reading IL amap: ImportMap - /// A callback for TcVal in the typechecker. Used to generalize values when finding witnesses. + /// A callback for tcVal in the typechecker. Used to generalize values when finding witnesses. /// It is unfortunate this is needed but it is until we supply witnesses through the compiation. - TcVal : ConstraintSolver.TcValF + tcVal : ConstraintSolver.TcValF /// The TAST for the assembly being emitted viewCcu: CcuThunk @@ -742,7 +743,7 @@ type ValStorage = /// Indicates the value is "stored" as a IL static method (in a "main" class for a F# /// compilation unit, or as a member) according to its inferred or specified arity. - | Method of ValReprInfo * ValRef * ILMethodSpec * Range.range * ArgReprInfo list * TType list * ArgReprInfo + | Method of ValReprInfo * ValRef * ILMethodSpec * Range.range * Typars * Typars * CurriedArgInfos * ArgReprInfo list * TraitWitnessInfos * TType list * ArgReprInfo /// Indicates the value is stored at the given position in the closure environment accessed via "ldarg 0" | Env of ILType * int * ILFieldSpec * NamedLocalIlxClosureInfo ref option @@ -814,6 +815,9 @@ and IlxGenEnv = /// All values in scope valsInScope: ValMap> + /// All witnesses in scope + witnessesInScope: ImmutableDictionary + /// For optimizing direct tail recursion to a loop - mark says where to branch to. Length is 0 or 1. /// REVIEW: generalize to arbitrary nested local loops?? innerVals: (ValRef * (BranchCallItem * Mark)) list @@ -877,7 +881,14 @@ let AddStorageForVal (g: TcGlobals) (v, s) eenv = else eenv -let AddStorageForLocalVals g vals eenv = List.foldBack (fun (v, s) acc -> AddStorageForVal g (v, notlazy s) acc) vals eenv +let AddStorageForLocalVals g vals eenv = + List.foldBack (fun (v, s) acc -> AddStorageForVal g (v, notlazy s) acc) vals eenv + +let AddStorageForLocalWitness eenv (w,s) = + { eenv with witnessesInScope = eenv.witnessesInScope.Add (w, s) } + +let AddStorageForLocalWitnesses eenv witnesses = + (eenv, witnesses) ||> List.fold AddStorageForLocalWitness //-------------------------------------------------------------------------- // Lookup eenv @@ -901,9 +912,9 @@ let IsValRefIsDllImport g (vref:ValRef) = /// as a method. let GetMethodSpecForMemberVal amap g (memberInfo:ValMemberInfo) (vref:ValRef) = let m = vref.Range - let tps, curriedArgInfos, returnTy, retInfo = + let tps, cxs, curriedArgInfos, returnTy, retInfo = assert(vref.ValReprInfo.IsSome) - GetTopValTypeInCompiledForm g (Option.get vref.ValReprInfo) vref.Type m + GetTopValTypeInCompiledForm g vref.ValReprInfo.Value vref.Type m let tyenvUnderTypars = TypeReprEnv.ForTypars tps let flatArgInfos = List.concat curriedArgInfos let isCtor = (memberInfo.MemberFlags.MemberKind = MemberKind.Constructor) @@ -945,18 +956,20 @@ let GetMethodSpecForMemberVal amap g (memberInfo:ValMemberInfo) (vref:ValRef) = thisArgTys let methodArgTys, paramInfos = List.unzip flatArgInfos let isSlotSig = memberInfo.MemberFlags.IsDispatchSlot || memberInfo.MemberFlags.IsOverrideOrExplicitImpl + let ilWitnessArgTys = GenTypes amap m tyenvUnderTypars (GenWitnessTys g cxs) let ilMethodArgTys = GenParamTypes amap m tyenvUnderTypars isSlotSig methodArgTys let ilMethodInst = GenTypeArgs amap m tyenvUnderTypars (List.map mkTyparTy mtps) - let mspec = mkILInstanceMethSpecInTy (ilTy, vref.CompiledName, ilMethodArgTys, ilActualRetTy, ilMethodInst) + let mspec = mkILInstanceMethSpecInTy (ilTy, vref.CompiledName, ilWitnessArgTys @ ilMethodArgTys, ilActualRetTy, ilMethodInst) - mspec, ctps, mtps, paramInfos, retInfo, methodArgTys + mspec, ctps, mtps, curriedArgInfos, paramInfos, retInfo, cxs, methodArgTys else let methodArgTys, paramInfos = List.unzip flatArgInfos + let ilWitnessArgTys = GenTypes amap m tyenvUnderTypars (GenWitnessTys g cxs) let ilMethodArgTys = GenParamTypes amap m tyenvUnderTypars false methodArgTys let ilMethodInst = GenTypeArgs amap m tyenvUnderTypars (List.map mkTyparTy mtps) - let mspec = mkILStaticMethSpecInTy (ilTy, vref.CompiledName, ilMethodArgTys, ilActualRetTy, ilMethodInst) + let mspec = mkILStaticMethSpecInTy (ilTy, vref.CompiledName, ilWitnessArgTys @ ilMethodArgTys, ilActualRetTy, ilMethodInst) - mspec, ctps, mtps, paramInfos, retInfo, methodArgTys + mspec, ctps, mtps, curriedArgInfos, paramInfos, retInfo, cxs, methodArgTys /// Determine how a top-level value is represented, when representing as a field, by computing an ILFieldSpec let ComputeFieldSpecForVal(optIntraAssemblyInfo:IlxGenIntraAssemblyInfo option, isInteractive, g, ilTyForProperty, vspec:Val, nm, m, cloc, ilTy, ilGetterMethRef) = @@ -993,23 +1006,24 @@ let ComputeStorageForFSharpValue amap g cloc optIntraAssemblyInfo optShadowLocal /// Compute the representation information for an F#-declared member let ComputeStorageForFSharpMember amap g topValInfo memberInfo (vref:ValRef) m = - let mspec, _, _, paramInfos, retInfo, methodArgTys = GetMethodSpecForMemberVal amap g memberInfo vref - Method (topValInfo, vref, mspec, m, paramInfos, methodArgTys, retInfo) + let mspec, ctps, mtps, curriedArgInfos, paramInfos, retInfo, witnessInfos, methodArgTys = GetMethodSpecForMemberVal amap g memberInfo vref + Method (topValInfo, vref, mspec, m, ctps, mtps, curriedArgInfos, paramInfos, witnessInfos, methodArgTys, retInfo) /// Compute the representation information for an F#-declared function in a module or an F#-decalared extension member. /// Note, there is considerable overlap with ComputeStorageForFSharpMember/GetMethodSpecForMemberVal and these could be /// rationalized. let ComputeStorageForFSharpFunctionOrFSharpExtensionMember amap g cloc topValInfo (vref:ValRef) m = let nm = vref.CompiledName - let (tps, curriedArgInfos, returnTy, retInfo) = GetTopValTypeInCompiledForm g topValInfo vref.Type m + let (tps, cxs, curriedArgInfos, returnTy, retInfo) = GetTopValTypeInCompiledForm g topValInfo vref.Type m let tyenvUnderTypars = TypeReprEnv.ForTypars tps - let (methodArgTys, paramInfos) = curriedArgInfos |> List.concat |> List.unzip - let ilMethodArgTys = GenParamTypes amap m tyenvUnderTypars false methodArgTys + let (argTys, paramInfos) = curriedArgInfos |> List.concat |> List.unzip + let ilMethodArgTys = GenParamTypes amap m tyenvUnderTypars false argTys let ilRetTy = GenReturnType amap m tyenvUnderTypars returnTy let ilLocTy = mkILTyForCompLoc cloc let ilMethodInst = GenTypeArgs amap m tyenvUnderTypars (List.map mkTyparTy tps) - let mspec = mkILStaticMethSpecInTy (ilLocTy, nm, ilMethodArgTys, ilRetTy, ilMethodInst) - Method (topValInfo, vref, mspec, m, paramInfos, methodArgTys, retInfo) + let ilWitnessArgTys = GenTypes amap m tyenvUnderTypars (GenWitnessTys g cxs) + let mspec = mkILStaticMethSpecInTy (ilLocTy, nm, (ilWitnessArgTys @ ilMethodArgTys), ilRetTy, ilMethodInst) + Method (topValInfo, vref, mspec, m, [], tps, curriedArgInfos, paramInfos, cxs, argTys, retInfo) /// Determine if an F#-declared value, method or function is compiled as a method. let IsFSharpValCompiledAsMethod g (v:Val) = @@ -2183,8 +2197,10 @@ let rec GenExpr (cenv:cenv) (cgbuf:CodeGenBuffer) eenv sp expr sequel = ) -> // application of local type functions with type parameters = measure types and body = local value - inine the body GenExpr cenv cgbuf eenv sp v sequel - | Expr.App(f,fty,tyargs,args,m) -> - GenApp cenv cgbuf eenv (f,fty,tyargs,args,m) sequel + + | Expr.App(f, fty, tyargs, curriedArgs, m) -> + GenApp cenv cgbuf eenv (f, fty, tyargs, curriedArgs, m) sequel + | Expr.Val(v,_,m) -> GenGetVal cenv cgbuf eenv (v,m) sequel @@ -2855,24 +2871,24 @@ and GenUntupledArgExpr cenv cgbuf eenv m argInfos expr sequel = // Generate calls (try to detect direct calls) //-------------------------------------------------------------------------- -and GenApp cenv cgbuf eenv (f, fty, tyargs, args, m) sequel = - match (f, tyargs, args) with - (* Look for tailcall to turn into branch *) +and GenApp cenv cgbuf eenv (f, fty, tyargs, curriedArgs, m) sequel = + match (f, tyargs, curriedArgs) with + // Look for tailcall to turn into branch | (Expr.Val(v, _, _), _, _) when match ListAssoc.tryFind cenv.g.valRefEq v eenv.innerVals with | Some (kind, _) -> (not v.IsConstructor && - (* when branch-calling methods we must have the right type parameters *) + // when branch-calling methods we must have the right type parameters (match kind with | BranchCallClosure _ -> true | BranchCallMethod (_, _, tps, _, _) -> (List.lengthsEqAndForall2 (fun ty tp -> typeEquiv cenv.g ty (mkTyparTy tp)) tyargs tps)) && - (* must be exact #args, ignoring tupling - we untuple if needed below *) + // must be exact #args, ignoring tupling - we untuple if needed below (let arityInfo = match kind with | BranchCallClosure arityInfo | BranchCallMethod (arityInfo, _, _, _, _) -> arityInfo - arityInfo.Length = args.Length + arityInfo.Length = curriedArgs.Length ) && (* no tailcall out of exception handler, etc. *) (match sequelIgnoringEndScopesAndDiscard sequel with Return | ReturnVoid -> true | _ -> false)) @@ -2883,15 +2899,15 @@ and GenApp cenv cgbuf eenv (f, fty, tyargs, args, m) sequel = match kind with | BranchCallClosure arityInfo -> let ntmargs = List.foldBack (+) arityInfo 0 - GenExprs cenv cgbuf eenv args + GenExprs cenv cgbuf eenv curriedArgs ntmargs | BranchCallMethod (arityInfo, curriedArgInfos, _, ntmargs, numObjArgs) -> assert (curriedArgInfos.Length = arityInfo.Length ) - assert (curriedArgInfos.Length = args.Length) + assert (curriedArgInfos.Length = curriedArgs.Length) //assert (curriedArgInfos.Length = ntmargs ) - GenUntupledArgsDiscardingLoneUnit cenv cgbuf eenv m numObjArgs curriedArgInfos args + GenUntupledArgsDiscardingLoneUnit cenv cgbuf eenv m numObjArgs curriedArgInfos curriedArgs if v.IsExtensionMember then - match curriedArgInfos, args with + match curriedArgInfos, curriedArgs with | [[]], [_] when numObjArgs = 0 -> (ntmargs-1) | [[_];[]], [_;_] when numObjArgs = 1 -> (ntmargs-1) | _ -> ntmargs @@ -2929,7 +2945,7 @@ and GenApp cenv cgbuf eenv (f, fty, tyargs, args, m) sequel = let storage = StorageForValRef m vref eenv match storage with - | Method (_, _, mspec, _, _, _, _) -> + | Method (_, _, mspec, _, _, _, _, _, _, _, _) -> CG.EmitInstr cgbuf (pop 0) (Push [cenv.g.iltyp_RuntimeMethodHandle]) (I_ldtoken (ILToken.ILMethod mspec)) | _ -> errorR(Error(FSComp.SR.ilxgenUnexpectedArgumentToMethodHandleOfDuringCodegen(), m)) @@ -2956,28 +2972,40 @@ and GenApp cenv cgbuf eenv (f, fty, tyargs, args, m) sequel = when (let storage = StorageForValRef m vref eenv match storage with - | Method (topValInfo, vref, _, _, _, _, _) -> + | Method (topValInfo, vref, _, _, _, _, _, _, _, _, _) -> (let tps, argtys, _, _ = GetTopValTypeInFSharpForm cenv.g topValInfo vref.Type m tps.Length = tyargs.Length && - argtys.Length <= args.Length) + argtys.Length <= curriedArgs.Length) | _ -> false) -> let storage = StorageForValRef m vref eenv match storage with - | Method (topValInfo, vref, mspec, _, _, _, _) -> - let nowArgs, laterArgs = - let _, curriedArgInfos, _, _ = GetTopValTypeInFSharpForm cenv.g topValInfo vref.Type m - List.splitAt curriedArgInfos.Length args + | Method (topValInfo, vref, mspec, _, ctps, mtps, curriedArgInfos, _, _, _, _) -> + let nowArgs, laterArgs = List.splitAt curriedArgInfos.Length curriedArgs let actualRetTy = applyTys cenv.g vref.Type (tyargs, nowArgs) - let _, curriedArgInfos, returnTy, _ = GetTopValTypeInCompiledForm cenv.g topValInfo vref.Type m + let _, _cxs, curriedArgInfos, returnTy, _ = GetTopValTypeInCompiledForm cenv.g topValInfo vref.Type m + + let witnessArgs = + let ctyargs, mtyargs = List.splitAt ctps.Length tyargs + + // Witness for enclosing type parameters must be passed to static members and constructors + // For non-extension instance methods they are stored as fields. + let cwitnesses = + if vref.IsInstanceMember && not vref.IsExtensionMember then + [] + else + ConstraintSolver.CodegenWitnessesForTyparInst cenv.tcVal cenv.g cenv.amap m ctps ctyargs |> CommitOperationResult + let mwitnesses = ConstraintSolver.CodegenWitnessesForTyparInst cenv.tcVal cenv.g cenv.amap m mtps mtyargs |> CommitOperationResult + cwitnesses @ mwitnesses + + let nowArgs = witnessArgs @ nowArgs let ilTyArgs = GenTypeArgs cenv.amap m eenv.tyenv tyargs - // For instance method calls chop off some type arguments, which are already // carried by the class. Also work out if it's a virtual call. - let _, virtualCall, newobj, isSuperInit, isSelfInit, _, _, _ = GetMemberCallInfo cenv.g (vref, valUseFlags) in + let _, virtualCall, newobj, isSuperInit, isSelfInit, _, _, _ = GetMemberCallInfo cenv.g (vref, valUseFlags) // numEnclILTypeArgs will include unit-of-measure args, unfortunately. For now, just cut-and-paste code from GetMemberCallInfo // @REVIEW: refactor this @@ -3076,12 +3104,12 @@ and GenApp cenv cgbuf eenv (f, fty, tyargs, args, m) sequel = // In this case we can often generate a type-specific local expression for the value. // This reduces the number of dynamic type applications. | (Expr.Val(vref, _, _), _, _) -> - GenGetValRefAndSequel cenv cgbuf eenv m vref (Some (tyargs, args, m, sequel)) + GenGetValRefAndSequel cenv cgbuf eenv m vref (Some (tyargs, curriedArgs, m, sequel)) | _ -> (* worst case: generate a first-class function value and call *) GenExpr cenv cgbuf eenv SPSuppress f Continue - GenArgsAndIndirectCall cenv cgbuf eenv (fty, tyargs, args, m) sequel + GenCurriedArgsAndIndirectCall cenv cgbuf eenv (fty, tyargs, curriedArgs, m) sequel and CanTailcall (hasStructObjArg, ccallInfo, withinSEH, hasByrefArg, mustGenerateUnitAfterCall, isDllImport, isSelfInit, makesNoCriticalTailcalls, sequel) = @@ -3128,14 +3156,14 @@ and GenNamedLocalTyFuncCall cenv (cgbuf: CodeGenBuffer) eenv ty cloinfo tyargs m /// Generate an indirect call, converting to an ILX callfunc instruction -and GenArgsAndIndirectCall cenv cgbuf eenv (functy, tyargs, args, m) sequel = +and GenCurriedArgsAndIndirectCall cenv cgbuf eenv (functy, tyargs, curriedArgs, m) sequel = - // Generate the arguments to the indirect call - GenExprs cenv cgbuf eenv args - GenIndirectCall cenv cgbuf eenv (functy, tyargs, args, m) sequel + // Generate the curried arguments to the indirect call + GenExprs cenv cgbuf eenv curriedArgs + GenIndirectCall cenv cgbuf eenv (functy, tyargs, curriedArgs, m) sequel /// Generate an indirect call, converting to an ILX callfunc instruction -and GenIndirectCall cenv cgbuf eenv (functy, tyargs, args, m) sequel = +and GenIndirectCall cenv cgbuf eenv (functy, tyargs, curriedArgs, m) sequel = // Fold in the new types into the environment as we generate the formal types. let ilxClosureApps = @@ -3148,18 +3176,15 @@ and GenIndirectCall cenv cgbuf eenv (functy, tyargs, args, m) sequel = // This does two phases: REVIEW: the code is too complex for what it's achieving and should be rewritten let formalRetTy, appBuilder = - List.fold - (fun (formalFuncTy, sofar) _ -> + ((formalFuncTy, id), curriedArgs) ||> List.fold (fun (formalFuncTy, appBuilder) _ -> let dty, rty = destFunTy cenv.g formalFuncTy - (rty, (fun acc -> sofar (Apps_app(GenType cenv.amap m feenv dty, acc))))) - (formalFuncTy, id) - args + (rty, (fun acc -> appBuilder (Apps_app(GenType cenv.amap m feenv dty, acc))))) let ilxRetApps = Apps_done (GenType cenv.amap m feenv formalRetTy) List.foldBack (fun tyarg acc -> Apps_tyapp(GenType cenv.amap m eenv.tyenv tyarg, acc)) tyargs (appBuilder ilxRetApps) - let actualRetTy = applyTys cenv.g functy (tyargs, args) + let actualRetTy = applyTys cenv.g functy (tyargs, curriedArgs) let ilActualRetTy = GenType cenv.amap m eenv.tyenv actualRetTy // Check if any byrefs are involved to make sure we don't tailcall @@ -3176,7 +3201,7 @@ and GenIndirectCall cenv cgbuf eenv (functy, tyargs, args, m) sequel = // Generate the code code an ILX callfunc operation let instrs = EraseClosures.mkCallFunc cenv.g.ilxPubCloEnv (fun ty -> cgbuf.AllocLocal([], ty, false) |> uint16) eenv.tyenv.Count isTailCall ilxClosureApps - CG.EmitInstrs cgbuf (pop (1+args.Length)) (Push [ilActualRetTy]) instrs + CG.EmitInstrs cgbuf (pop (1+curriedArgs.Length)) (Push [ilActualRetTy]) instrs // Done compiling indirect call... GenSequel cenv eenv.cloc cgbuf sequel @@ -3634,7 +3659,7 @@ and GenQuotation cenv cgbuf eenv (ast, conv, m, ety) sequel = | Some res -> res | None -> try - let qscope = QuotationTranslator.QuotationGenerationScope.Create (cenv.g, cenv.amap, cenv.viewCcu, QuotationTranslator.IsReflectedDefinition.No) + let qscope = QuotationTranslator.QuotationGenerationScope.Create (cenv.g, cenv.amap, cenv.viewCcu, cenv.tcVal, QuotationTranslator.IsReflectedDefinition.No) let astSpec = QuotationTranslator.ConvExprPublic qscope QuotationTranslator.QuotationTranslationEnv.Empty ast let referencedTypeDefs, spliceTypes, spliceArgExprs = qscope.Close() referencedTypeDefs, List.map fst spliceTypes, List.map fst spliceArgExprs, astSpec @@ -3727,17 +3752,26 @@ and MakeNotSupportedExnExpr cenv eenv (argExpr, m) = let mref = mkILCtorMethSpecForTy(ilty, [cenv.g.ilg.typ_String]).MethodRef Expr.Op(TOp.ILCall(false, false, false, true, NormalValUse, false, false, mref, [], [], [ety]), [], [argExpr], m) -and GenTraitCall cenv cgbuf eenv (traitInfo, argExprs, m) expr sequel = - let minfoOpt = CommitOperationResult (ConstraintSolver.CodegenWitnessThatTypeSupportsTraitConstraint cenv.TcVal cenv.g cenv.amap m traitInfo argExprs) - match minfoOpt with - | None -> - let exnArg = mkString cenv.g m (FSComp.SR.ilDynamicInvocationNotSupported(traitInfo.MemberName)) - let exnExpr = MakeNotSupportedExnExpr cenv eenv (exnArg, m) - let replacementExpr = mkThrow m (tyOfExpr cenv.g expr) exnExpr - GenExpr cenv cgbuf eenv SPSuppress replacementExpr sequel - | Some expr -> - let expr = cenv.optimizeDuringCodeGen expr - GenExpr cenv cgbuf eenv SPSuppress expr sequel +and GenTraitCall cenv cgbuf eenv (traitInfo: TraitConstraintInfo, argExprs, m) expr sequel = + match eenv.witnessesInScope.TryGetValue traitInfo.TraitKey with + | true, storage -> + + let ty = GenWitnessTy cenv.g traitInfo.TraitKey + GenGetStorageAndSequel cenv cgbuf eenv m (ty, GenType cenv.amap m eenv.tyenv ty) storage (Some([], argExprs, m, sequel)) + + | _ -> + assert false // We should now always find trait witnesses in scope + + let minfoOpt = CommitOperationResult (ConstraintSolver.CodegenWitnessThatTypeSupportsTraitConstraint cenv.tcVal cenv.g cenv.amap m traitInfo argExprs) + match minfoOpt with + | None -> + let exnArg = mkString cenv.g m (FSComp.SR.ilDynamicInvocationNotSupported(traitInfo.MemberName)) + let exnExpr = MakeNotSupportedExnExpr cenv eenv (exnArg, m) + let replacementExpr = mkThrow m (tyOfExpr cenv.g expr) exnExpr + GenExpr cenv cgbuf eenv SPSuppress replacementExpr sequel + | Some expr -> + let expr = cenv.optimizeDuringCodeGen expr + GenExpr cenv cgbuf eenv SPSuppress expr sequel //-------------------------------------------------------------------------- // Generate byref-related operations @@ -5150,11 +5184,12 @@ and GenBindingAfterSequencePoint cenv cgbuf eenv sp (TBind(vspec, rhsExpr, _)) s CommitStartScope cgbuf startScopeMarkOpt GenExpr cenv cgbuf eenv SPSuppress cctorBody discard - | Method (topValInfo, _, mspec, _, paramInfos, methodArgTys, retInfo) -> - let tps, ctorThisValOpt, baseValOpt, vsl, body', bodyty = IteratedAdjustArityOfLambda cenv.g cenv.amap topValInfo rhsExpr - let methodVars = List.concat vsl + | Method (topValInfo, _, mspec, _, ctps, mtps, curriedArgInfos, paramInfos, witnessInfos, argTys, retInfo) -> + let methLambdaTypars, methLambdaCtorThisValOpt, methLambdaBaseValOpt, methLambdaCurriedVars, methLambdaBody, methLambdaBodyTy = + IteratedAdjustArityOfLambda cenv.g cenv.amap topValInfo rhsExpr + let methLambdaVars = List.concat methLambdaCurriedVars CommitStartScope cgbuf startScopeMarkOpt - GenMethodForBinding cenv cgbuf eenv (vspec, mspec, access, paramInfos, retInfo) (topValInfo, ctorThisValOpt, baseValOpt, tps, methodVars, methodArgTys, body', bodyty) + GenMethodForBinding cenv cgbuf eenv (vspec, mspec, access, ctps, mtps, witnessInfos, curriedArgInfos, paramInfos, argTys, retInfo, topValInfo, methLambdaCtorThisValOpt, methLambdaBaseValOpt, methLambdaTypars, methLambdaVars, methLambdaBody, methLambdaBodyTy) | StaticProperty (ilGetterMethSpec, optShadowLocal) -> @@ -5428,58 +5463,65 @@ and GenParamAttribs cenv paramTy attribs = inFlag, outFlag, optionalFlag, defaultValue, Marshal, attribs /// Generate IL parameters -and GenParams cenv eenv (mspec:ILMethodSpec) (attribs:ArgReprInfo list) methodArgTys (implValsOpt: Val list option) = - let ilArgTys = mspec.FormalArgTypes - let argInfosAndTypes = - if List.length attribs = List.length ilArgTys then List.zip ilArgTys attribs - else ilArgTys |> List.map (fun ilArgTy -> ilArgTy, ValReprInfo.unnamedTopArg1) +and GenParams cenv eenv m (mspec:ILMethodSpec) witnessInfos (argInfos:ArgReprInfo list) methArgTys (implValsOpt: Val list option) = + let ilWitnessParams = GenWitnessParams cenv eenv m witnessInfos + let ilArgTys = mspec.FormalArgTypes |> List.skip witnessInfos.Length - let argInfosAndTypes = + let ilArgTysAndInfos = + if argInfos.Length = ilArgTys.Length then + List.zip ilArgTys argInfos + else + assert false + ilArgTys |> List.map (fun ilArgTy -> ilArgTy, ValReprInfo.unnamedTopArg1) + + let ilArgTysAndInfoAndVals = match implValsOpt with - | Some(implVals) when (implVals.Length = ilArgTys.Length) -> - List.map2 (fun x y -> x, Some y) argInfosAndTypes implVals + | Some implVals when (implVals.Length = ilArgTys.Length) -> + List.map2 (fun x y -> x, Some y) ilArgTysAndInfos implVals | _ -> - List.map (fun x -> x, None) argInfosAndTypes + List.map (fun x -> x, None) ilArgTysAndInfos - (Set.empty, List.zip methodArgTys argInfosAndTypes) - ||> List.mapFold (fun takenNames (methodArgTy, ((ilArgTy, topArgInfo), implValOpt)) -> - let inFlag, outFlag, optionalFlag, defaultParamValue, Marshal, attribs = GenParamAttribs cenv methodArgTy topArgInfo.Attribs + let ilParams, _ = + (Set.empty, List.zip methArgTys ilArgTysAndInfoAndVals) + ||> List.mapFold (fun takenNames (methodArgTy, ((ilArgTy, topArgInfo), implValOpt)) -> + let inFlag, outFlag, optionalFlag, defaultParamValue, Marshal, attribs = GenParamAttribs cenv methodArgTy topArgInfo.Attribs - let idOpt = (match topArgInfo.Name with - | Some v -> Some v - | None -> match implValOpt with - | Some v -> Some v.Id - | None -> None) - - let nmOpt, takenNames = - match idOpt with - | Some id -> - let nm = if takenNames.Contains(id.idText) then globalNng.FreshCompilerGeneratedName (id.idText, id.idRange) else id.idText - Some nm, takenNames.Add(nm) - | None -> - None, takenNames + let idOpt = (match topArgInfo.Name with + | Some v -> Some v + | None -> match implValOpt with + | Some v -> Some v.Id + | None -> None) + + let nmOpt, takenNames = + match idOpt with + | Some id -> + let nm = if takenNames.Contains(id.idText) then globalNng.FreshCompilerGeneratedName (id.idText, id.idRange) else id.idText + Some nm, takenNames.Add(nm) + | None -> + None, takenNames - let ilAttribs = GenAttrs cenv eenv attribs + let ilAttribs = GenAttrs cenv eenv attribs - let ilAttribs = - match GenReadOnlyAttributeIfNecessary cenv.g methodArgTy with - | Some attr -> ilAttribs @ [attr] - | None -> ilAttribs - - let param : ILParameter = - { Name=nmOpt - Type= ilArgTy - Default=defaultParamValue - Marshal=Marshal - IsIn=inFlag - IsOut=outFlag - IsOptional=optionalFlag - CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs ilAttribs) - MetadataIndex = NoMetadataIdx } - - param, takenNames) - |> fst + let ilAttribs = + match GenReadOnlyAttributeIfNecessary cenv.g methodArgTy with + | Some attr -> ilAttribs @ [attr] + | None -> ilAttribs + + let param : ILParameter = + { Name=nmOpt + Type= ilArgTy + Default=defaultParamValue + Marshal=Marshal + IsIn=inFlag + IsOut=outFlag + IsOptional=optionalFlag + CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs ilAttribs) + MetadataIndex = NoMetadataIdx } + + param, takenNames) + + ilWitnessParams @ ilParams /// Generate IL method return information and GenReturnInfo cenv eenv ilRetTy (retInfo : ArgReprInfo) : ILReturn = @@ -5585,39 +5627,50 @@ and ComputeMethodImplAttribs cenv (_v:Val) attrs = and GenMethodForBinding cenv cgbuf eenv - (v:Val, mspec, access, paramInfos, retInfo) - (topValInfo, ctorThisValOpt, baseValOpt, tps, methodVars, methodArgTys, body, returnTy) = + (v:Val, mspec, access, ctps, mtps, witnessInfos, curriedArgInfos, paramInfos, argTys, retInfo, topValInfo, + ctorThisValOpt, baseValOpt, methLambdaTypars, methLambdaVars, methLambdaBody, returnTy) = let m = v.Range let selfMethodVars, nonSelfMethodVars, compileAsInstance = match v.MemberInfo with | Some _ when ValSpecIsCompiledAsInstance cenv.g v -> - match methodVars with + match methLambdaVars with | [] -> error(InternalError("Internal error: empty argument list for instance method", v.Range)) | h::t -> [h], t, true - | _ -> [], methodVars, false + | _ -> [], methLambdaVars, false - let nonUnitNonSelfMethodVars, body = BindUnitVars cenv.g (nonSelfMethodVars, paramInfos, body) + let nonUnitNonSelfMethodVars, body = BindUnitVars cenv.g (nonSelfMethodVars, paramInfos, methLambdaBody) let nonUnitMethodVars = selfMethodVars@nonUnitNonSelfMethodVars - let cmtps, curriedArgInfos, _, _ = GetTopValTypeInCompiledForm cenv.g topValInfo v.Type v.Range let eenv = bindBaseOrThisVarOpt cenv eenv ctorThisValOpt let eenv = bindBaseOrThisVarOpt cenv eenv baseValOpt // The type parameters of the method's type are different to the type parameters // for the big lambda ("tlambda") of the implementation of the method. - let eenvUnderMethLambdaTypars = EnvForTypars tps eenv - let eenvUnderMethTypeTypars = EnvForTypars cmtps eenv + let eenvUnderMethLambdaTypars = EnvForTypars methLambdaTypars eenv + let eenvUnderMethTypeClassTypars = EnvForTypars ctps eenv + let eenvUnderMethTypeTypars = EnvForTypars mtps eenvUnderMethTypeClassTypars // Add the arguments to the environment. We add an implicit 'this' argument to constructors let isCtor = v.IsConstructor + + let methLambdaWitnessInfos = + let methLambdaParentTypars, methLambdaMethTypars = List.splitAt ctps.Length methLambdaTypars + GetTraitWitnessInfosOfTypars cenv.g methLambdaParentTypars methLambdaMethTypars + + // If this assert fails then there is a mismatch in the number of trait constraints on the method type and the number + // on the method implementation. + assert (methLambdaWitnessInfos.Length = witnessInfos.Length) + let eenvForMeth = let eenvForMeth = eenvUnderMethLambdaTypars let numImplicitArgs = if isCtor then 1 else 0 + let eenvForMeth = AddStorageForLocalWitnesses eenvForMeth (methLambdaWitnessInfos |> List.mapi (fun i w -> (w, Arg (numImplicitArgs+i)))) + let numImplicitArgs = numImplicitArgs + List.length witnessInfos let eenvForMeth = AddStorageForLocalVals cenv.g (List.mapi (fun i v -> (v, Arg (numImplicitArgs+i))) nonUnitMethodVars) eenvForMeth eenvForMeth - let tailCallInfo = [(mkLocalValRef v, BranchCallMethod (topValInfo.AritiesOfArgs, curriedArgInfos, tps, nonUnitMethodVars.Length, v.NumObjArgs))] + let tailCallInfo = [(mkLocalValRef v, BranchCallMethod (topValInfo.AritiesOfArgs, curriedArgInfos, methLambdaTypars, nonUnitMethodVars.Length, v.NumObjArgs))] // Discard the result on a 'void' return type. For a constructor just return 'void' let sequel = @@ -5629,7 +5682,7 @@ and GenMethodForBinding let hasPreserveSigNamedArg, ilMethodBody, hasDllImport = match TryFindFSharpAttributeOpt cenv.g cenv.g.attrib_DllImportAttribute v.Attribs with | Some (Attrib(_, _, [ AttribStringArg(dll) ], namedArgs, _, _, m)) -> - if not (isNil tps) then error(Error(FSComp.SR.ilSignatureForExternalFunctionContainsTypeParameters(), m)) + if not (isNil methLambdaTypars) then error(Error(FSComp.SR.ilSignatureForExternalFunctionContainsTypeParameters(), m)) let hasPreserveSigNamedArg, mbody = GenPInvokeMethod (v.CompiledName, dll, namedArgs) hasPreserveSigNamedArg, mbody, true @@ -5682,9 +5735,9 @@ and GenMethodForBinding [ yield! GenAttrs cenv eenv attrs yield! GenCompilationArgumentCountsAttr cenv v ] - let ilTypars = GenGenericParams cenv eenvUnderMethLambdaTypars tps - let ilParams = GenParams cenv eenv mspec paramInfos methodArgTys (Some(nonUnitNonSelfMethodVars)) - let ilReturn = GenReturnInfo cenv eenv mspec.FormalReturnType retInfo + let ilTypars = GenGenericParams cenv eenvUnderMethLambdaTypars methLambdaTypars + let ilParams = GenParams cenv eenvUnderMethTypeTypars m mspec witnessInfos paramInfos argTys (Some(nonUnitNonSelfMethodVars)) + let ilReturn = GenReturnInfo cenv eenvUnderMethTypeTypars mspec.FormalReturnType retInfo let methName = mspec.Name let tref = mspec.MethodRef.DeclaringTypeRef @@ -5917,7 +5970,7 @@ and GenSetStorage m cgbuf storage = | StaticProperty (ilGetterMethSpec, _) -> error(Error(FSComp.SR.ilStaticMethodIsNotLambda(ilGetterMethSpec.Name), m)) - | Method (_, _, mspec, m, _, _, _) -> + | Method (_, _, mspec, m, _, _, _, _, _, _, _) -> error(Error(FSComp.SR.ilStaticMethodIsNotLambda(mspec.Name), m)) | Null -> @@ -5930,23 +5983,28 @@ and GenSetStorage m cgbuf storage = // Note: ldarg0 has already been emitted in GenSetVal CG.EmitInstr cgbuf (pop 2) Push0 (mkNormalStfld ilField) -and CommitGetStorageSequel cenv cgbuf eenv m ty localCloInfo storeSequel = - match localCloInfo, storeSequel with - | Some {contents =NamedLocalIlxClosureInfoGenerator _cloinfo}, _ -> error(InternalError("Unexpected generator", m)) +and CommitGetStorageSequel cenv cgbuf eenv m ty localCloInfo fetchSequel = + match localCloInfo, fetchSequel with + | Some {contents =NamedLocalIlxClosureInfoGenerator _cloinfo}, _ -> + error(InternalError("Unexpected generator", m)) + | Some {contents =NamedLocalIlxClosureInfoGenerated cloinfo}, Some (tyargs, args, m, sequel) when not (isNil tyargs) -> let actualRetTy = GenNamedLocalTyFuncCall cenv cgbuf eenv ty cloinfo tyargs m CommitGetStorageSequel cenv cgbuf eenv m actualRetTy None (Some ([], args, m, sequel)) + | _, None -> () + | _, Some ([], [], _, sequel) -> GenSequel cenv eenv.cloc cgbuf sequel + | _, Some (tyargs, args, m, sequel) -> - GenArgsAndIndirectCall cenv cgbuf eenv (ty, tyargs, args, m) sequel + GenCurriedArgsAndIndirectCall cenv cgbuf eenv (ty, tyargs, args, m) sequel -and GenGetStorageAndSequel cenv cgbuf eenv m (ty, ilTy) storage storeSequel = +and GenGetStorageAndSequel cenv cgbuf eenv m (ty, ilTy) storage fetchSequel = match storage with | Local (idx, _, localCloInfo) -> EmitGetLocal cgbuf ilTy idx - CommitGetStorageSequel cenv cgbuf eenv m ty localCloInfo storeSequel + CommitGetStorageSequel cenv cgbuf eenv m ty localCloInfo fetchSequel | StaticField (fspec, _, hasLiteralAttr, ilContainerTy, _, _, ilGetterMethRef, _, _) -> // References to literals go directly to the field - no property is used @@ -5954,13 +6012,13 @@ and GenGetStorageAndSequel cenv cgbuf eenv m (ty, ilTy) storage storeSequel = EmitGetStaticField cgbuf ilTy fspec else CG.EmitInstr cgbuf (pop 0) (Push [ilTy]) (I_call(Normalcall, mkILMethSpecForMethRefInTy (ilGetterMethRef, ilContainerTy, []), None)) - CommitGetStorageSequel cenv cgbuf eenv m ty None storeSequel + CommitGetStorageSequel cenv cgbuf eenv m ty None fetchSequel | StaticProperty (ilGetterMethSpec, _) -> CG.EmitInstr cgbuf (pop 0) (Push [ilTy]) (I_call (Normalcall, ilGetterMethSpec, None)) - CommitGetStorageSequel cenv cgbuf eenv m ty None storeSequel + CommitGetStorageSequel cenv cgbuf eenv m ty None fetchSequel - | Method (topValInfo, vref, mspec, _, _, _, _) -> + | Method (topValInfo, vref, mspec, _, _, _, _, _, _, _, _) -> // Get a toplevel value as a first-class value. // We generate a lambda expression and that simply calls // the toplevel method. However we optimize the case where we are @@ -5971,7 +6029,7 @@ and GenGetStorageAndSequel cenv cgbuf eenv m (ty, ilTy) storage storeSequel = let expr, exprty = AdjustValForExpectedArity cenv.g m vref NormalValUse topValInfo // Then reduce out any arguments (i.e. apply the sequel immediately if we can...) - match storeSequel with + match fetchSequel with | None -> GenLambda cenv cgbuf eenv false None expr Continue | Some (tyargs', args, m, sequel) -> @@ -5982,16 +6040,16 @@ and GenGetStorageAndSequel cenv cgbuf eenv m (ty, ilTy) storage storeSequel = | Null -> CG.EmitInstr cgbuf (pop 0) (Push [ilTy]) (AI_ldnull) - CommitGetStorageSequel cenv cgbuf eenv m ty None storeSequel + CommitGetStorageSequel cenv cgbuf eenv m ty None fetchSequel | Arg i -> CG.EmitInstr cgbuf (pop 0) (Push [ilTy]) (mkLdarg (uint16 i)) - CommitGetStorageSequel cenv cgbuf eenv m ty None storeSequel + CommitGetStorageSequel cenv cgbuf eenv m ty None fetchSequel | Env (_, _, ilField, localCloInfo) -> // Note: ldarg 0 is emitted in 'cu_erase' erasure of the ldenv instruction CG.EmitInstrs cgbuf (pop 0) (Push [ilTy]) [ mkLdarg0; mkNormalLdfld ilField ] - CommitGetStorageSequel cenv cgbuf eenv m ty localCloInfo storeSequel + CommitGetStorageSequel cenv cgbuf eenv m ty localCloInfo fetchSequel and GenGetLocalVals cenv cgbuf eenvouter m fvs = List.iter (fun v -> GenGetLocalVal cenv cgbuf eenvouter m v None) fvs @@ -6217,7 +6275,7 @@ and GenAttr amap g eenv (Attrib(_, k, args, props, _, _, _)) = | ILAttrib(mref) -> mkILMethSpec(mref, AsObject, [], []) | FSAttrib(vref) -> assert(vref.IsMember) - let mspec, _, _, _, _, _ = GetMethodSpecForMemberVal amap g (Option.get vref.MemberInfo) vref + let mspec, _, _, _, _, _, _, _ = GetMethodSpecForMemberVal amap g (Option.get vref.MemberInfo) vref mspec let ilArgs = List.map2 (fun (AttribExpr(_, vexpr)) ty -> GenAttribArg amap g eenv vexpr ty) args mspec.FormalArgTypes mkILCustomAttribMethRef g.ilg (mspec, ilArgs, props) @@ -6539,6 +6597,19 @@ and GenFieldInit m c = | ConstToILFieldInit fieldInit -> fieldInit | _ -> error(Error(FSComp.SR.ilTypeCannotBeUsedForLiteralField(), m)) +and GenWitnessParams cenv eenv m (witnessInfos: TraitWitnessInfos) = + let witnessTys = GenWitnessTys cenv.g witnessInfos + witnessTys |> List.mapi (fun i ty -> + { Name=Some ("_witness" + string i) + Type= GenType cenv.amap m eenv.tyenv ty + Default=None + Marshal=None + IsIn=false + IsOut=false + IsOptional=false + CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs []) + MetadataIndex = NoMetadataIdx }: ILParameter) + and GenAbstractBinding cenv eenv tref (vref:ValRef) = assert(vref.IsMember) let m = vref.Range @@ -6550,11 +6621,11 @@ and GenAbstractBinding cenv eenv tref (vref:ValRef) = [ yield! GenAttrs cenv eenv attribs yield! GenCompilationArgumentCountsAttr cenv vref.Deref ] - let mspec, ctps, mtps, argInfos, retInfo, methodArgTys = GetMethodSpecForMemberVal cenv.amap cenv.g memberInfo vref + let mspec, ctps, mtps, _curriedArgInfos, argInfos, retInfo, witnessInfos, methArgTys = GetMethodSpecForMemberVal cenv.amap cenv.g memberInfo vref let eenvForMeth = EnvForTypars (ctps@mtps) eenv let ilMethTypars = GenGenericParams cenv eenvForMeth mtps let ilReturn = GenReturnInfo cenv eenvForMeth mspec.FormalReturnType retInfo - let ilParams = GenParams cenv eenvForMeth mspec argInfos methodArgTys None + let ilParams = GenParams cenv eenvForMeth m mspec witnessInfos argInfos methArgTys None let compileAsInstance = ValRefIsCompiledAsInstanceMember cenv.g vref let mdef = mkILGenericVirtualMethod (vref.CompiledName, ILMemberAccess.Public, ilMethTypars, ilParams, ilReturn, MethodBody.Abstract) @@ -6595,7 +6666,7 @@ and GenAbstractBinding cenv eenv tref (vref:ValRef) = and GenToStringMethod cenv eenv ilThisTy m = [ match (eenv.valsInScope.TryFind cenv.g.sprintf_vref.Deref, eenv.valsInScope.TryFind cenv.g.new_format_vref.Deref) with - | Some(Lazy(Method(_, _, sprintfMethSpec, _, _, _, _))), Some(Lazy(Method(_, _, newFormatMethSpec, _, _, _, _))) -> + | Some(Lazy(Method(_, _, sprintfMethSpec, _, _, _, _, _, _, _, _))), Some(Lazy(Method(_, _, newFormatMethSpec, _, _, _, _, _, _, _, _))) -> // The type returned by the 'sprintf' call let funcTy = EraseClosures.mkILFuncTy cenv.g.ilxPubCloEnv ilThisTy cenv.g.ilg.typ_String // Give the instantiation of the printf format object, i.e. a Format`5 object compatible with StringFormat @@ -6924,7 +6995,7 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon:Tycon) = let (|Lazy|) (x:Lazy<_>) = x.Force() match (eenv.valsInScope.TryFind cenv.g.sprintf_vref.Deref, eenv.valsInScope.TryFind cenv.g.new_format_vref.Deref) with - | Some(Lazy(Method(_, _, sprintfMethSpec, _, _, _, _))), Some(Lazy(Method(_, _, newFormatMethSpec, _, _, _, _))) -> + | Some(Lazy(Method(_, _, sprintfMethSpec, _, _, _, _, _, _, _, _))), Some(Lazy(Method(_, _, newFormatMethSpec, _, _, _, _, _, _, _, _))) -> // The type returned by the 'sprintf' call let funcTy = EraseClosures.mkILFuncTy cenv.g.ilxPubCloEnv ilThisTy cenv.g.ilg.typ_String // Give the instantiation of the printf format object, i.e. a Format`5 object compatible with StringFormat @@ -7368,12 +7439,18 @@ let CodegenAssembly cenv eenv mgbuf fileImpls = // structures representing the contents of the module. //------------------------------------------------------------------------- -let GetEmptyIlxGenEnv (ilg : ILGlobals) ccu = +let GetEmptyIlxGenEnv (g : TcGlobals) ccu = let thisCompLoc = CompLocForCcu ccu { tyenv=TypeReprEnv.Empty cloc = thisCompLoc valsInScope=ValMap<_>.Empty - someTypeInThisAssembly=ilg.typ_Object (* dummy value *) + witnessesInScope= + ImmutableDictionary.Create( + { new IEqualityComparer<_> with + member __.Equals(a, b) = traitKeysAEquiv g TypeEquivEnv.Empty a b + member __.GetHashCode(a) = hash a.MemberName + }) + someTypeInThisAssembly= g.ilg.typ_Object // dummy value isFinalFile = false letBoundVars=[] liveLocals=IntMap.empty() @@ -7414,7 +7491,7 @@ let GenerateCode (cenv, anonTypeTable, eenv, TypedAssemblyAfterOptimization file match reflectedDefinitions with | [] -> [] | _ -> - let qscope = QuotationTranslator.QuotationGenerationScope.Create (cenv.g, cenv.amap, cenv.viewCcu, QuotationTranslator.IsReflectedDefinition.Yes) + let qscope = QuotationTranslator.QuotationGenerationScope.Create (cenv.g, cenv.amap, cenv.viewCcu, cenv.tcVal, QuotationTranslator.IsReflectedDefinition.Yes) let defns = reflectedDefinitions |> List.choose (fun ((methName, v), e) -> try @@ -7559,7 +7636,7 @@ let ClearGeneratedValue (ctxt: ExecutionContext) (_g:TcGlobals) eenv (v:Val) = type IlxAssemblyGenerator(amap: ImportMap, tcGlobals: TcGlobals, tcVal : ConstraintSolver.TcValF, ccu: Tast.CcuThunk) = // The incremental state held by the ILX code generator - let mutable ilxGenEnv = GetEmptyIlxGenEnv tcGlobals.ilg ccu + let mutable ilxGenEnv = GetEmptyIlxGenEnv tcGlobals ccu let anonTypeTable = AnonTypeGenerationTable() let intraAssemblyInfo = { StaticFieldInfo = new Dictionary<_, _>(HashIdentity.Structural) } let casApplied = new Dictionary() @@ -7577,7 +7654,7 @@ type IlxAssemblyGenerator(amap: ImportMap, tcGlobals: TcGlobals, tcVal : Constra member __.GenerateCode (codeGenOpts, typedAssembly, assemAttribs, moduleAttribs) = let cenv : cenv = { g=tcGlobals - TcVal = tcVal + tcVal = tcVal viewCcu = ccu ilUnitTy = None amap = amap diff --git a/src/fsharp/MethodCalls.fs b/src/fsharp/MethodCalls.fs index e754ce22d09..150eb0a2980 100644 --- a/src/fsharp/MethodCalls.fs +++ b/src/fsharp/MethodCalls.fs @@ -1327,3 +1327,125 @@ exception FieldNotMutable of DisplayEnv * Tast.RecdFieldRef * range let CheckRecdFieldMutation m denv (rfinfo:RecdFieldInfo) = if not rfinfo.RecdField.IsMutable then error (FieldNotMutable(denv, rfinfo.RecdFieldRef, m)) + +let GenWitnessExpr amap g m (traitInfo: TraitConstraintInfo) argExprs = + + let sln = + match traitInfo.Solution with + | None -> Choice5Of5() + | Some sln -> + match sln with + | ILMethSln(origTy, extOpt, mref, minst) -> + let metadataTy = convertToTypeWithMetadataIfPossible g origTy + let tcref = tcrefOfAppTy g metadataTy + let mdef = resolveILMethodRef tcref.ILTyconRawMetadata mref + let ilMethInfo = + match extOpt with + | None -> MethInfo.CreateILMeth(amap, m, origTy, mdef) + | Some ilActualTypeRef -> + let actualTyconRef = Import.ImportILTypeRef amap m ilActualTypeRef + MethInfo.CreateILExtensionMeth(amap, m, origTy, actualTyconRef, None, mdef) + Choice1Of5 (ilMethInfo, minst) + | FSMethSln(ty, vref, minst) -> + Choice1Of5 (FSMeth(g, ty, vref, None), minst) + | FSRecdFieldSln(tinst, rfref, isSetProp) -> + Choice2Of5 (tinst, rfref, isSetProp) + | FSAnonRecdFieldSln(anonInfo, tinst, i) -> + Choice3Of5 (anonInfo, tinst, i) + | BuiltInSln -> + Choice5Of5 () + | ClosedExprSln expr -> + Choice4Of5 expr + + match sln with + | Choice1Of5(minfo, methArgTys) -> + 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 + // fix - apply coercion for the arguments (excluding 'receiver' argument in instance calls) + + // 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) + |> List.concat + // do not apply coercion to the 'receiver' argument + let receiverArgOpt, argExprs = + if minfo.IsInstance then + match argExprs with + | 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 + | None -> convertedArgs + + // Fix bug 1281: If we resolve to an instance method on a struct and we haven't yet taken + // the address of the object then go do that + if minfo.IsStruct && minfo.IsInstance && (match argExprs with [] -> false | h :: _ -> not (isByrefTy g (tyOfExpr g h))) then + let h, t = List.headAndTail argExprs + let wrap, h', _readonly, _writeonly = mkExprAddrOfExpr g true false PossiblyMutates h None m + Some (wrap (Expr.Op(TOp.TraitCall(traitInfo), [], (h' :: t), m))) + else + Some (MakeMethInfoCall amap m minfo methArgTys argExprs ) + + | Choice2Of5 (tinst, rfref, isSet) -> + match isSet, rfref.RecdField.IsStatic, argExprs.Length with + | true, true, 1 -> + Some (mkStaticRecdFieldSet (rfref, tinst, argExprs.[0], m)) + | true, false, 2 -> + // If we resolve to an instance field on a struct and we haven't yet taken + // the address of the object then go do that + if rfref.Tycon.IsStructOrEnumTycon && not (isByrefTy g (tyOfExpr g argExprs.[0])) then + let h = List.head argExprs + let wrap, h', _readonly, _writeonly = mkExprAddrOfExpr g true false DefinitelyMutates h None m + Some (wrap (mkRecdFieldSetViaExprAddr (h', rfref, tinst, argExprs.[1], m))) + else + Some (mkRecdFieldSetViaExprAddr (argExprs.[0], rfref, tinst, argExprs.[1], m)) + | false, true, 0 -> + Some (mkStaticRecdFieldGet (rfref, tinst, m)) + | false, false, 1 -> + if rfref.Tycon.IsStructOrEnumTycon && isByrefTy g (tyOfExpr g argExprs.[0]) then + Some (mkRecdFieldGetViaExprAddr (argExprs.[0], rfref, tinst, m)) + else + Some (mkRecdFieldGet g (argExprs.[0], rfref, tinst, m)) + | _ -> None + + | Choice3Of5 (anonInfo, tinst, i) -> + let tupInfo = anonInfo.TupInfo + if evalTupInfoIsStruct tupInfo && isByrefTy g (tyOfExpr g argExprs.[0]) then + Some (mkAnonRecdFieldGetViaExprAddr (anonInfo, argExprs.[0], tinst, i, m)) + else + Some (mkAnonRecdFieldGet g (anonInfo, argExprs.[0], tinst, i, m)) + + | Choice4Of5 expr -> + Some (MakeApplicationAndBetaReduce g (expr, tyOfExpr g expr, [], argExprs, m)) + + | Choice5Of5 () -> + None + +(* +let MakeNotSupportedExnExpr amap g eenv (argExpr, m) = + let ety = mkAppTy (cenv.g.FindSysTyconRef ["System"] "NotSupportedException") [] + let ilty = GenType cenv.amap m eenv.tyenv ety + let mref = mkILCtorMethSpecForTy(ilty, [cenv.g.ilg.typ_String]).MethodRef + Expr.Op(TOp.ILCall(false, false, false, true, NormalValUse, false, false, mref, [], [], [ety]), [], [argExpr], m) +*) + +let GenWitnessExprLambda amap g m (traitInfo: TraitConstraintInfo) = + // TODO: use arg infos + let argtysl = GenWitnessArgTys traitInfo.TraitKey + let vse = argtysl |> List.mapiSquared (fun i j ty -> mkCompGenLocal m ("_warg" + string i + "_" + string j) ty) + let vsl = List.mapSquared fst vse + match GenWitnessExpr amap g m traitInfo (List.concat (List.mapSquared snd vse)) with + | Some expr -> + mkMemberLambdas m [] None None vsl (expr, tyOfExpr g expr) + | None -> + // TODO: generate builtin + // let exnArg = mkString g m (FSComp.SR.ilDynamicInvocationNotSupported(traitInfo.MemberName)) + // let exnExpr = MakeNotSupportedExnExpr cenv eenv (exnArg, m) + // let replacementExpr = mkThrow m (tyOfExpr cenv.g expr) exnExpr + mkOne g m + +let GenWitnessArgs amap g m (traitInfos: TraitConstraintInfo list) = + [ for traitInfo in traitInfos -> GenWitnessExprLambda amap g m traitInfo ] diff --git a/src/fsharp/MethodOverrides.fs b/src/fsharp/MethodOverrides.fs index a58ecf2ce64..d4d69b20d7a 100644 --- a/src/fsharp/MethodOverrides.fs +++ b/src/fsharp/MethodOverrides.fs @@ -87,7 +87,8 @@ module DispatchSlotChecking = /// Get the override info for a value being used to implement a dispatch slot. let GetTypeMemberOverrideInfo g reqdTy (overrideBy:ValRef) = - let _, argInfos, retTy, _ = GetTypeOfMemberInMemberForm g overrideBy + // TODO: consider witnesses w.r.t. overriding methods as types get more specialized.... + let _, _cxs, argInfos, retTy, _ = GetTypeOfMemberInMemberForm g overrideBy let nm = overrideBy.LogicalName let argTys = argInfos |> List.mapSquared fst @@ -126,7 +127,7 @@ module DispatchSlotChecking = /// Get the override information for an object expression method being used to implement dispatch slots let GetObjectExprOverrideInfo g amap (implty, id:Ident, memberFlags, ty, arityInfo, bindingAttribs, rhsExpr) = // Dissect the type - let tps, argInfos, retTy, _ = GetMemberTypeInMemberForm g memberFlags arityInfo ty id.idRange + let tps, _cxs, argInfos, retTy, _ = GetMemberTypeInMemberForm g memberFlags arityInfo ty id.idRange let argTys = argInfos |> List.mapSquared fst // Dissect the implementation let _, ctorThisValOpt, baseValOpt, vsl, rhsExpr, _ = destTopLambda g amap arityInfo (rhsExpr, ty) diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index 5cd213918c4..279021bd8c0 100755 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -668,7 +668,7 @@ module private PrintTypes = PrintIL.layoutILTypeRef denv tref ++ argsL | FSAttrib vref -> // REVIEW: this is not trimming "Attribute" - let _,_,rty,_ = GetTypeOfMemberInMemberForm denv.g vref + let _, _cxs, _, rty, _ = GetTypeOfMemberInMemberForm denv.g vref let rty = GetFSharpViewOfReturnType denv.g rty let tcref = tcrefOfAppTy denv.g rty layoutTyconRef denv tcref ++ argsL diff --git a/src/fsharp/Optimizer.fs b/src/fsharp/Optimizer.fs index 51c74b2ae35..dc85ff23c15 100644 --- a/src/fsharp/Optimizer.fs +++ b/src/fsharp/Optimizer.fs @@ -2919,7 +2919,6 @@ and OptimizeLambdas (vspec: Val option) cenv env topValInfo e ety = let expr2 = mkMemberLambdas m tps ctorThisValOpt None vsl (bodyR, bodyty) CurriedLambdaValue (lambdaId, arities, bsize, expr2, ety) - let estimatedSize = match vspec with | Some v when v.IsCompiledAsTopLevel -> methodDefnTotalSize diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index f691f4f0b9e..5b16fe345a3 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -198,7 +198,10 @@ type cenv = isInternalTestSpanStackReferring: bool // outputs mutable usesQuotations : bool - mutable entryPointGiven:bool } + mutable entryPointGiven:bool + + /// Callback required for quotation generation + tcVal: ConstraintSolver.TcValF } /// Check if the value is an argument of a function let IsValArgument env (v: Val) = @@ -939,7 +942,7 @@ and CheckExpr (cenv:cenv) (env:env) origExpr (context:PermitByRefExpr) : Limit = // Translate to quotation data try - let qscope = QuotationTranslator.QuotationGenerationScope.Create (g, cenv.amap, cenv.viewCcu, QuotationTranslator.IsReflectedDefinition.No) + let qscope = QuotationTranslator.QuotationGenerationScope.Create (g, cenv.amap, cenv.viewCcu, cenv.tcVal, QuotationTranslator.IsReflectedDefinition.No) let qdata = QuotationTranslator.ConvExprPublic qscope QuotationTranslator.QuotationTranslationEnv.Empty ast let typeDefs, spliceTypes, spliceExprs = qscope.Close() match savedConv.Value with @@ -1718,7 +1721,7 @@ and CheckBinding cenv env alwaysCheckNoReraise context (TBind(v, bindRhs, _) as | Expr.TyLambda (_, tps, b, _, _) -> tps, b, applyForallTy g ety (List.map mkTyparTy tps) | _ -> [], bindRhs, ety let env = QuotationTranslator.QuotationTranslationEnv.Empty.BindTypars tps - let qscope = QuotationTranslator.QuotationGenerationScope.Create (g, cenv.amap, cenv.viewCcu, QuotationTranslator.IsReflectedDefinition.Yes) + let qscope = QuotationTranslator.QuotationGenerationScope.Create (g, cenv.amap, cenv.viewCcu, cenv.tcVal, QuotationTranslator.IsReflectedDefinition.Yes) QuotationTranslator.ConvExprPublic qscope env taue |> ignore let _, _, argExprs = qscope.Close() if not (isNil argExprs) then @@ -2256,7 +2259,7 @@ and CheckModuleSpec cenv env x = let env = { env with reflect = env.reflect || HasFSharpAttribute cenv.g cenv.g.attrib_ReflectedDefinitionAttribute mspec.Attribs } CheckDefnInModule cenv env rhs -let CheckTopImpl (g, amap, reportErrors, infoReader, internalsVisibleToPaths, viewCcu, denv , mexpr, extraAttribs, (isLastCompiland:bool*bool), isInternalTestSpanStackReferring) = +let CheckTopImpl (g, amap, reportErrors, infoReader, internalsVisibleToPaths, viewCcu, tcVal, denv , mexpr, extraAttribs, (isLastCompiland:bool*bool), isInternalTestSpanStackReferring) = let cenv = { g =g reportErrors=reportErrors @@ -2272,7 +2275,8 @@ let CheckTopImpl (g, amap, reportErrors, infoReader, internalsVisibleToPaths, vi viewCcu= viewCcu isLastCompiland=isLastCompiland isInternalTestSpanStackReferring = isInternalTestSpanStackReferring - entryPointGiven=false} + entryPointGiven=false + tcVal = tcVal} // Certain type equality checks go faster if these TyconRefs are pre-resolved. // This is because pre-resolving allows tycon equality to be determined by pointer equality on the entities. @@ -2295,7 +2299,7 @@ let CheckTopImpl (g, amap, reportErrors, infoReader, internalsVisibleToPaths, vi reflect=false external=false returnScope = 0 - isInAppExpr = false } + isInAppExpr = false } CheckModuleExpr cenv env mexpr CheckAttribs cenv env extraAttribs diff --git a/src/fsharp/PostInferenceChecks.fsi b/src/fsharp/PostInferenceChecks.fsi index 25c6bf3ac35..e6b01b4e65a 100644 --- a/src/fsharp/PostInferenceChecks.fsi +++ b/src/fsharp/PostInferenceChecks.fsi @@ -11,4 +11,4 @@ open FSharp.Compiler.Tastops open FSharp.Compiler.TcGlobals /// Perform the checks on the TAST for a file after type inference is complete. -val CheckTopImpl : TcGlobals * ImportMap * bool * InfoReader * CompilationPath list * CcuThunk * DisplayEnv * ModuleOrNamespaceExprWithSig * Attribs * (bool * bool) * isInternalTestSpanStackReferring: bool -> bool * StampMap +val CheckTopImpl : TcGlobals * ImportMap * bool * InfoReader * CompilationPath list * CcuThunk * ConstraintSolver.TcValF * DisplayEnv * ModuleOrNamespaceExprWithSig * Attribs * (bool * bool) * isInternalTestSpanStackReferring: bool -> bool * StampMap diff --git a/src/fsharp/QuotationTranslator.fs b/src/fsharp/QuotationTranslator.fs index 6deca36555e..19d42466128 100644 --- a/src/fsharp/QuotationTranslator.fs +++ b/src/fsharp/QuotationTranslator.fs @@ -36,6 +36,7 @@ type QuotationGenerationScope = { g: TcGlobals amap: Import.ImportMap scope: CcuThunk + tcVal : ConstraintSolver.TcValF // Accumulate the references to type definitions referencedTypeDefs: ResizeArray referencedTypeDefsTable: Dictionary @@ -47,10 +48,11 @@ type QuotationGenerationScope = quotationFormat : QuotationSerializationFormat mutable emitDebugInfoInQuotations : bool } - static member Create (g: TcGlobals, amap, scope, isReflectedDefinition) = + static member Create (g: TcGlobals, amap, scope, tcVal, isReflectedDefinition) = { g = g scope = scope amap = amap + tcVal = tcVal referencedTypeDefs = new ResizeArray<_>() referencedTypeDefsTable = new Dictionary<_, _>() typeSplices = new ResizeArray<_>() @@ -241,18 +243,19 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP. let (numEnclTypeArgs, _, isNewObj, valUseFlags, isSelfInit, takesInstanceArg, isPropGet, isPropSet) = GetMemberCallInfo cenv.g (vref, vFlags) - let isMember, tps, curriedArgInfos, retTy = + // TODO: numEnclTypeArgs/ctps for constraints + let isMember, tps, _cxs, curriedArgInfos, retTy = match vref.MemberInfo with | Some _ when not vref.IsExtensionMember -> // This is an application of a member method // We only count one argument block for these. - let tps, curriedArgInfos, retTy, _ = GetTypeOfIntrinsicMemberInCompiledForm cenv.g vref - true, tps, curriedArgInfos, retTy + let tps, cxs, curriedArgInfos, retTy, _ = GetTypeOfIntrinsicMemberInCompiledForm cenv.g vref + true, tps, cxs, curriedArgInfos, retTy | _ -> // This is an application of a module value or extension member let arities = arityOfVal vref.Deref - let tps, curriedArgInfos, retTy, _ = GetTopValTypeInCompiledForm cenv.g arities vref.Type m - false, tps, curriedArgInfos, retTy + let tps, cxs, curriedArgInfos, retTy, _ = GetTopValTypeInCompiledForm cenv.g arities vref.Type m + false, tps, cxs, curriedArgInfos, retTy // Compute the object arguments as they appear in a compiled call // Strip off the object argument, if any. The curriedArgInfos are already adjusted to compiled member form @@ -301,11 +304,13 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP. if verboseCReflect then dprintfn "vref.DisplayName = %A , after unit adjust, #untupledCurriedArgs = %A, #curriedArgInfos = %d" vref.DisplayName (List.map List.length untupledCurriedArgs) curriedArgInfos.Length + + let witnessArgs = ConstraintSolver.CodegenWitnessesForTyparInst cenv.tcVal cenv.g cenv.amap m tps tyargs |> CommitOperationResult + let subCall = if isMember then - // This is an application of a member method - // We only count one argument block for these. - let callArgs = (objArgs::untupledCurriedArgs) |> List.concat + + let callArgs = (objArgs::witnessArgs::untupledCurriedArgs) |> List.concat let parentTyconR = ConvTyconRef cenv vref.TopValDeclaringEntity m let isNewObj = isNewObj || valUseFlags || isSelfInit @@ -319,7 +324,9 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP. ConvObjectModelCall cenv env m (isPropGet, isPropSet, isNewObj, parentTyconR, methArgTypesR, methRetTypeR, methName, tyargs, numGenericArgs, callArgs) else // This is an application of the module value. + // TODO: witnessArgs ConvModuleValueApp cenv env m vref tyargs untupledCurriedArgs + match curriedArgs, curriedArgInfos with // static member and module value unit argument elimination | [arg:Expr], [[]] -> @@ -735,7 +742,7 @@ and ConvObjectModelCallCore cenv env m (isPropGet, isPropSet, isNewObj, parentTy and ConvModuleValueApp cenv env m (vref:ValRef) tyargs (args: Expr list list) = EmitDebugInfoIfNecessary cenv env m (ConvModuleValueAppCore cenv env m vref tyargs args) -and ConvModuleValueAppCore cenv env m (vref:ValRef) tyargs (args: Expr list list) = +and ConvModuleValueAppCore cenv env m (vref:ValRef) tyargs (curriedArgs: Expr list list) = match vref.DeclaringEntity with | ParentNone -> failwith "ConvModuleValueApp" | Parent(tcref) -> @@ -743,7 +750,8 @@ and ConvModuleValueAppCore cenv env m (vref:ValRef) tyargs (args: Expr list list let tcrefR = ConvTyconRef cenv tcref m let tyargsR = ConvTypes cenv env m tyargs let nm = vref.CompiledName - let argsR = List.map (ConvExprs cenv env) args + let argsR = List.map (ConvExprs cenv env) curriedArgs + // TODO: augment mkModuleValueApp with hidden witness args and hidden entry point QP.mkModuleValueApp(tcrefR, nm, isProperty, tyargsR, argsR) and ConvExprs cenv env args = @@ -1060,7 +1068,8 @@ let ConvMethodBase cenv env (methName, v:Val) = | Some vspr when not v.IsExtensionMember -> let vref = mkLocalValRef v - let tps, argInfos, retTy, _ = GetTypeOfMemberInMemberForm cenv.g vref + // TODO: representation of witnesses + let tps, _cxs, argInfos, retTy, _ = GetTypeOfMemberInMemberForm cenv.g vref let numEnclTypeArgs = vref.MemberApparentEntity.TyparsNoRange.Length let argTys = argInfos |> List.concat |> List.map fst @@ -1087,7 +1096,8 @@ let ConvMethodBase cenv env (methName, v:Val) = | _ when v.IsExtensionMember -> - let tps, argInfos, retTy, _ = GetTopValTypeInCompiledForm cenv.g v.ValReprInfo.Value v.Type v.Range + // TODO: witnesses? + let tps, _cxs, argInfos, retTy, _ = GetTopValTypeInCompiledForm cenv.g v.ValReprInfo.Value v.Type v.Range let argTys = argInfos |> List.concat |> List.map fst let envinner = BindFormalTypars env tps let methArgTypesR = ConvTypes cenv envinner m argTys diff --git a/src/fsharp/QuotationTranslator.fsi b/src/fsharp/QuotationTranslator.fsi index 184f1d3da4e..930a56879ad 100755 --- a/src/fsharp/QuotationTranslator.fsi +++ b/src/fsharp/QuotationTranslator.fsi @@ -32,7 +32,7 @@ type QuotationSerializationFormat = [] type QuotationGenerationScope = - static member Create: TcGlobals * ImportMap * CcuThunk * IsReflectedDefinition -> QuotationGenerationScope + static member Create: TcGlobals * ImportMap * CcuThunk * ConstraintSolver.TcValF * IsReflectedDefinition -> QuotationGenerationScope member Close: unit -> ILTypeRef list * (TType * range) list * (Expr * range) list static member ComputeQuotationFormat : TcGlobals -> QuotationSerializationFormat diff --git a/src/fsharp/TastOps.fs b/src/fsharp/TastOps.fs index 21b82215eda..729eec7cce2 100644 --- a/src/fsharp/TastOps.fs +++ b/src/fsharp/TastOps.fs @@ -905,6 +905,13 @@ let rec traitsAEquivAux erasureFlag g aenv (TTrait(tys1, nm, mf1, argtys, rty, _ returnTypesAEquivAux erasureFlag g aenv rty rty2 && List.lengthsEqAndForall2 (typeAEquivAux erasureFlag g aenv) argtys argtys2 +and traitKeysAEquivAux erasureFlag g aenv (TraitWitnessInfo(tys1, nm, mf1, argtys, rty)) (TraitWitnessInfo(tys2, nm2, mf2, argtys2, rty2)) = + mf1 = mf2 && + nm = nm2 && + ListSet.equals (typeAEquivAux erasureFlag g aenv) tys1 tys2 && + returnTypesAEquivAux erasureFlag g aenv rty rty2 && + List.lengthsEqAndForall2 (typeAEquivAux erasureFlag g aenv) argtys argtys2 + and returnTypesAEquivAux erasureFlag g aenv rty rty2 = match rty, rty2 with | None, None -> true @@ -1020,6 +1027,7 @@ and typeEquivAux erasureFlag g ty1 ty2 = typeAEquivAux erasureFlag g TypeEquivEn let typeAEquiv g aenv ty1 ty2 = typeAEquivAux EraseNone g aenv ty1 ty2 let typeEquiv g ty1 ty2 = typeEquivAux EraseNone g ty1 ty2 let traitsAEquiv g aenv t1 t2 = traitsAEquivAux EraseNone g aenv t1 t2 +let traitKeysAEquiv g aenv t1 t2 = traitKeysAEquivAux EraseNone g aenv t1 t2 let typarConstraintsAEquiv g aenv c1 c2 = typarConstraintsAEquivAux EraseNone g aenv c1 c2 let typarsAEquiv g aenv d1 d2 = typarsAEquivAux EraseNone g aenv d1 d2 let returnTypesAEquiv g aenv t1 t2 = returnTypesAEquivAux EraseNone g aenv t1 t2 @@ -1541,8 +1549,11 @@ let tryDestRefTupleTy g ty = if isRefTupleTy g ty then destRefTupleTy g ty else [ty] type UncurriedArgInfos = (TType * ArgReprInfo) list + type CurriedArgInfos = (TType * ArgReprInfo) list list +type TraitWitnessInfos = TraitWitnessInfo list + // A 'tau' type is one with its type parameters stripped off let GetTopTauTypeInFSharpForm g (curriedArgInfos: ArgReprInfo list list) tau m = let nArgInfos = curriedArgInfos.Length @@ -2242,8 +2253,21 @@ let checkMemberVal membInfo arity m = let checkMemberValRef (vref:ValRef) = checkMemberVal vref.MemberInfo vref.ValReprInfo vref.Range +// Get information about the as-ye-unsolved constraints for a set of typars +let GetTraitConstraintInfosOfTypars g (tps: Typars) = + let cxs = tps |> List.collect (fun tp -> tp.Constraints |> List.choose (fun cx -> match cx with TyparConstraint.MayResolveMember(traitInfo, _) -> Some traitInfo | _ -> None)) + let cxs = cxs |> ListSet.setify (traitsAEquiv g TypeEquivEnv.Empty) + cxs + +// Get information about the runtime witnesses needed for a set of generalized typars +let GetTraitWitnessInfosOfTypars g parentTypars tps = + let tps = tps |> List.filter (fun tp -> not (parentTypars |> List.exists (typarEq tp))) + let cxs = GetTraitConstraintInfosOfTypars g tps + cxs |> List.map (fun cx -> cx.TraitKey) + let GetTopValTypeInCompiledForm g topValInfo ty m = let tps, paramArgInfos, rty, retInfo = GetTopValTypeInFSharpForm g topValInfo ty m + let witnessInfos = GetTraitWitnessInfosOfTypars g [] tps // TODO: parentTypars // Eliminate lone single unit arguments let paramArgInfos = match paramArgInfos, topValInfo.ArgInfos with @@ -2258,7 +2282,7 @@ let GetTopValTypeInCompiledForm g topValInfo ty m = | _ -> paramArgInfos let rty = if isUnitTy g rty then None else Some rty - (tps, paramArgInfos, rty, retInfo) + (tps, witnessInfos, paramArgInfos, rty, retInfo) // Pull apart the type for an F# value that represents an object model method // and see the "member" form for the type, i.e. @@ -2270,6 +2294,7 @@ let GetTopValTypeInCompiledForm g topValInfo ty m = // many arguments the method takes etc. let GetMemberTypeInMemberForm g memberFlags topValInfo ty m = let tps, paramArgInfos, rty, retInfo = GetMemberTypeInFSharpForm g memberFlags topValInfo ty m + let witnessInfos = GetTraitWitnessInfosOfTypars g [] tps // TODO: parentTypars // Eliminate lone single unit arguments let paramArgInfos = match paramArgInfos, topValInfo.ArgInfos with @@ -2284,7 +2309,7 @@ let GetMemberTypeInMemberForm g memberFlags topValInfo ty m = | _ -> paramArgInfos let rty = if isUnitTy g rty then None else Some rty - (tps, paramArgInfos, rty, retInfo) + (tps, witnessInfos, paramArgInfos, rty, retInfo) let GetTypeOfMemberInMemberForm g (vref:ValRef) = //assert (not vref.IsExtensionMember) @@ -2326,7 +2351,7 @@ let PartitionValRefTypars g (vref: ValRef) = PartitionValTypars g vref.Deref /// Get the arguments for an F# value that represents an object model method let ArgInfosOfMemberVal g (v:Val) = let membInfo, topValInfo = checkMemberVal v.MemberInfo v.ValReprInfo v.Range - let _, arginfos, _, _ = GetMemberTypeInMemberForm g membInfo.MemberFlags topValInfo v.Type v.Range + let _, _cxs, arginfos, _, _ = GetMemberTypeInMemberForm g membInfo.MemberFlags topValInfo v.Type v.Range arginfos let ArgInfosOfMember g (vref: ValRef) = @@ -2344,13 +2369,13 @@ let ReturnTypeOfPropertyVal g (v:Val) = let membInfo, topValInfo = checkMemberVal v.MemberInfo v.ValReprInfo v.Range match membInfo.MemberFlags.MemberKind with | MemberKind.PropertySet -> - let _, arginfos, _, _ = GetMemberTypeInMemberForm g membInfo.MemberFlags topValInfo v.Type v.Range + let _, _cxs, arginfos, _, _ = GetMemberTypeInMemberForm g membInfo.MemberFlags topValInfo v.Type v.Range if not arginfos.IsEmpty && not arginfos.Head.IsEmpty then arginfos.Head |> List.last |> fst else error(Error(FSComp.SR.tastValueDoesNotHaveSetterType(), v.Range)) | MemberKind.PropertyGet -> - let _, _, rty, _ = GetMemberTypeInMemberForm g membInfo.MemberFlags topValInfo v.Type v.Range + let _, _cxs, _, rty, _ = GetMemberTypeInMemberForm g membInfo.MemberFlags topValInfo v.Type v.Range GetFSharpViewOfReturnType g rty | _ -> error(InternalError("ReturnTypeOfPropertyVal", v.Range)) @@ -2363,7 +2388,7 @@ let ArgInfosOfPropertyVal g (v:Val) = | MemberKind.PropertyGet -> ArgInfosOfMemberVal g v |> List.concat | MemberKind.PropertySet -> - let _, arginfos, _, _ = GetMemberTypeInMemberForm g membInfo.MemberFlags topValInfo v.Type v.Range + let _, _cxs, arginfos, _, _ = GetMemberTypeInMemberForm g membInfo.MemberFlags topValInfo v.Type v.Range if not arginfos.IsEmpty && not arginfos.Head.IsEmpty then arginfos.Head |> List.frontAndBack |> fst else @@ -7616,9 +7641,28 @@ let LinearizeTopMatch g parent = function //--------------------------------------------------------------------------- -// XmlDoc signatures +// Witnesses //--------------------------------------------------------------------------- +let GenWitnessArgTys (traitInfo: TraitWitnessInfo) = + let (TraitWitnessInfo(tys, _nm, memFlags, argtys, _rty)) = traitInfo + let argtysl = List.map List.singleton argtys + match tys with + | _ when not memFlags.IsInstance -> argtysl + | [ty] when memFlags.IsInstance -> [ty] :: argtysl + | _ -> failwith "can't generate choosy instance members yet" + +let GenWitnessTy (g: TcGlobals) (traitInfo: TraitWitnessInfo) = + let rty = match traitInfo.ReturnType with None -> g.unit_ty | Some ty -> ty + let argtysl = GenWitnessArgTys traitInfo + mkMethodTy g argtysl rty + +let GenWitnessTys (g: TcGlobals) (cxs: TraitWitnessInfos) = + cxs |> List.map (GenWitnessTy g) + +//--------------------------------------------------------------------------- +// XmlDoc signatures +//--------------------------------------------------------------------------- let commaEncs strs = String.concat "," strs let angleEnc str = "{" + str + "}" @@ -7700,9 +7744,9 @@ and tyargsEnc g (gtpsType, gtpsMethod) args = | [a] when (match (stripTyEqns g a) with TType_measure _ -> true | _ -> false) -> "" // float should appear as just "float" in the generated .XML xmldoc file | _ -> angleEnc (commaEncs (List.map (typeEnc g (gtpsType, gtpsMethod)) args)) -let XmlDocArgsEnc g (gtpsType, gtpsMethod) argTs = - if isNil argTs then "" - else "(" + String.concat "," (List.map (typeEnc g (gtpsType, gtpsMethod)) argTs) + ")" +let XmlDocArgsEnc g (gtpsType, gtpsMethod) argTys = + if isNil argTys then "" + else "(" + String.concat "," (List.map (typeEnc g (gtpsType, gtpsMethod)) argTys) + ")" let buildAccessPath (cp : CompilationPath option) = match cp with @@ -7713,16 +7757,17 @@ let buildAccessPath (cp : CompilationPath option) = let prependPath path name = if path = "" then name else path + "." + name let XmlDocSigOfVal g path (v:Val) = - let parentTypars, methTypars, argInfos, prefix, path, name = + let parentTypars, methTypars, cxs, argInfos, prefix, path, name = // CLEANUP: this is one of several code paths that treat module values and members // separately when really it would be cleaner to make sure GetTopValTypeInFSharpForm, GetMemberTypeInFSharpForm etc. // were lined up so code paths like this could be uniform + // TODO: representation of constraint witnesses match v.MemberInfo with | Some membInfo when not v.IsExtensionMember -> - (* Methods, Properties etc. *) - let tps, argInfos, _, _ = GetMemberTypeInMemberForm g membInfo.MemberFlags (Option.get v.ValReprInfo) v.Type v.Range + // Methods, Properties etc. + let tps, cxs, argInfos, _, _ = GetMemberTypeInMemberForm g membInfo.MemberFlags (Option.get v.ValReprInfo) v.Type v.Range let prefix, name = match membInfo.MemberFlags.MemberKind with | MemberKind.ClassConstructor @@ -7736,18 +7781,21 @@ let XmlDocSigOfVal g path (v:Val) = match PartitionValTypars g v with | Some(_, memberParentTypars, memberMethodTypars, _, _) -> memberParentTypars, memberMethodTypars | None -> [], tps - parentTypars, methTypars, argInfos, prefix, path, name + parentTypars, methTypars, cxs, argInfos, prefix, path, name | _ -> // Regular F# values and extension members let w = arityOfVal v - let tps, argInfos, _, _ = GetTopValTypeInCompiledForm g w v.Type v.Range + let tps, cxs, argInfos, _, _ = GetTopValTypeInCompiledForm g w v.Type v.Range let name = v.CompiledName let prefix = if w.NumCurriedArgs = 0 && isNil tps then "P:" else "M:" - [], tps, argInfos, prefix, path, name - let argTs = argInfos |> List.concat |> List.map fst - let args = XmlDocArgsEnc g (parentTypars, methTypars) argTs + [], tps, cxs, argInfos, prefix, path, name + + let witnessArgTys = GenWitnessTys g cxs + let argTys = argInfos |> List.concat |> List.map fst + let argTys = witnessArgTys @ argTys + let args = XmlDocArgsEnc g (parentTypars, methTypars) argTys let arity = List.length methTypars in (* C# XML doc adds `` to *generic* member names *) let genArity = if arity=0 then "" else sprintf "``%d" arity prefix + prependPath path name + genArity + args @@ -8616,7 +8664,7 @@ let EvalLiteralExprOrAttribArg g x = let GetTypeOfIntrinsicMemberInCompiledForm g (vref:ValRef) = assert (not vref.IsExtensionMember) let membInfo, topValInfo = checkMemberValRef vref - let tps, argInfos, rty, retInfo = GetTypeOfMemberInMemberForm g vref + let tps, cxs, argInfos, rty, retInfo = GetTypeOfMemberInMemberForm g vref let argInfos = // Check if the thing is really an instance member compiled as a static member // If so, the object argument counts as a normal argument in the compiled form @@ -8628,7 +8676,7 @@ let GetTypeOfIntrinsicMemberInCompiledForm g (vref:ValRef) = argInfos | h::_ -> h ::argInfos else argInfos - tps, argInfos, rty, retInfo + tps, cxs, argInfos, rty, retInfo //-------------------------------------------------------------------------- @@ -8851,5 +8899,3 @@ let isThreadOrContextStatic g attrs = let mkUnitDelayLambda (g: TcGlobals) m e = let uv, _ = mkCompGenLocal m "unitVar" g.unit_ty mkLambda m uv (e, tyOfExpr g e) - - diff --git a/src/fsharp/TastOps.fsi b/src/fsharp/TastOps.fsi index 6098625122f..9b3ae08a8eb 100755 --- a/src/fsharp/TastOps.fsi +++ b/src/fsharp/TastOps.fsi @@ -723,6 +723,8 @@ type UncurriedArgInfos = (TType * ArgReprInfo) list type CurriedArgInfos = UncurriedArgInfos list +type TraitWitnessInfos = TraitWitnessInfo list + val destTopForallTy : TcGlobals -> ValReprInfo -> TType -> Typars * TType val GetTopTauTypeInFSharpForm : TcGlobals -> ArgReprInfo list list -> TType -> range -> CurriedArgInfos * TType @@ -733,7 +735,7 @@ val IsCompiledAsStaticProperty : TcGlobals -> Val -> bool val IsCompiledAsStaticPropertyWithField : TcGlobals -> Val -> bool -val GetTopValTypeInCompiledForm : TcGlobals -> ValReprInfo -> TType -> range -> Typars * CurriedArgInfos * TType option * ArgReprInfo +val GetTopValTypeInCompiledForm : TcGlobals -> ValReprInfo -> TType -> range -> Typars * TraitWitnessInfos * CurriedArgInfos * TType option * ArgReprInfo val GetFSharpViewOfReturnType : TcGlobals -> TType option -> TType @@ -829,6 +831,10 @@ val traitsAEquivAux : Erasure -> TcGlobals -> TypeEquivEnv -> TraitCon val traitsAEquiv : TcGlobals -> TypeEquivEnv -> TraitConstraintInfo -> TraitConstraintInfo -> bool +val traitKeysAEquivAux : Erasure -> TcGlobals -> TypeEquivEnv -> TraitWitnessInfo -> TraitWitnessInfo -> bool + +val traitKeysAEquiv : TcGlobals -> TypeEquivEnv -> TraitWitnessInfo -> TraitWitnessInfo -> bool + val typarConstraintsAEquivAux : Erasure -> TcGlobals -> TypeEquivEnv -> TyparConstraint -> TyparConstraint -> bool val typarConstraintsAEquiv : TcGlobals -> TypeEquivEnv -> TyparConstraint -> TyparConstraint -> bool @@ -884,11 +890,11 @@ val normalizeMeasure : TcGlobals -> Measure -> Measure val GetTypeOfMemberInFSharpForm : TcGlobals -> ValRef -> Typars * CurriedArgInfos * TType * ArgReprInfo -val GetTypeOfMemberInMemberForm : TcGlobals -> ValRef -> Typars * CurriedArgInfos * TType option * ArgReprInfo +val GetTypeOfMemberInMemberForm : TcGlobals -> ValRef -> Typars * TraitWitnessInfos * CurriedArgInfos * TType option * ArgReprInfo -val GetTypeOfIntrinsicMemberInCompiledForm : TcGlobals -> ValRef -> Typars * CurriedArgInfos * TType option * ArgReprInfo +val GetTypeOfIntrinsicMemberInCompiledForm : TcGlobals -> ValRef -> Typars * TraitWitnessInfos * CurriedArgInfos * TType option * ArgReprInfo -val GetMemberTypeInMemberForm : TcGlobals -> MemberFlags -> ValReprInfo -> TType -> range -> Typars * CurriedArgInfos * TType option * ArgReprInfo +val GetMemberTypeInMemberForm : TcGlobals -> MemberFlags -> ValReprInfo -> TType -> range -> Typars * TraitWitnessInfos * CurriedArgInfos * TType option * ArgReprInfo /// Returns (parentTypars,memberParentTypars,memberMethodTypars,memberToParentInst,tinst) val PartitionValTyparsForApparentEnclosingType : TcGlobals -> Val -> (Typars * Typars * Typars * TyparInst * TType list) option @@ -2277,3 +2283,13 @@ val isThreadOrContextStatic: TcGlobals -> Attrib list -> bool val mkUnitDelayLambda: TcGlobals -> range -> Expr -> Expr +val GenWitnessArgTys: TraitWitnessInfo -> TType list list + +val GenWitnessTys: TcGlobals -> TraitWitnessInfos -> TType list + +val GenWitnessTy: TcGlobals -> TraitWitnessInfo -> TType + +val GetTraitConstraintInfosOfTypars: TcGlobals -> Typars -> TraitConstraintInfo list + +val GetTraitWitnessInfosOfTypars: TcGlobals -> parentTypars: Typars -> typars: Typars -> TraitWitnessInfos + diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index e9a57aa3ae5..88691342cad 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -4342,7 +4342,7 @@ and TcPseudoMemberSpec cenv newOk env synTypes tpenv memSpfn m = | [ValSpecResult(_, _, id, _, _, memberConstraintTy, partialValReprInfo, _)] -> let memberConstraintTypars, _ = tryDestForallTy cenv.g memberConstraintTy let topValInfo = TranslatePartialArity memberConstraintTypars partialValReprInfo - let _, curriedArgInfos, returnTy, _ = GetTopValTypeInCompiledForm cenv.g topValInfo memberConstraintTy m + let _, _cxs, curriedArgInfos, returnTy, _ = GetTopValTypeInCompiledForm cenv.g topValInfo memberConstraintTy m //if curriedArgInfos.Length > 1 then error(Error(FSComp.SR.tcInvalidConstraint(), m)) let argTys = List.concat curriedArgInfos let argTys = List.map fst argTys @@ -12745,7 +12745,7 @@ module IncrClassChecking = InVar isCtorArg | topValInfo -> //dprintfn "Representing %s as a method %s" v.LogicalName name - let tps, argInfos, _, _ = GetTopValTypeInCompiledForm g topValInfo v.Type v.Range + let tps, _cxs, argInfos, _, _ = GetTopValTypeInCompiledForm g topValInfo v.Type v.Range let valSynInfo = SynValInfo(argInfos |> List.mapSquared (fun (_, argInfo) -> SynArgInfo([], false, argInfo.Name)), SynInfo.unnamedRetVal) let memberFlags = (if isStatic then StaticMemberFlags else NonVirtualMemberFlags) MemberKind.Member @@ -12763,6 +12763,7 @@ module IncrClassChecking = let (ValReprInfo(tpNames, args, ret)) = topValInfo let topValInfo = ValReprInfo(tpNames, ValReprInfo.selfMetadata::args, ret) tauTy, topValInfo + // Add the enclosing type parameters on to the function let topValInfo = let (ValReprInfo(tpNames, args, ret)) = topValInfo @@ -15734,7 +15735,7 @@ module EstablishTypeDefinitionCores = noAbstractClassAttributeCheck() noFieldsCheck(userFields) let ty', _ = TcTypeAndRecover cenv NoNewTypars CheckCxs ItemOccurence.UseInType envinner tpenv ty - let _, curriedArgInfos, returnTy, _ = GetTopValTypeInCompiledForm cenv.g (arity |> TranslateTopValSynInfo m (TcAttributes cenv envinner) |> TranslatePartialArity []) ty' m + let _, _cxs, curriedArgInfos, returnTy, _ = GetTopValTypeInCompiledForm cenv.g (arity |> TranslateTopValSynInfo m (TcAttributes cenv envinner) |> TranslatePartialArity []) ty' m if curriedArgInfos.Length < 1 then error(Error(FSComp.SR.tcInvalidDelegateSpecification(), m)) if curriedArgInfos.Length > 1 then error(Error(FSComp.SR.tcDelegatesCannotBeCurried(), m)) let ttps = thisTyconRef.Typars(m) @@ -17540,10 +17541,10 @@ let TypeCheckOneImplFile try let reportErrors = not (checkForErrors()) - + let tcVal = LightweightTcValForUsingInBuildMethodCall g PostTypeCheckSemanticChecks.CheckTopImpl (g, cenv.amap, reportErrors, cenv.infoReader, - env.eInternalsVisibleCompPaths, cenv.topCcu, envAtEnd.DisplayEnv, + env.eInternalsVisibleCompPaths, cenv.topCcu, tcVal, envAtEnd.DisplayEnv, implFileExprAfterSig, extraAttribs, isLastCompiland, isInternalTestSpanStackReferring) diff --git a/src/fsharp/infos.fs b/src/fsharp/infos.fs index 642d0d46bc7..b18e1d4b291 100755 --- a/src/fsharp/infos.fs +++ b/src/fsharp/infos.fs @@ -436,7 +436,7 @@ let MakeSlotSig (nm, ty, ctps, mtps, paraml, retTy) = copySlotSig (TSlotSig(nm, /// - the return type of the method /// - the actual type arguments of the enclosing type. let private AnalyzeTypeOfMemberVal isCSharpExt g (ty, vref:ValRef) = - let memberAllTypars, _, retTy, _ = GetTypeOfMemberInMemberForm g vref + let memberAllTypars, _cxs, _, retTy, _ = GetTypeOfMemberInMemberForm g vref if isCSharpExt || vref.IsExtensionMember then [], memberAllTypars, retTy, [] else @@ -446,13 +446,13 @@ let private AnalyzeTypeOfMemberVal isCSharpExt g (ty, vref:ValRef) = /// Get the object type for a member value which is an extension method (C#-style or F#-style) let private GetObjTypeOfInstanceExtensionMethod g (vref:ValRef) = - let _, curriedArgInfos, _, _ = GetTopValTypeInCompiledForm g vref.ValReprInfo.Value vref.Type vref.Range + let _, _cxs, curriedArgInfos, _, _ = GetTopValTypeInCompiledForm g vref.ValReprInfo.Value vref.Type vref.Range curriedArgInfos.Head.Head |> fst -/// Get the object type for a member value which is a C#-style extension method +/// Get the object type for a member value, which might be a C#-style extension method let private GetArgInfosOfMember isCSharpExt g (vref:ValRef) = if isCSharpExt then - let _, curriedArgInfos, _, _ = GetTopValTypeInCompiledForm g vref.ValReprInfo.Value vref.Type vref.Range + let _, _cxs, curriedArgInfos, _, _ = GetTopValTypeInCompiledForm g vref.ValReprInfo.Value vref.Type vref.Range [ curriedArgInfos.Head.Tail ] else ArgInfosOfMember g vref @@ -1481,7 +1481,8 @@ type MethInfo = | ValInRecScope(false) -> error(Error((FSComp.SR.InvalidRecursiveReferenceToAbstractSlot()), m)) | _ -> () - let allTyparsFromMethod, _, retTy, _ = GetTypeOfMemberInMemberForm g vref + // TODO: consider witnesses w.r.t. slot sigs? + let allTyparsFromMethod, _cxs, _, retTy, _ = GetTypeOfMemberInMemberForm g vref // A slot signature is w.r.t. the type variables of the type it is associated with. // So we have to rename from the member type variables to the type variables of the type. let formalEnclosingTypars = x.ApparentEnclosingTyconRef.Typars(m) diff --git a/src/fsharp/tast.fs b/src/fsharp/tast.fs index e02f27bf399..14082ac6d35 100644 --- a/src/fsharp/tast.fs +++ b/src/fsharp/tast.fs @@ -2363,6 +2363,15 @@ and override x.ToString() = sprintf "%+A" x +and TraitWitnessInfo = + | TraitWitnessInfo of TTypes * string * MemberFlags * TTypes * TType option + + /// Get the member name associated with the member constraint. + member x.MemberName = (let (TraitWitnessInfo(_, b, _, _, _)) = x in b) + + /// Get the return type recorded in the member constraint. + member x.ReturnType = (let (TraitWitnessInfo(_, _, _, _, ty)) = x in ty) + /// The specification of a member constraint that must be solved and [] @@ -2374,6 +2383,9 @@ and /// to store the inferred solution of the constraint. | TTrait of TTypes * string * MemberFlags * TTypes * TType option * TraitConstraintSln option ref + /// Get the key associated with the member constraint. + member x.TraitKey = (let (TTrait(a, b, c, d, e, _)) = x in TraitWitnessInfo(a, b, c, d, e)) + /// Get the member name associated with the member constraint. member x.MemberName = (let (TTrait(_, nm, _, _, _, _)) = x in nm) From 53b05795efb674e212bb7a20e37268c740bbe091 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Wed, 20 Mar 2019 17:28:09 +0000 Subject: [PATCH 02/77] more work on trait witnesses for quotations --- src/fsharp/FSharp.Core/Linq.fs | 19 +- src/fsharp/FSharp.Core/prim-types.fs | 125 ++++---- src/fsharp/FSharp.Core/prim-types.fsi | 33 +- src/fsharp/FSharp.Core/quotations.fs | 151 ++++++--- src/fsharp/FSharp.Core/quotations.fsi | 37 ++- src/fsharp/IlxGen.fs | 431 ++++++++++++++++---------- src/fsharp/MethodCalls.fs | 13 +- src/fsharp/PostInferenceChecks.fs | 2 +- src/fsharp/QuotationPickler.fs | 62 +++- src/fsharp/QuotationPickler.fsi | 22 +- src/fsharp/QuotationTranslator.fs | 164 ++++++---- src/fsharp/QuotationTranslator.fsi | 10 +- src/fsharp/TastOps.fs | 30 +- src/fsharp/TastOps.fsi | 4 +- src/fsharp/TcGlobals.fs | 7 + src/fsharp/fsc.fs | 6 +- tests/fsharp/core/quotes/test.fsx | 118 ++++++- 17 files changed, 820 insertions(+), 414 deletions(-) diff --git a/src/fsharp/FSharp.Core/Linq.fs b/src/fsharp/FSharp.Core/Linq.fs index 8b6b5124c4d..7a87af9492a 100644 --- a/src/fsharp/FSharp.Core/Linq.fs +++ b/src/fsharp/FSharp.Core/Linq.fs @@ -332,10 +332,17 @@ module LeafExpressionConverter = let (|ConvUInt32Q|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun x -> Operators.uint32 x)) let (|ConvUInt64Q|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun x -> Operators.uint64 x)) - let (|ConvInt8Q|_|) = SpecificCallToMethodInfo (typeof.Assembly.GetType("Microsoft.FSharp.Core.ExtraTopLevelOperators").GetMethod("ToSByte")) - let (|ConvUInt8Q|_|) = SpecificCallToMethodInfo (typeof.Assembly.GetType("Microsoft.FSharp.Core.ExtraTopLevelOperators").GetMethod("ToByte")) - let (|ConvDoubleQ|_|) = SpecificCallToMethodInfo (typeof.Assembly.GetType("Microsoft.FSharp.Core.ExtraTopLevelOperators").GetMethod("ToDouble")) - let (|ConvSingleQ|_|) = SpecificCallToMethodInfo (typeof.Assembly.GetType("Microsoft.FSharp.Core.ExtraTopLevelOperators").GetMethod("ToSingle")) + /// Get the version of the method that does not carry witnesses + let nonWitnessMethodInfo nm (ms: MethodInfo[]) = + ms |> Array.pick (fun m -> if m.Name = nm && m.GetParameters().Length = 1 then Some m else None) + + let ExtraOperatorsTy = typeof.Assembly.GetType("Microsoft.FSharp.Core.ExtraTopLevelOperators") + let ExtraOperatorsCheckedTy = typeof.Assembly.GetType("Microsoft.FSharp.Core.ExtraTopLevelOperators+Checked") + + let (|ConvInt8Q|_|) = SpecificCallToMethodInfo (ExtraOperatorsTy.GetMethods() |> nonWitnessMethodInfo "ToSByte") + let (|ConvUInt8Q|_|) = SpecificCallToMethodInfo (ExtraOperatorsTy.GetMethods() |> nonWitnessMethodInfo "ToByte") + let (|ConvDoubleQ|_|) = SpecificCallToMethodInfo (ExtraOperatorsTy.GetMethods() |> nonWitnessMethodInfo "ToDouble") + let (|ConvSingleQ|_|) = SpecificCallToMethodInfo (ExtraOperatorsTy.GetMethods() |> nonWitnessMethodInfo "ToSingle") let (|ConvNullableCharQ|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun x -> Nullable.char x)) let (|ConvNullableDecimalQ|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun x -> Nullable.decimal x)) @@ -363,8 +370,8 @@ module LeafExpressionConverter = let (|TypeTestGeneric|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun x -> LanguagePrimitives.IntrinsicFunctions.TypeTestGeneric x)) let (|CheckedConvCharQ|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun x -> Checked.char x)) let (|CheckedConvSByteQ|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun x -> Checked.sbyte x)) - let (|CheckedConvInt8Q|_|) = SpecificCallToMethodInfo (typeof.Assembly.GetType("Microsoft.FSharp.Core.ExtraTopLevelOperators+Checked").GetMethod("ToSByte")) - let (|CheckedConvUInt8Q|_|) = SpecificCallToMethodInfo (typeof.Assembly.GetType("Microsoft.FSharp.Core.ExtraTopLevelOperators+Checked").GetMethod("ToByte")) + let (|CheckedConvInt8Q|_|) = SpecificCallToMethodInfo (ExtraOperatorsCheckedTy.GetMethods() |> nonWitnessMethodInfo "ToSByte") + let (|CheckedConvUInt8Q|_|) = SpecificCallToMethodInfo (ExtraOperatorsCheckedTy.GetMethods() |> nonWitnessMethodInfo "ToByte") let (|CheckedConvInt16Q|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun x -> Checked.int16 x)) let (|CheckedConvInt32Q|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun x -> Checked.int32 x)) let (|CheckedConvInt64Q|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun x -> Checked.int64 x)) diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 7929ef77581..2798e09bdff 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -301,9 +301,14 @@ namespace Microsoft.FSharp.Core [] [] - type NoDynamicInvocationAttribute() = + type NoDynamicInvocationAttribute(legacy: bool) = + inherit System.Attribute() + new () = NoDynamicInvocationAttribute(false) + + member x.IsLegacy = legacy + [] [] type OptionalArgumentAttribute() = @@ -3450,7 +3455,7 @@ namespace Microsoft.FSharp.Core [] let defaultValueArg arg defaultValue = match arg with ValueNone -> defaultValue | ValueSome v -> v - [] + [] let inline (~-) (n: ^T) : ^T = (^T : (static member (~-) : ^T -> ^T) (n)) when ^T : int32 = (# "neg" n : int32 #) @@ -3486,7 +3491,7 @@ namespace Microsoft.FSharp.Core // That is, not in the generic implementation of '+' when ^T : ^T = ((^T or ^U): (static member (+) : ^T * ^U -> ^V) (x,y)) - [] + [] let inline (-) (x: ^T) (y: ^U) : ^V = ((^T or ^U): (static member (-) : ^T * ^U -> ^V) (x,y)) when ^T : int32 and ^U : int32 = (# "sub" x y : int32 #) @@ -3524,7 +3529,7 @@ namespace Microsoft.FSharp.Core // That is, not in the generic implementation of '*' when ^T : ^T = ((^T or ^U): (static member (*) : ^T * ^U -> ^V) (x,y)) - [] + [] let inline ( / ) (x: ^T) (y: ^U) : ^V = ((^T or ^U): (static member (/) : ^T * ^U -> ^V) (x,y)) when ^T : int32 and ^U : int32 = (# "div" x y : int32 #) @@ -3541,7 +3546,7 @@ namespace Microsoft.FSharp.Core when ^T : byte and ^U : byte = (# "conv.u1" (# "div.un" x y : uint32 #) : byte #) when ^T : decimal and ^U : decimal = (# "" (System.Decimal.op_Division((# "" x : decimal #),(# "" y : decimal #))) : ^V #) - [] + [] let inline ( % ) (x: ^T) (y: ^U) : ^V = ((^T or ^U): (static member (%) : ^T * ^U -> ^V) (x,y)) when ^T : int32 and ^U : int32 = (# "rem" x y : int32 #) @@ -3558,7 +3563,7 @@ namespace Microsoft.FSharp.Core when ^T : byte and ^U : byte = (# "conv.u1" (# "rem.un" x y : uint32 #) : byte #) when ^T : decimal and ^U : decimal = (# "" (System.Decimal.op_Modulus((# "" x : decimal #),(# "" y : decimal #))) : ^V #) - [] + [] let inline (~+) (value: ^T) : ^T = (^T: (static member (~+) : ^T -> ^T) (value)) when ^T : int32 = value @@ -3577,7 +3582,7 @@ namespace Microsoft.FSharp.Core let inline mask (n:int) (m:int) = (# "and" n m : int #) - [] + [] let inline (<<<) (value: ^T) (shift:int) : ^T = (^T: (static member (<<<) : ^T * int -> ^T) (value,shift)) when ^T : int32 = (# "shl" value (mask shift 31) : int #) @@ -3591,7 +3596,7 @@ namespace Microsoft.FSharp.Core when ^T : sbyte = (# "conv.i1" (# "shl" value (mask shift 7 ) : int32 #) : sbyte #) when ^T : byte = (# "conv.u1" (# "shl" value (mask shift 7 ) : uint32 #) : byte #) - [] + [] let inline (>>>) (value: ^T) (shift:int) : ^T = (^T: (static member (>>>) : ^T * int -> ^T) (value,shift)) when ^T : int32 = (# "shr" value (mask shift 31) : int32 #) @@ -3605,7 +3610,7 @@ namespace Microsoft.FSharp.Core when ^T : sbyte = (# "conv.i1" (# "shr" value (mask shift 7 ) : int32 #) : sbyte #) when ^T : byte = (# "conv.u1" (# "shr.un" value (mask shift 7 ) : uint32 #) : byte #) - [] + [] let inline (&&&) (x: ^T) (y: ^T) : ^T = (^T: (static member (&&&) : ^T * ^T -> ^T) (x,y)) when ^T : int32 = (# "and" x y : int32 #) @@ -3619,7 +3624,7 @@ namespace Microsoft.FSharp.Core when ^T : sbyte = (# "and" x y : sbyte #) when ^T : byte = (# "and" x y : byte #) - [] + [] let inline (|||) (x: ^T) (y: ^T) : ^T = (^T: (static member (|||) : ^T * ^T -> ^T) (x,y)) when ^T : int32 = (# "or" x y : int32 #) @@ -3633,7 +3638,7 @@ namespace Microsoft.FSharp.Core when ^T : sbyte = (# "or" x y : sbyte #) when ^T : byte = (# "or" x y : byte #) - [] + [] let inline (^^^) (x: ^T) (y: ^T) : ^T = (^T: (static member (^^^) : ^T * ^T -> ^T) (x,y)) when ^T : int32 = (# "xor" x y : int32 #) @@ -3647,7 +3652,7 @@ namespace Microsoft.FSharp.Core when ^T : sbyte = (# "xor" x y : sbyte #) when ^T : byte = (# "xor" x y : byte #) - [] + [] let inline (~~~) (value: ^T) : ^T = (^T: (static member (~~~) : ^T -> ^T) (value)) when ^T : int32 = (# "not" value : int32 #) @@ -3698,7 +3703,7 @@ namespace Microsoft.FSharp.Core let inline ParseSingle (s:string) = Single.Parse(removeUnderscores s,NumberStyles.Float, CultureInfo.InvariantCulture) - [] + [] [] let inline byte (value: ^T) = (^T : (static member op_Explicit: ^T -> byte) (value)) @@ -3717,7 +3722,7 @@ namespace Microsoft.FSharp.Core when ^T : unativeint = (# "conv.u1" value : byte #) when ^T : byte = (# "conv.u1" value : byte #) - [] + [] [] let inline sbyte (value: ^T) = (^T : (static member op_Explicit: ^T -> sbyte) (value)) @@ -3736,7 +3741,7 @@ namespace Microsoft.FSharp.Core when ^T : unativeint = (# "conv.i1" value : sbyte #) when ^T : byte = (# "conv.i1" value : sbyte #) - [] + [] [] let inline uint16 (value: ^T) = (^T : (static member op_Explicit: ^T -> uint16) (value)) @@ -3755,7 +3760,7 @@ namespace Microsoft.FSharp.Core when ^T : unativeint = (# "conv.u2" value : uint16 #) when ^T : byte = (# "conv.u2" value : uint16 #) - [] + [] [] let inline int16 (value: ^T) = (^T : (static member op_Explicit: ^T -> int16) (value)) @@ -3774,7 +3779,7 @@ namespace Microsoft.FSharp.Core when ^T : unativeint = (# "conv.i2" value : int16 #) when ^T : byte = (# "conv.i2" value : int16 #) - [] + [] [] let inline uint32 (value: ^T) = (^T : (static member op_Explicit: ^T -> uint32) (value)) @@ -3800,7 +3805,7 @@ namespace Microsoft.FSharp.Core when ^T : unativeint = (# "conv.u4" value : uint32 #) when ^T : byte = (# "conv.u4" value : uint32 #) - [] + [] [] let inline int32 (value: ^T) = (^T : (static member op_Explicit: ^T -> int32) (value)) @@ -3844,7 +3849,7 @@ namespace Microsoft.FSharp.Core [] let nanf = System.Single.NaN - [] + [] [] let inline uint64 (value: ^T) = (^T : (static member op_Explicit: ^T -> uint64) (value)) @@ -3870,7 +3875,7 @@ namespace Microsoft.FSharp.Core when ^T : unativeint = (# "conv.u8" value : uint64 #) when ^T : byte = (# "conv.u8" value : uint64 #) - [] + [] [] let inline int64 (value: ^T) = (^T : (static member op_Explicit: ^T -> int64) (value)) @@ -3893,7 +3898,7 @@ namespace Microsoft.FSharp.Core when ^T : unativeint = (# "conv.u8" value : int64 #) when ^T : byte = (# "conv.u8" value : int64 #) - [] + [] [] let inline float32 (value: ^T) = (^T : (static member op_Explicit: ^T -> float32) (value)) @@ -3913,7 +3918,7 @@ namespace Microsoft.FSharp.Core when ^T : unativeint = (# "conv.r.un conv.r4" value : float32 #) when ^T : byte = (# "conv.r.un conv.r4" value : float32 #) - [] + [] [] let inline float (value: ^T) = (^T : (static member op_Explicit: ^T -> float) (value)) @@ -3934,7 +3939,7 @@ namespace Microsoft.FSharp.Core when ^T : byte = (# "conv.r.un conv.r8" value : float #) when ^T : decimal = (System.Convert.ToDouble((# "" value : decimal #))) - [] + [] [] let inline decimal (value: ^T) = (^T : (static member op_Explicit: ^T -> decimal) (value)) @@ -3958,7 +3963,7 @@ namespace Microsoft.FSharp.Core // C# names: sbyte, byte, short, ushort, int, uint, long, ulong, single, double. // F# names: sbyte, byte, int16, uint16, int, uint32, int64, uint64, float32, float. - [] + [] [] let inline unativeint (value: ^T) = (^T : (static member op_Explicit: ^T -> unativeint) (value)) @@ -3983,7 +3988,7 @@ namespace Microsoft.FSharp.Core when ^T : unativeint = (# "" value : unativeint #) when ^T : byte = (# "conv.u" value : unativeint #) - [] + [] [] let inline nativeint (value: ^T) = (^T : (static member op_Explicit: ^T -> nativeint) (value)) @@ -4027,7 +4032,7 @@ namespace Microsoft.FSharp.Core when ^T : unativeint = (# "" value : unativeint #).ToString() when ^T : byte = (# "" value : byte #).ToString("g",CultureInfo.InvariantCulture) - [] + [] [] let inline char (value: ^T) = (^T : (static member op_Explicit: ^T -> char) (value)) @@ -4357,7 +4362,7 @@ namespace Microsoft.FSharp.Core // That is, not in the generic implementation of '+' when ^T : ^T = ((^T or ^U): (static member (+) : ^T * ^U -> ^V) (x,y)) - [] + [] let inline (-) (x: ^T) (y: ^U) : ^V = ((^T or ^U): (static member (-) : ^T * ^U -> ^V) (x,y)) when ^T : int32 and ^U : int32 = (# "sub.ovf" x y : int32 #) @@ -4374,7 +4379,7 @@ namespace Microsoft.FSharp.Core when ^T : byte and ^U : byte = (# "conv.ovf.u1.un" (# "sub.ovf.un" x y : uint32 #) : byte #) when ^T : decimal and ^U : decimal = (# "" (System.Decimal.op_Subtraction((# "" x : decimal #),(# "" y : decimal #))) : ^V #) - [] + [] let inline (~-) (value: ^T) : ^T = (^T : (static member (~-) : ^T -> ^T) (value)) when ^T : int32 = (# "sub.ovf" 0 value : int32 #) @@ -4406,7 +4411,7 @@ namespace Microsoft.FSharp.Core // That is, not in the generic implementation of '*' when ^T : ^T = ((^T or ^U): (static member (*) : ^T * ^U -> ^V) (x,y)) - [] + [] [] let inline byte (value: ^T) = (^T : (static member op_Explicit: ^T -> byte) (value)) @@ -4425,7 +4430,7 @@ namespace Microsoft.FSharp.Core when ^T : unativeint = (# "conv.ovf.u1.un" value : byte #) when ^T : byte = (# "conv.ovf.u1.un" value : byte #) - [] + [] [] let inline sbyte (value: ^T) = (^T : (static member op_Explicit: ^T -> sbyte) (value)) @@ -4444,7 +4449,7 @@ namespace Microsoft.FSharp.Core when ^T : unativeint = (# "conv.ovf.i1.un" value : sbyte #) when ^T : byte = (# "conv.ovf.i1.un" value : sbyte #) - [] + [] [] let inline uint16 (value: ^T) = (^T : (static member op_Explicit: ^T -> uint16) (value)) @@ -4463,7 +4468,7 @@ namespace Microsoft.FSharp.Core when ^T : unativeint = (# "conv.ovf.u2.un" value : uint16 #) when ^T : byte = (# "conv.ovf.u2.un" value : uint16 #) - [] + [] [] let inline char (value: ^T) = (^T : (static member op_Explicit: ^T -> char) (value)) @@ -4482,7 +4487,7 @@ namespace Microsoft.FSharp.Core when ^T : unativeint = (# "conv.ovf.u2.un" value : char #) when ^T : byte = (# "conv.ovf.u2.un" value : char #) - [] + [] [] let inline int16 (value: ^T) = (^T : (static member op_Explicit: ^T -> int16) (value)) @@ -4501,7 +4506,7 @@ namespace Microsoft.FSharp.Core when ^T : unativeint = (# "conv.ovf.i2.un" value : int16 #) when ^T : byte = (# "conv.ovf.i2.un" value : int16 #) - [] + [] [] let inline uint32 (value: ^T) = (^T : (static member op_Explicit: ^T -> uint32) (value)) @@ -4520,7 +4525,7 @@ namespace Microsoft.FSharp.Core when ^T : unativeint = (# "conv.ovf.u4.un" value : uint32 #) when ^T : byte = (# "conv.ovf.u4.un" value : uint32 #) - [] + [] [] let inline int32 (value: ^T) = (^T : (static member op_Explicit: ^T -> int32) (value)) @@ -4543,7 +4548,7 @@ namespace Microsoft.FSharp.Core [] let inline int value = int32 value - [] + [] [] let inline uint64 (value: ^T) = (^T : (static member op_Explicit: ^T -> uint64) (value)) @@ -4562,7 +4567,7 @@ namespace Microsoft.FSharp.Core when ^T : unativeint = (# "conv.ovf.u8.un" value : uint64 #) when ^T : byte = (# "conv.ovf.u8.un" value : uint64 #) - [] + [] [] let inline int64 (value: ^T) = (^T : (static member op_Explicit: ^T -> int64) (value)) @@ -4581,7 +4586,7 @@ namespace Microsoft.FSharp.Core when ^T : unativeint = (# "conv.ovf.i8.un" value : int64 #) when ^T : byte = (# "conv.ovf.i8.un" value : int64 #) - [] + [] [] let inline unativeint (value: ^T) = (^T : (static member op_Explicit: ^T -> unativeint) (value)) @@ -4600,7 +4605,7 @@ namespace Microsoft.FSharp.Core when ^T : unativeint = (# "conv.ovf.u.un" value : unativeint #) when ^T : byte = (# "conv.ovf.u.un" value : unativeint #) - [] + [] [] let inline nativeint (value: ^T) = (^T : (static member op_Explicit: ^T -> nativeint) (value)) @@ -5144,7 +5149,7 @@ namespace Microsoft.FSharp.Core if len <= 0 then String.Empty else source.Substring(start, len) - [] + [] let inline absImpl (x: ^T) : ^T = (^T: (static member Abs : ^T -> ^T) (x)) when ^T : int32 = let x : int32 = retype x in System.Math.Abs(x) @@ -5161,61 +5166,61 @@ namespace Microsoft.FSharp.Core when ^T : sbyte = let x : sbyte = retype x in System.Math.Abs(x) when ^T : decimal = System.Math.Abs(retype x : decimal) - [] + [] let inline acosImpl(x: ^T) : ^T = (^T: (static member Acos : ^T -> ^T) (x)) when ^T : float = System.Math.Acos(retype x) when ^T : float32 = System.Math.Acos(toFloat (retype x)) |> toFloat32 - [] + [] let inline asinImpl(x: ^T) : ^T = (^T: (static member Asin : ^T -> ^T) (x)) when ^T : float = System.Math.Asin(retype x) when ^T : float32 = System.Math.Asin(toFloat (retype x)) |> toFloat32 - [] + [] let inline atanImpl(x: ^T) : ^T = (^T: (static member Atan : ^T -> ^T) (x)) when ^T : float = System.Math.Atan(retype x) when ^T : float32 = System.Math.Atan(toFloat (retype x)) |> toFloat32 - [] + [] let inline atan2Impl(x: ^T) (y: ^T) : 'U = (^T: (static member Atan2 : ^T * ^T -> 'U) (x,y)) when ^T : float = System.Math.Atan2(retype x, retype y) when ^T : float32 = System.Math.Atan2(toFloat (retype x), toFloat(retype y)) |> toFloat32 - [] + [] let inline ceilImpl(x: ^T) : ^T = (^T: (static member Ceiling : ^T -> ^T) (x)) when ^T : float = System.Math.Ceiling(retype x : float) when ^T : float32 = System.Math.Ceiling(toFloat (retype x)) |> toFloat32 - [] + [] let inline expImpl(x: ^T) : ^T = (^T: (static member Exp : ^T -> ^T) (x)) when ^T : float = System.Math.Exp(retype x) when ^T : float32 = System.Math.Exp(toFloat (retype x)) |> toFloat32 - [] + [] let inline floorImpl (x: ^T) : ^T = (^T: (static member Floor : ^T -> ^T) (x)) when ^T : float = System.Math.Floor(retype x : float) when ^T : float32 = System.Math.Floor(toFloat (retype x)) |> toFloat32 - [] + [] let inline truncateImpl (x: ^T) : ^T = (^T: (static member Truncate : ^T -> ^T) (x)) when ^T : float = System.Math.Truncate(retype x : float) when ^T : float32 = System.Math.Truncate(toFloat (retype x)) |> toFloat32 - [] + [] let inline roundImpl (x: ^T) : ^T = (^T: (static member Round : ^T -> ^T) (x)) when ^T : float = System.Math.Round(retype x : float) when ^T : float32 = System.Math.Round(toFloat (retype x)) |> toFloat32 - [] + [] let inline signImpl (x: ^T) : int = (^T: (member Sign : int) (x)) when ^T : int32 = System.Math.Sign(retype x : int32) @@ -5227,61 +5232,61 @@ namespace Microsoft.FSharp.Core when ^T : float32 = System.Math.Sign(toFloat (retype x)) when ^T : decimal = System.Math.Sign(retype x : decimal) - [] + [] let inline logImpl(x: ^T) : ^T = (^T: (static member Log : ^T -> ^T) (x)) when ^T : float = System.Math.Log(retype x) when ^T : float32 = System.Math.Log(toFloat (retype x)) |> toFloat32 - [] + [] let inline log10Impl(x: ^T) : ^T = (^T: (static member Log10 : ^T -> ^T) (x)) when ^T : float = System.Math.Log10(retype x) when ^T : float32 = System.Math.Log10(toFloat (retype x)) |> toFloat32 - [] + [] let inline sqrtImpl(x: ^T) : ^U = (^T: (static member Sqrt : ^T -> ^U) (x)) when ^T : float = System.Math.Sqrt(retype x : float) when ^T : float32 = System.Math.Sqrt(toFloat (retype x)) |> toFloat32 - [] + [] let inline cosImpl(x: ^T) : ^T = (^T: (static member Cos : ^T -> ^T) (x)) when ^T : float = System.Math.Cos(retype x) when ^T : float32 = System.Math.Cos(toFloat (retype x)) |> toFloat32 - [] + [] let inline coshImpl(x: ^T) : ^T = (^T: (static member Cosh : ^T -> ^T) (x)) when ^T : float = System.Math.Cosh(retype x) when ^T : float32 = System.Math.Cosh(toFloat (retype x)) |> toFloat32 - [] + [] let inline sinImpl(x: ^T) : ^T = (^T: (static member Sin : ^T -> ^T) (x)) when ^T : float = System.Math.Sin(retype x) when ^T : float32 = System.Math.Sin(toFloat (retype x)) |> toFloat32 - [] + [] let inline sinhImpl(x: ^T) : ^T = (^T: (static member Sinh : ^T -> ^T) (x)) when ^T : float = System.Math.Sinh(retype x) when ^T : float32 = System.Math.Sinh(toFloat (retype x)) |> toFloat32 - [] + [] let inline tanImpl(x: ^T) : ^T = (^T: (static member Tan : ^T -> ^T) (x)) when ^T : float = System.Math.Tan(retype x) when ^T : float32 = System.Math.Tan(toFloat (retype x)) |> toFloat32 - [] + [] let inline tanhImpl(x: ^T) : ^T = (^T: (static member Tanh : ^T -> ^T) (x)) when ^T : float = System.Math.Tanh(retype x) when ^T : float32 = System.Math.Tanh(toFloat (retype x)) |> toFloat32 - [] + [] let inline powImpl (x: ^T) (y: ^U) : ^T = (^T: (static member Pow : ^T * ^U -> ^T) (x,y)) when ^T : float = System.Math.Pow((retype x : float), (retype y: float)) diff --git a/src/fsharp/FSharp.Core/prim-types.fsi b/src/fsharp/FSharp.Core/prim-types.fsi index a62b9d18783..1a74f81482e 100644 --- a/src/fsharp/FSharp.Core/prim-types.fsi +++ b/src/fsharp/FSharp.Core/prim-types.fsi @@ -714,6 +714,8 @@ namespace Microsoft.FSharp.Core /// NoDynamicInvocationAttribute new : unit -> NoDynamicInvocationAttribute + new : isLegacy: bool -> NoDynamicInvocationAttribute + /// This attribute is used to indicate that references to the elements of a module, record or union /// type require explicit qualified access. [] @@ -2743,6 +2745,7 @@ namespace Microsoft.FSharp.Core /// input types the operation requires an appropriate static conversion method on the input type. /// The input value. /// The converted char. + [] [] val inline char : value:^T -> char when ^T : (static member op_Explicit : ^T -> char) and default ^T : int @@ -3181,14 +3184,14 @@ namespace Microsoft.FSharp.Core /// Overloaded unary negation (checks for overflow) /// The input value. /// The negated value. - [] + [] val inline ( ~- ) : value:^T -> ^T when ^T : (static member ( ~- ) : ^T -> ^T) and default ^T : int /// Overloaded subtraction operator (checks for overflow) /// The first value. /// The second value. /// The first value minus the second value. - [] + [] val inline ( - ) : x:^T1 -> y:^T2 -> ^T3 when (^T1 or ^T2) : (static member ( - ) : ^T1 * ^T2 -> ^T3) and default ^T2 : ^T3 and default ^T3 : ^T1 and default ^T3 : ^T2 and default ^T1 : ^T3 and default ^T1 : ^T2 and default ^T1 : int /// Overloaded addition operator (checks for overflow) @@ -3201,7 +3204,7 @@ namespace Microsoft.FSharp.Core /// The first value. /// The second value. /// The product of the two input values. - [] + [] val inline ( * ) : x:^T1 -> y:^T2 -> ^T3 when (^T1 or ^T2) : (static member ( * ) : ^T1 * ^T2 -> ^T3) and default ^T2 : ^T3 and default ^T3 : ^T1 and default ^T3 : ^T2 and default ^T1 : ^T3 and default ^T1 : ^T2 and default ^T1 : int /// Converts the argument to byte. This is a direct, checked conversion for all @@ -3210,7 +3213,7 @@ namespace Microsoft.FSharp.Core /// static conversion method on the input type. /// The input value. /// The converted byte - [] + [] [] val inline byte : value:^T -> byte when ^T : (static member op_Explicit : ^T -> byte) and default ^T : int @@ -3220,7 +3223,7 @@ namespace Microsoft.FSharp.Core /// static conversion method on the input type. /// The input value. /// The converted sbyte - [] + [] [] val inline sbyte : value:^T -> sbyte when ^T : (static member op_Explicit : ^T -> sbyte) and default ^T : int @@ -3230,7 +3233,7 @@ namespace Microsoft.FSharp.Core /// static conversion method on the input type. /// The input value. /// The converted int16 - [] + [] [] val inline int16 : value:^T -> int16 when ^T : (static member op_Explicit : ^T -> int16) and default ^T : int @@ -3240,7 +3243,7 @@ namespace Microsoft.FSharp.Core /// static conversion method on the input type. /// The input value. /// The converted uint16 - [] + [] [] val inline uint16 : value:^T -> uint16 when ^T : (static member op_Explicit : ^T -> uint16) and default ^T : int @@ -3250,7 +3253,7 @@ namespace Microsoft.FSharp.Core /// static conversion method on the input type. /// The input value. /// The converted int - [] + [] [] val inline int : value:^T -> int when ^T : (static member op_Explicit : ^T -> int) and default ^T : int @@ -3260,7 +3263,7 @@ namespace Microsoft.FSharp.Core /// static conversion method on the input type. /// The input value. /// The converted int32 - [] + [] [] val inline int32 : value:^T -> int32 when ^T : (static member op_Explicit : ^T -> int32) and default ^T : int @@ -3270,7 +3273,7 @@ namespace Microsoft.FSharp.Core /// static conversion method on the input type. /// The input value. /// The converted uint32 - [] + [] [] val inline uint32 : value:^T -> uint32 when ^T : (static member op_Explicit : ^T -> uint32) and default ^T : int @@ -3280,7 +3283,7 @@ namespace Microsoft.FSharp.Core /// static conversion method on the input type. /// The input value. /// The converted int64 - [] + [] [] val inline int64 : value:^T -> int64 when ^T : (static member op_Explicit : ^T -> int64) and default ^T : int @@ -3290,7 +3293,7 @@ namespace Microsoft.FSharp.Core /// static conversion method on the input type. /// The input value. /// The converted uint64 - [] + [] [] val inline uint64 : value:^T -> uint64 when ^T : (static member op_Explicit : ^T -> uint64) and default ^T : int @@ -3299,7 +3302,7 @@ namespace Microsoft.FSharp.Core /// static conversion method on the input type. /// The input value. /// The converted nativeint - [] + [] [] val inline nativeint : value:^T -> nativeint when ^T : (static member op_Explicit : ^T -> nativeint) and default ^T : int @@ -3308,7 +3311,7 @@ namespace Microsoft.FSharp.Core /// static conversion method on the input type. /// The input value. /// The converted unativeint - [] + [] [] val inline unativeint : value:^T -> unativeint when ^T : (static member op_Explicit : ^T -> unativeint) and default ^T : int @@ -3318,7 +3321,7 @@ namespace Microsoft.FSharp.Core /// appropriate static conversion method on the input type. /// The input value. /// The converted char - [] + [] [] val inline char : value:^T -> char when ^T : (static member op_Explicit : ^T -> char) and default ^T : int diff --git a/src/fsharp/FSharp.Core/quotations.fs b/src/fsharp/FSharp.Core/quotations.fs index 6198357fa08..31d5256f7a5 100644 --- a/src/fsharp/FSharp.Core/quotations.fs +++ b/src/fsharp/FSharp.Core/quotations.fs @@ -175,6 +175,8 @@ and | NewObjectOp of ConstructorInfo | InstanceMethodCallOp of MethodInfo | StaticMethodCallOp of MethodInfo + | InstanceMethodCallWOp of MethodInfo * MethodInfo * int + | StaticMethodCallWOp of MethodInfo * MethodInfo * int | CoerceOp of Type | NewArrayOp of Type | NewDelegateOp of Type @@ -263,6 +265,8 @@ and [] | CombTerm(WithValueOp(v,_),[defn]) -> combL "WithValue" [objL v; expr defn] | CombTerm(InstanceMethodCallOp(minfo),obj::args) -> combL "Call" [someL obj; minfoL minfo; listL (exprs args)] | CombTerm(StaticMethodCallOp(minfo),args) -> combL "Call" [noneL; minfoL minfo; listL (exprs args)] + | CombTerm(InstanceMethodCallWOp(minfo, _minfoW, nWitnesses),obj::args) -> combL "Call" [someL obj; minfoL minfo; listL (exprs (List.skip nWitnesses args))] + | CombTerm(StaticMethodCallWOp(minfo, _minfoW, nWitnesses),args) -> combL "Call" [noneL; minfoL minfo; listL (exprs (List.skip nWitnesses args))] | CombTerm(InstancePropGetOp(pinfo),(obj::args)) -> combL "PropertyGet" [someL obj; pinfoL pinfo; listL (exprs args)] | CombTerm(StaticPropGetOp(pinfo),args) -> combL "PropertyGet" [noneL; pinfoL pinfo; listL (exprs args)] | CombTerm(InstancePropSetOp(pinfo),(obj::args)) -> combL "PropertySet" [someL obj; pinfoL pinfo; listL (exprs args)] @@ -344,7 +348,7 @@ module Patterns = let ES ts = List.map E ts let (|E|) (e: Expr) = e.Tree - let (|ES|) (es: list) = es |> List.map (fun e -> e.Tree) + let (|ES|) (es: Expr list) = es |> List.map (fun e -> e.Tree) let (|FrontAndBack|_|) es = let rec loop acc xs = match xs with [] -> None | [h] -> Some (List.rev acc, h) | h::t -> loop (h::acc) t loop [] es @@ -519,6 +523,17 @@ module Patterns = match input with | E(CombTerm(StaticMethodCallOp minfo,args)) -> Some(None,minfo,args) | E(CombTerm(InstanceMethodCallOp minfo,(obj::args))) -> Some(Some(obj),minfo,args) + | E(CombTerm(StaticMethodCallWOp (minfo, _minfoW, nWitnesses),args)) -> Some(None,minfo,List.skip nWitnesses args) + | E(CombTerm(InstanceMethodCallWOp (minfo, _minfoW, nWitnesses),(obj::args))) -> Some(Some(obj),minfo,List.skip nWitnesses args) + | _ -> None + + [] + let (|CallWithWitnesses|_|) input = + match input with + | E(CombTerm(StaticMethodCallOp minfo,args)) -> Some(None,minfo,minfo,[],args) + | E(CombTerm(InstanceMethodCallOp minfo,(obj::args))) -> Some(Some(obj),minfo,minfo,[],args) + | E(CombTerm(StaticMethodCallWOp (minfo, minfoW, nWitnesses),args)) -> Some(None,minfo,minfoW,List.take nWitnesses args, List.skip nWitnesses args) + | E(CombTerm(InstanceMethodCallWOp (minfo, minfoW, nWitnesses),(obj::args))) -> Some(Some(obj),minfo,minfoW,List.take nWitnesses args, List.skip nWitnesses args) | _ -> None let (|LetRaw|_|) input = @@ -629,6 +644,8 @@ module Patterns = | NewObjectOp ctor,_ -> ctor.DeclaringType | InstanceMethodCallOp minfo,_ -> minfo.ReturnType |> removeVoid | StaticMethodCallOp minfo,_ -> minfo.ReturnType |> removeVoid + | InstanceMethodCallWOp (_,minfoW,_),_ -> minfoW.ReturnType |> removeVoid + | StaticMethodCallWOp (_,minfoW,_),_ -> minfoW.ReturnType |> removeVoid | CoerceOp ty,_ -> ty | SequentialOp,[_;b] -> typeOf b | ForIntegerRangeLoopOp,_ -> typeof @@ -674,7 +691,7 @@ module Patterns = if (not (assignableFrom expectedType receivedType)) then invalidArg "receivedType" (String.Format(threeHoleSR, name, expectedType, receivedType)) - let checkArgs (paramInfos: ParameterInfo[]) (args:list) = + let checkArgs (paramInfos: ParameterInfo[]) (args:Expr list) = if (paramInfos.Length <> args.Length) then invalidArg "args" (SR.GetString(SR.QincorrectNumArgs)) List.iter2 ( fun (p:ParameterInfo) a -> checkTypesWeakSR p.ParameterType (typeOf a) "args" (SR.GetString(SR.QtmmInvalidParam))) @@ -765,7 +782,7 @@ module Patterns = mkFE1 (TupleGetOp (ty,n)) x // Records - let mkNewRecord (ty,args:list) = + let mkNewRecord (ty,args:Expr list) = let mems = FSharpType.GetRecordFields(ty,publicOrPrivateBindingFlags) if (args.Length <> mems.Length) then invalidArg "args" (SR.GetString(SR.QincompatibleRecordLength)) List.iter2 (fun (minfo:PropertyInfo) a -> checkTypesSR minfo.PropertyType (typeOf a) "recd" (SR.GetString(SR.QtmmIncorrectArgForRecord))) (Array.toList mems) args @@ -773,7 +790,7 @@ module Patterns = // Discriminated unions - let mkNewUnionCase (unionCase:UnionCaseInfo,args:list) = + let mkNewUnionCase (unionCase:UnionCaseInfo,args:Expr list) = if Unchecked.defaultof = unionCase then raise (new ArgumentNullException()) let sargs = unionCase.GetFields() if (args.Length <> sargs.Length) then invalidArg "args" (SR.GetString(SR.QunionNeedsDiffNumArgs)) @@ -825,7 +842,7 @@ module Patterns = mkFE2 (InstanceFieldSetOp finfo) (obj,value) | true -> invalidArg "finfo" (SR.GetString(SR.QstaticWithReceiverObject)) - let mkCtorCall (ci:ConstructorInfo,args:list) = + let mkCtorCall (ci:ConstructorInfo,args:Expr list) = if Unchecked.defaultof = ci then raise (new ArgumentNullException()) checkArgs (ci.GetParameters()) args mkFEN (NewObjectOp ci) args @@ -833,7 +850,7 @@ module Patterns = let mkDefaultValue (ty:Type) = mkFE0 (DefaultValueOp ty) - let mkStaticPropGet (pinfo:PropertyInfo,args:list) = + let mkStaticPropGet (pinfo:PropertyInfo,args:Expr list) = if Unchecked.defaultof = pinfo then raise (new ArgumentNullException()) if (not pinfo.CanRead) then invalidArg "pinfo" (SR.GetString(SR.QreadingSetOnly)) checkArgs (pinfo.GetIndexParameters()) args @@ -841,7 +858,7 @@ module Patterns = | true -> mkFEN (StaticPropGetOp pinfo) args | false -> invalidArg "pinfo" (SR.GetString(SR.QnonStaticNoReceiverObject)) - let mkInstancePropGet (obj,pinfo:PropertyInfo,args:list) = + let mkInstancePropGet (obj,pinfo:PropertyInfo,args:Expr list) = if Unchecked.defaultof = pinfo then raise (new ArgumentNullException()) if (not pinfo.CanRead) then invalidArg "pinfo" (SR.GetString(SR.QreadingSetOnly)) checkArgs (pinfo.GetIndexParameters()) args @@ -851,7 +868,7 @@ module Patterns = mkFEN (InstancePropGetOp pinfo) (obj::args) | true -> invalidArg "pinfo" (SR.GetString(SR.QstaticWithReceiverObject)) - let mkStaticPropSet (pinfo:PropertyInfo,args:list,value:Expr) = + let mkStaticPropSet (pinfo:PropertyInfo,args:Expr list,value:Expr) = if Unchecked.defaultof = pinfo then raise (new ArgumentNullException()) if (not pinfo.CanWrite) then invalidArg "pinfo" (SR.GetString(SR.QwritingGetOnly)) checkArgs (pinfo.GetIndexParameters()) args @@ -859,7 +876,7 @@ module Patterns = | true -> mkFEN (StaticPropSetOp pinfo) (args@[value]) | false -> invalidArg "pinfo" (SR.GetString(SR.QnonStaticNoReceiverObject)) - let mkInstancePropSet (obj,pinfo:PropertyInfo,args:list,value:Expr) = + let mkInstancePropSet (obj,pinfo:PropertyInfo,args:Expr list,value:Expr) = if Unchecked.defaultof = pinfo then raise (new ArgumentNullException()) if (not pinfo.CanWrite) then invalidArg "pinfo" (SR.GetString(SR.QwritingGetOnly)) checkArgs (pinfo.GetIndexParameters()) args @@ -869,7 +886,7 @@ module Patterns = mkFEN (InstancePropSetOp pinfo) (obj::(args@[value])) | true -> invalidArg "pinfo" (SR.GetString(SR.QstaticWithReceiverObject)) - let mkInstanceMethodCall (obj,minfo:MethodInfo,args:list) = + let mkInstanceMethodCall (obj,minfo:MethodInfo,args:Expr list) = if Unchecked.defaultof = minfo then raise (new ArgumentNullException()) checkArgs (minfo.GetParameters()) args match minfo.IsStatic with @@ -878,13 +895,29 @@ module Patterns = mkFEN (InstanceMethodCallOp minfo) (obj::args) | true -> invalidArg "minfo" (SR.GetString(SR.QstaticWithReceiverObject)) - let mkStaticMethodCall (minfo:MethodInfo,args:list) = + let mkInstanceMethodCallW (obj, minfo:MethodInfo, minfoW:MethodInfo, nWitnesses: int,args:Expr list) = + if Unchecked.defaultof = minfo then raise (new ArgumentNullException()) + checkArgs (minfoW.GetParameters()) args + match minfoW.IsStatic with + | false -> + checkObj minfo obj + mkFEN (InstanceMethodCallWOp (minfo, minfoW, nWitnesses)) (obj::args) + | true -> invalidArg "minfo" (SR.GetString(SR.QstaticWithReceiverObject)) + + let mkStaticMethodCall (minfo:MethodInfo,args:Expr list) = if Unchecked.defaultof = minfo then raise (new ArgumentNullException()) checkArgs (minfo.GetParameters()) args match minfo.IsStatic with | true -> mkFEN (StaticMethodCallOp minfo) args | false -> invalidArg "minfo" (SR.GetString(SR.QnonStaticNoReceiverObject)) + let mkStaticMethodCallW (minfo:MethodInfo, minfoW:MethodInfo, nWitnesses: int, args:Expr list) = + if Unchecked.defaultof = minfo then raise (new ArgumentNullException()) + checkArgs (minfoW.GetParameters()) args + match minfo.IsStatic with + | true -> mkFEN (StaticMethodCallWOp (minfo, minfoW, nWitnesses)) args + | false -> invalidArg "minfo" (SR.GetString(SR.QnonStaticNoReceiverObject)) + let mkForLoop (v:Var,lowerBound,upperBound,body) = checkTypesSR (typeof) (typeOf lowerBound) "lowerBound" (SR.GetString(SR.QtmmLowerUpperBoundMustBeInt)) checkTypesSR (typeof) (typeOf upperBound) "upperBound" (SR.GetString(SR.QtmmLowerUpperBoundMustBeInt)) @@ -914,7 +947,7 @@ module Patterns = | [x] -> mkApplication (f,x) | _ -> mkApplication (f,mkNewTuple args) - let mkApplications(f: Expr,es:list>) = mkLLinear mkTupledApplication (f,es) + let mkApplications(f: Expr,es:list) = mkLLinear mkTupledApplication (f,es) let mkIteratedLambdas(vs,b) = mkRLinear mkLambda (vs,b) @@ -1011,11 +1044,6 @@ module Patterns = // tries to locate unique function in a given type // in case of multiple candidates returns None so bindModuleFunctionWithCallSiteArgs will be used for more precise resolution - let bindModuleFunction (ty:Type,nm) = - match ty.GetMethods(staticBindingFlags) |> Array.filter (fun mi -> mi.Name = nm) with - | [||] -> raise <| System.InvalidOperationException (String.Format(SR.GetString(SR.QcannotBindFunction), nm, ty.ToString())) - | [| res |] -> Some res - | _ -> None let bindModuleFunctionWithCallSiteArgs (ty:Type, nm, argTypes : Type list, tyArgs : Type list) = let argTypes = List.toArray argTypes @@ -1411,7 +1439,7 @@ module Patterns = let rec u_Expr st = let tag = u_byte_as_int st match tag with - | 0 -> u_tup3 u_constSpec u_dtypes (u_list u_Expr) st + | 0 -> u_tup3 u_opSpec u_dtypes (u_list u_Expr) st |> (fun (a,b,args) (env:BindingEnv) -> let args = List.map (fun e -> e env) args let a = @@ -1461,13 +1489,30 @@ module Patterns = let case,i = u_tup2 u_UnionCaseInfo u_int st (fun tyargs -> getUnionCaseInfoField(case tyargs,i)) - and u_ModuleDefn st = + and u_ModuleDefn nWitnesses st = let (ty,nm,isProp) = u_tup3 u_NamedType u_string u_bool st if isProp then Unique(StaticPropGetOp(bindModuleProperty(ty,nm))) else - match bindModuleFunction(ty, nm) with - | Some mi -> Unique(StaticMethodCallOp(mi)) - | None -> Ambiguous(fun argTypes tyargs -> StaticMethodCallOp(bindModuleFunctionWithCallSiteArgs(ty, nm, argTypes, tyargs))) + let meths = ty.GetMethods(staticBindingFlags) |> Array.filter (fun mi -> mi.Name = nm) + match meths with + | [||] -> + raise <| System.InvalidOperationException (String.Format(SR.GetString(SR.QcannotBindFunction), nm, ty.ToString())) + | [| res |] -> + Unique(StaticMethodCallOp(res)) + | [| res1; res2 |] when nWitnesses > 0 -> + if res1.GetParameters().Length < res2.GetParameters().Length then + Unique(StaticMethodCallWOp(res1, res2, nWitnesses)) + else + Unique(StaticMethodCallWOp(res2, res1, nWitnesses)) + | _ -> + Ambiguous(fun argTypes tyargs -> + if nWitnesses = 0 then + let minfo = bindModuleFunctionWithCallSiteArgs(ty, nm, argTypes, tyargs) + StaticMethodCallOp minfo + else + let minfo = bindModuleFunctionWithCallSiteArgs(ty, nm, List.skip nWitnesses argTypes, tyargs) + let minfoW = bindModuleFunctionWithCallSiteArgs(ty, nm, argTypes, tyargs) + StaticMethodCallWOp(minfo, minfoW, nWitnesses)) and u_MethodInfoData st = u_tup5 u_NamedType (u_list u_dtype) u_dtype u_string u_int st @@ -1482,7 +1527,7 @@ module Patterns = let tag = u_byte_as_int st match tag with | 0 -> - match u_ModuleDefn st with + match u_ModuleDefn 0 st with | Unique(StaticMethodCallOp(minfo)) -> (minfo :> MethodBase) | Unique(StaticPropGetOp(pinfo)) -> (pinfo.GetGetMethod(true) :> MethodBase) | Ambiguous(_) -> raise (System.Reflection.AmbiguousMatchException()) @@ -1497,26 +1542,42 @@ module Patterns = (minfo :> MethodBase) | 2 -> let data = u_CtorInfoData st - let cinfo = bindGenericCtor(data) in - (cinfo :> MethodBase) + let cinfo = bindGenericCtor(data) + (cinfo :> MethodBase) + | 3 -> + let nWitnesses = u_int st + match u_ModuleDefn nWitnesses st with + | Unique(StaticMethodCallOp(minfo)) -> (minfo :> MethodBase) + | Unique(StaticMethodCallWOp(_minfo, minfoW, _)) -> (minfoW :> MethodBase) + | Unique(StaticPropGetOp(pinfo)) -> (pinfo.GetGetMethod(true) :> MethodBase) + | Ambiguous(_) -> raise (System.Reflection.AmbiguousMatchException()) + | _ -> failwith "unreachable" | _ -> failwith "u_MethodBase" - and u_constSpec st = + and instModuleDefnOp r tyargs = + match r with + | StaticMethodCallOp(minfo) -> StaticMethodCallOp(instMeth(minfo,tyargs)) + | StaticMethodCallWOp(minfo, minfoW, n) -> StaticMethodCallWOp(instMeth(minfo,tyargs), instMeth(minfoW,tyargs), n) + // OK to throw away the tyargs here since this only non-generic values in modules get represented by static properties + | x -> x + + and u_opSpec st = let tag = u_byte_as_int st if tag = 1 then - let bindModuleDefn r tyargs = - match r with - | StaticMethodCallOp(minfo) -> StaticMethodCallOp(instMeth(minfo,tyargs)) - // OK to throw away the tyargs here since this only non-generic values in modules get represented by static properties - | x -> x - match u_ModuleDefn st with - | Unique(r) -> Unique(bindModuleDefn r) - | Ambiguous(f) -> Ambiguous(fun argTypes tyargs -> bindModuleDefn (f argTypes tyargs) tyargs) + match u_ModuleDefn 0 st with + | Unique(r) -> Unique(instModuleDefnOp r) + | Ambiguous(f) -> Ambiguous(fun argTypes tyargs -> instModuleDefnOp (f argTypes tyargs) tyargs) + elif tag = 51 then + let nWitnesses = u_int st + match u_ModuleDefn nWitnesses st with + | Unique(r) -> Unique(instModuleDefnOp r) + | Ambiguous(f) -> Ambiguous(fun argTypes tyargs -> instModuleDefnOp (f argTypes tyargs) tyargs) else let constSpec = match tag with | 0 -> u_void st |> (fun () NoTyArgs -> IfThenElseOp) + // 1 taken above | 2 -> u_void st |> (fun () NoTyArgs -> LetRecOp) | 3 -> u_NamedType st |> (fun x tyargs -> NewRecordOp (mkNamedType(x,tyargs))) | 4 -> u_RecdField st |> (fun prop tyargs -> InstancePropGetOp(prop tyargs)) @@ -1564,8 +1625,16 @@ module Patterns = | 47 -> u_void st |> (fun () NoTyArgs -> TryFinallyOp) | 48 -> u_void st |> (fun () NoTyArgs -> TryWithOp) | 49 -> u_void st |> (fun () NoTyArgs -> VarSetOp) - | _ -> failwithf "u_constSpec, unrecognized tag %d" tag + | 50 -> + u_tup3 u_MethodInfoData u_MethodInfoData u_int st |> (fun (m1, m2, n) tyargs -> + let minfo = bindMeth (m1,tyargs) + let minfoW = bindMeth (m2, tyargs) + if minfo.IsStatic then StaticMethodCallWOp(minfo, minfoW, n) + else InstanceMethodCallWOp(minfo, minfoW, n)) + // 51 taken above + | _ -> failwithf "u_opSpec, unrecognized tag %d" tag Unique constSpec + let u_ReflectedDefinition = u_tup2 u_MethodBase u_Expr let u_ReflectedDefinitions = u_list u_ReflectedDefinition @@ -1919,6 +1988,16 @@ type Expr with checkNonNull "methodInfo" methodInfo mkInstanceMethodCall (obj,methodInfo,arguments) + static member CallWithWitnesses (methodInfo:MethodInfo, methodInfoWithWitnesses:MethodInfo, witnessArguments, arguments) = + checkNonNull "methodInfo" methodInfo + checkNonNull "methodInfo" methodInfoWithWitnesses + mkStaticMethodCallW (methodInfo, methodInfoWithWitnesses, List.length witnessArguments, witnessArguments@arguments) + + static member CallWithWitnesses (obj:Expr, methodInfo:MethodInfo, methodInfoWithWitnesses:MethodInfo, witnessArguments, arguments) = + checkNonNull "methodInfo" methodInfo + checkNonNull "methodInfo" methodInfoWithWitnesses + mkInstanceMethodCallW (obj, methodInfo, methodInfoWithWitnesses, List.length witnessArguments, witnessArguments@arguments) + static member Coerce (source:Expr, target:Type) = checkNonNull "target" target mkCoerce (target, source) @@ -2241,6 +2320,8 @@ module ExprShape = | DefaultValueOp(ty),_ -> mkDefaultValue(ty) | StaticMethodCallOp(minfo),_ -> mkStaticMethodCall(minfo,arguments) | InstanceMethodCallOp(minfo),obj::args -> mkInstanceMethodCall(obj,minfo,args) + | StaticMethodCallWOp(minfo, minfoW, n),_ -> mkStaticMethodCallW(minfo,minfoW,n,arguments) + | InstanceMethodCallWOp(minfo, minfoW, n),obj::args -> mkInstanceMethodCallW(obj,minfo,minfoW,n,args) | CoerceOp(ty),[arg] -> mkCoerce(ty,arg) | NewArrayOp(ty),_ -> mkNewArray(ty,arguments) | NewDelegateOp(ty),[arg] -> mkNewDelegate(ty,arg) diff --git a/src/fsharp/FSharp.Core/quotations.fsi b/src/fsharp/FSharp.Core/quotations.fsi index f9ab5d7089f..80517d5d879 100644 --- a/src/fsharp/FSharp.Core/quotations.fsi +++ b/src/fsharp/FSharp.Core/quotations.fsi @@ -84,20 +84,37 @@ type Expr = /// The function to apply. /// The list of lists of arguments to the function. /// The resulting expression. - static member Applications: functionExpr:Expr * arguments:list> -> Expr + static member Applications: functionExpr:Expr * arguments:list -> Expr /// Builds an expression that represents a call to an static method or module-bound function /// The MethodInfo describing the method to call. /// The list of arguments to the method. /// The resulting expression. - static member Call : methodInfo:MethodInfo * arguments:list -> Expr + static member Call : methodInfo:MethodInfo * arguments:Expr list -> Expr /// Builds an expression that represents a call to an instance method associated with an object /// The input object. /// The description of the method to call. /// The list of arguments to the method. /// The resulting expression. - static member Call : obj:Expr * methodInfo:MethodInfo * arguments:list -> Expr + static member Call : obj:Expr * methodInfo: MethodInfo * arguments:Expr list -> Expr + + /// Builds an expression that represents a call to an static method or module-bound function + /// The MethodInfo describing the method to call. + /// The additional MethodInfo describing the method to call, accepting witnesses. + /// The list of witnesses to the method. + /// The list of arguments to the method. + /// The resulting expression. + static member CallWithWitnesses: methodInfo: MethodInfo * methodInfoWithWitnesses: MethodInfo * witnesses: Expr list * arguments: Expr list -> Expr + + /// Builds an expression that represents a call to an instance method associated with an object + /// The input object. + /// The description of the method to call. + /// The additional MethodInfo describing the method to call, accepting witnesses. + /// The list of witnesses to the method. + /// The list of arguments to the method. + /// The resulting expression. + static member CallWithWitnesses: obj:Expr * methodInfo:MethodInfo * methodInfoWithWitnesses: MethodInfo * witnesses: Expr list * arguments:Expr list -> Expr /// Builds an expression that represents the coercion of an expression to a type /// The expression to coerce. @@ -370,7 +387,7 @@ type Expr = /// The spliced expressions to replace references to spliced expressions. /// The serialized form of the quoted expression. /// The resulting expression. - static member Deserialize : qualifyingType:System.Type * spliceTypes:list * spliceExprs:list * bytes:byte[] -> Expr + static member Deserialize : qualifyingType:System.Type * spliceTypes:list * spliceExprs:Expr list * bytes:byte[] -> Expr /// This function is called automatically when quotation syntax (<@ @>) and other sources of /// quotations are used. @@ -449,6 +466,12 @@ module Patterns = [] val (|Call|_|) : input:Expr -> (Expr option * MethodInfo * Expr list) option + /// An active pattern to recognize expressions that represent calls to static and instance methods, and functions defined in modules, including witness arguments + /// The input expression to match against. + /// (Expr option * MethodInfo * MethodInfo * Expr list) option + [] + val (|CallWithWitnesses|_|) : input:Expr -> (Expr option * MethodInfo * MethodInfo * Expr list * Expr list) option + /// An active pattern to recognize expressions that represent coercions from one type to another /// The input expression to match against. /// (Expr * Type) option @@ -770,7 +793,7 @@ module DerivedPatterns = /// instance method), the generic type instantiation (non-empty if the target is a generic /// instantiation), and the arguments to the function or method. [] - val (|SpecificCall|_|) : templateParameter:Expr -> (Expr -> (Expr option * list * list) option) + val (|SpecificCall|_|) : templateParameter:Expr -> (Expr -> (Expr option * list * Expr list) option) /// An active pattern to recognize methods that have an associated ReflectedDefinition /// The description of the method. @@ -801,11 +824,11 @@ module ExprShape = val (|ShapeVar|ShapeLambda|ShapeCombination|) : input:Expr -> Choice)> // ConstApp + (obj * Expr list)> // ConstApp /// Re-build combination expressions. The first parameter should be an object /// returned by the ShapeCombination case of the active pattern in this module. /// The input shape. /// The list of arguments. /// The rebuilt expression. - val RebuildShapeCombination : shape:obj * arguments:list -> Expr + val RebuildShapeCombination : shape:obj * arguments:Expr list -> Expr diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 7fb12462b84..8b16d200d60 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -251,6 +251,7 @@ type cenv = /// Used to apply forced inlining optimizations to witnesses generated late during codegen mutable optimizeDuringCodeGen : (Expr -> Expr) + } @@ -738,12 +739,12 @@ type ValStorage = /// Indicates the value is stored in a static field. | StaticField of ILFieldSpec * ValRef * (*hasLiteralAttr:*)bool * ILType * string * ILType * ILMethodRef * ILMethodRef * OptionalShadowLocal - /// Indicates the value is "stored" as a property that recomputes it each time it is referenced. Used for simple constants that do not cause initialization triggers + /// Indicates the value is represented as a property that recomputes it each time it is referenced. Used for simple constants that do not cause initialization triggers | StaticProperty of ILMethodSpec * OptionalShadowLocal - /// Indicates the value is "stored" as a IL static method (in a "main" class for a F# + /// Indicates the value is represented as an IL method (in a "main" class for a F# /// compilation unit, or as a member) according to its inferred or specified arity. - | Method of ValReprInfo * ValRef * ILMethodSpec * Range.range * Typars * Typars * CurriedArgInfos * ArgReprInfo list * TraitWitnessInfos * TType list * ArgReprInfo + | Method of ValReprInfo * ValRef * ILMethodSpec * ILMethodSpec * Range.range * Typars * Typars * CurriedArgInfos * ArgReprInfo list * TraitWitnessInfos * TType list * ArgReprInfo /// Indicates the value is stored at the given position in the closure environment accessed via "ldarg 0" | Env of ILType * int * ILFieldSpec * NamedLocalIlxClosureInfo ref option @@ -956,20 +957,30 @@ let GetMethodSpecForMemberVal amap g (memberInfo:ValMemberInfo) (vref:ValRef) = thisArgTys let methodArgTys, paramInfos = List.unzip flatArgInfos let isSlotSig = memberInfo.MemberFlags.IsDispatchSlot || memberInfo.MemberFlags.IsOverrideOrExplicitImpl - let ilWitnessArgTys = GenTypes amap m tyenvUnderTypars (GenWitnessTys g cxs) let ilMethodArgTys = GenParamTypes amap m tyenvUnderTypars isSlotSig methodArgTys let ilMethodInst = GenTypeArgs amap m tyenvUnderTypars (List.map mkTyparTy mtps) - let mspec = mkILInstanceMethSpecInTy (ilTy, vref.CompiledName, ilWitnessArgTys @ ilMethodArgTys, ilActualRetTy, ilMethodInst) + let mspec = mkILInstanceMethSpecInTy (ilTy, vref.CompiledName, ilMethodArgTys, ilActualRetTy, ilMethodInst) + let mspecW = + if not g.generateWitnesses || cxs.IsEmpty then + mspec + else + let ilWitnessArgTys = GenTypes amap m tyenvUnderTypars (GenWitnessTys g cxs) + mkILInstanceMethSpecInTy (ilTy, vref.CompiledName, ilWitnessArgTys @ ilMethodArgTys, ilActualRetTy, ilMethodInst) - mspec, ctps, mtps, curriedArgInfos, paramInfos, retInfo, cxs, methodArgTys + mspec, mspecW, ctps, mtps, curriedArgInfos, paramInfos, retInfo, cxs, methodArgTys else let methodArgTys, paramInfos = List.unzip flatArgInfos - let ilWitnessArgTys = GenTypes amap m tyenvUnderTypars (GenWitnessTys g cxs) let ilMethodArgTys = GenParamTypes amap m tyenvUnderTypars false methodArgTys let ilMethodInst = GenTypeArgs amap m tyenvUnderTypars (List.map mkTyparTy mtps) - let mspec = mkILStaticMethSpecInTy (ilTy, vref.CompiledName, ilWitnessArgTys @ ilMethodArgTys, ilActualRetTy, ilMethodInst) + let mspec = mkILStaticMethSpecInTy (ilTy, vref.CompiledName, ilMethodArgTys, ilActualRetTy, ilMethodInst) + let mspecW = + if not g.generateWitnesses || cxs.IsEmpty then + mspec + else + let ilWitnessArgTys = GenTypes amap m tyenvUnderTypars (GenWitnessTys g cxs) + mkILStaticMethSpecInTy (ilTy, vref.CompiledName, ilWitnessArgTys @ ilMethodArgTys, ilActualRetTy, ilMethodInst) - mspec, ctps, mtps, curriedArgInfos, paramInfos, retInfo, cxs, methodArgTys + mspec, mspecW, ctps, mtps, curriedArgInfos, paramInfos, retInfo, cxs, methodArgTys /// Determine how a top-level value is represented, when representing as a field, by computing an ILFieldSpec let ComputeFieldSpecForVal(optIntraAssemblyInfo:IlxGenIntraAssemblyInfo option, isInteractive, g, ilTyForProperty, vspec:Val, nm, m, cloc, ilTy, ilGetterMethRef) = @@ -1006,8 +1017,8 @@ let ComputeStorageForFSharpValue amap g cloc optIntraAssemblyInfo optShadowLocal /// Compute the representation information for an F#-declared member let ComputeStorageForFSharpMember amap g topValInfo memberInfo (vref:ValRef) m = - let mspec, ctps, mtps, curriedArgInfos, paramInfos, retInfo, witnessInfos, methodArgTys = GetMethodSpecForMemberVal amap g memberInfo vref - Method (topValInfo, vref, mspec, m, ctps, mtps, curriedArgInfos, paramInfos, witnessInfos, methodArgTys, retInfo) + let mspec, mspecW, ctps, mtps, curriedArgInfos, paramInfos, retInfo, witnessInfos, methodArgTys = GetMethodSpecForMemberVal amap g memberInfo vref + Method (topValInfo, vref, mspec, mspecW, m, ctps, mtps, curriedArgInfos, paramInfos, witnessInfos, methodArgTys, retInfo) /// Compute the representation information for an F#-declared function in a module or an F#-decalared extension member. /// Note, there is considerable overlap with ComputeStorageForFSharpMember/GetMethodSpecForMemberVal and these could be @@ -1021,9 +1032,14 @@ let ComputeStorageForFSharpFunctionOrFSharpExtensionMember amap g cloc topValInf let ilRetTy = GenReturnType amap m tyenvUnderTypars returnTy let ilLocTy = mkILTyForCompLoc cloc let ilMethodInst = GenTypeArgs amap m tyenvUnderTypars (List.map mkTyparTy tps) - let ilWitnessArgTys = GenTypes amap m tyenvUnderTypars (GenWitnessTys g cxs) - let mspec = mkILStaticMethSpecInTy (ilLocTy, nm, (ilWitnessArgTys @ ilMethodArgTys), ilRetTy, ilMethodInst) - Method (topValInfo, vref, mspec, m, [], tps, curriedArgInfos, paramInfos, cxs, argTys, retInfo) + let mspec = mkILStaticMethSpecInTy (ilLocTy, nm, ilMethodArgTys, ilRetTy, ilMethodInst) + let mspecW = + if not g.generateWitnesses || cxs.IsEmpty then + mspec + else + let ilWitnessArgTys = GenTypes amap m tyenvUnderTypars (GenWitnessTys g cxs) + mkILStaticMethSpecInTy (ilLocTy, nm, (ilWitnessArgTys @ ilMethodArgTys), ilRetTy, ilMethodInst) + Method (topValInfo, vref, mspec, mspecW, m, [], tps, curriedArgInfos, paramInfos, cxs, argTys, retInfo) /// Determine if an F#-declared value, method or function is compiled as a method. let IsFSharpValCompiledAsMethod g (v:Val) = @@ -2861,8 +2877,7 @@ and GenUntupledArgExpr cenv cgbuf eenv m argInfos expr sequel = GenBinding cenv cgbuf eenvinner bind let tys = destRefTupleTy cenv.g ty assert (tys.Length = numRequiredExprs) - // TODO - tupInfoRef - argInfos |> List.iteri (fun i _ -> GenGetTupleField cenv cgbuf eenvinner (tupInfoRef (* TODO *), loce, tys, i, m) Continue) + argInfos |> List.iteri (fun i _ -> GenGetTupleField cenv cgbuf eenvinner (tupInfoRef, loce, tys, i, m) Continue) GenSequel cenv eenv.cloc cgbuf sequel ) @@ -2945,7 +2960,7 @@ and GenApp cenv cgbuf eenv (f, fty, tyargs, curriedArgs, m) sequel = let storage = StorageForValRef m vref eenv match storage with - | Method (_, _, mspec, _, _, _, _, _, _, _, _) -> + | Method (_, _, mspec, _, _, _, _, _, _, _, _, _) -> CG.EmitInstr cgbuf (pop 0) (Push [cenv.g.iltyp_RuntimeMethodHandle]) (I_ldtoken (ILToken.ILMethod mspec)) | _ -> errorR(Error(FSComp.SR.ilxgenUnexpectedArgumentToMethodHandleOfDuringCodegen(), m)) @@ -2972,7 +2987,7 @@ and GenApp cenv cgbuf eenv (f, fty, tyargs, curriedArgs, m) sequel = when (let storage = StorageForValRef m vref eenv match storage with - | Method (topValInfo, vref, _, _, _, _, _, _, _, _, _) -> + | Method (topValInfo, vref, _, _, _, _, _, _, _, _, _, _) -> (let tps, argtys, _, _ = GetTopValTypeInFSharpForm cenv.g topValInfo vref.Type m tps.Length = tyargs.Length && argtys.Length <= curriedArgs.Length) @@ -2980,24 +2995,45 @@ and GenApp cenv cgbuf eenv (f, fty, tyargs, curriedArgs, m) sequel = let storage = StorageForValRef m vref eenv match storage with - | Method (topValInfo, vref, mspec, _, ctps, mtps, curriedArgInfos, _, _, _, _) -> + | Method (topValInfo, vref, mspec, mspecW, _, ctps, mtps, curriedArgInfos, _, _, _, _) -> + let nowArgs, laterArgs = List.splitAt curriedArgInfos.Length curriedArgs let actualRetTy = applyTys cenv.g vref.Type (tyargs, nowArgs) - let _, _cxs, curriedArgInfos, returnTy, _ = GetTopValTypeInCompiledForm cenv.g topValInfo vref.Type m + + let _, cxs, curriedArgInfos, returnTy, _ = GetTopValTypeInCompiledForm cenv.g topValInfo vref.Type m + + let mspec = + if not cenv.g.generateWitnesses || cxs.IsEmpty then + mspec + else + mspecW let witnessArgs = - let ctyargs, mtyargs = List.splitAt ctps.Length tyargs - - // Witness for enclosing type parameters must be passed to static members and constructors - // For non-extension instance methods they are stored as fields. - let cwitnesses = - if vref.IsInstanceMember && not vref.IsExtensionMember then - [] - else - ConstraintSolver.CodegenWitnessesForTyparInst cenv.tcVal cenv.g cenv.amap m ctps ctyargs |> CommitOperationResult - let mwitnesses = ConstraintSolver.CodegenWitnessesForTyparInst cenv.tcVal cenv.g cenv.amap m mtps mtyargs |> CommitOperationResult - cwitnesses @ mwitnesses + if not cenv.g.generateWitnesses || cxs.IsEmpty then + [] + else + let _ctyargs, mtyargs = List.splitAt ctps.Length tyargs + + // Witness for enclosing type parameters are not currently allowed, because these can never be 'inline'. + // Regardless, even if they were they must be passed to static members and constructors + // For non-extension instance methods would be stored as fields, if they were permitted. + //let cwitnesses = + // if vref.IsInstanceMember && not vref.IsExtensionMember then + // [] + // else + // ConstraintSolver.CodegenWitnessesForTyparInst cenv.tcVal cenv.g cenv.amap m ctps ctyargs + // |> CommitOperationResult + // |> List.map snd + + // We currently should never have any class-quantified witnesses + //assert cwitnesses.IsEmpty + + let mwitnesses = + ConstraintSolver.CodegenWitnessesForTyparInst cenv.tcVal cenv.g cenv.amap m mtps mtyargs + |> CommitOperationResult + + mwitnesses let nowArgs = witnessArgs @ nowArgs @@ -3020,6 +3056,7 @@ and GenApp cenv cgbuf eenv (f, fty, tyargs, curriedArgs, m) sequel = List.splitAt numEnclILTypeArgs ilTyArgs let boxity = mspec.DeclaringType.Boxity + let mspec = mkILMethSpec (mspec.MethodRef, boxity, ilEnclArgTys, ilMethArgTys) // "Unit" return types on static methods become "void" @@ -3675,15 +3712,14 @@ and GenQuotation cenv cgbuf eenv (ast, conv, m, ety) sequel = let bytesExpr = Expr.Op(TOp.Bytes(astSerializedBytes), [], [], m) let deserializeExpr = - match QuotationTranslator.QuotationGenerationScope.ComputeQuotationFormat cenv.g with - | QuotationTranslator.QuotationSerializationFormat.FSharp_40_Plus -> + let qf = QuotationTranslator.QuotationGenerationScope.ComputeQuotationFormat cenv.g + if qf.SupportsDeserializeEx then let referencedTypeDefExprs = List.map (mkILNonGenericBoxedTy >> mkTypeOfExpr cenv m) referencedTypeDefs let referencedTypeDefsExpr = mkArray (cenv.g.system_Type_ty, referencedTypeDefExprs, m) let spliceTypesExpr = mkArray (cenv.g.system_Type_ty, spliceTypeExprs, m) let spliceArgsExpr = mkArray (rawTy, spliceArgExprs, m) mkCallDeserializeQuotationFSharp40Plus cenv.g m someTypeInModuleExpr referencedTypeDefsExpr spliceTypesExpr spliceArgsExpr bytesExpr - - | QuotationTranslator.QuotationSerializationFormat.FSharp_20_Plus -> + else let mkList ty els = List.foldBack (mkCons cenv.g ty) els (mkNil cenv.g m ty) let spliceTypesExpr = mkList cenv.g.system_Type_ty spliceTypeExprs let spliceArgsExpr = mkList rawTy spliceArgExprs @@ -3753,14 +3789,23 @@ and MakeNotSupportedExnExpr cenv eenv (argExpr, m) = Expr.Op(TOp.ILCall(false, false, false, true, NormalValUse, false, false, mref, [], [], [ety]), [], [argExpr], m) and GenTraitCall cenv cgbuf eenv (traitInfo: TraitConstraintInfo, argExprs, m) expr sequel = - match eenv.witnessesInScope.TryGetValue traitInfo.TraitKey with - | true, storage -> + let witness = + if cenv.g.generateWitnesses then + match eenv.witnessesInScope.TryGetValue traitInfo.TraitKey with + | true, storage -> Some storage + | _ -> None + else + None + + match witness with + | Some storage -> let ty = GenWitnessTy cenv.g traitInfo.TraitKey GenGetStorageAndSequel cenv cgbuf eenv m (ty, GenType cenv.amap m eenv.tyenv ty) storage (Some([], argExprs, m, sequel)) - | _ -> - assert false // We should now always find trait witnesses in scope + | None -> + // If witnesses are available, we should now always find trait witnesses in scope + assert not eenv.witnessesInScope.IsEmpty let minfoOpt = CommitOperationResult (ConstraintSolver.CodegenWitnessThatTypeSupportsTraitConstraint cenv.tcVal cenv.g cenv.amap m traitInfo argExprs) match minfoOpt with @@ -4644,9 +4689,26 @@ and GenDelegateExpr cenv cgbuf eenvouter expr (TObjExprMethod((TSlotSig(_, deleg /// Generate statically-resolved conditionals used for type-directed optimizations. and GenStaticOptimization cenv cgbuf eenv (constraints, e2, e3, _m) sequel = + // Note: during IlxGen, even if answer is StaticOptimizationAnswer.Unknown we discard the static optimization + // This means 'when ^T : ^T' is discarded if not resolved. + // + // This doesn't apply when witnesses are available. In that case, "when ^T : ^T" is resolved as 'Yes', + // this is because all the uses of "when ^T : ^T" in FSharp.Core (e.g. for are for deciding between the + // witness-based implementation and the legacy dynamic implementation, e.g. + // + // let inline ( * ) (x: ^T) (y: ^U) : ^V = + // MultiplyDynamic<(^T),(^U),(^V)> x y + // ... + // when ^T : ^T = ((^T or ^U): (static member (*) : ^T * ^U -> ^V) (x,y)) + // + // When witnesses are available we use the dynamic implementation. + let e = - if DecideStaticOptimizations cenv.g constraints = StaticOptimizationAnswer.Yes then e2 - else e3 + let haveWitnesses = not eenv.witnessesInScope.IsEmpty + if DecideStaticOptimizations cenv.g constraints haveWitnesses = StaticOptimizationAnswer.Yes then + e2 + else + e3 GenExpr cenv cgbuf eenv SPSuppress e sequel //------------------------------------------------------------------------- @@ -5184,12 +5246,22 @@ and GenBindingAfterSequencePoint cenv cgbuf eenv sp (TBind(vspec, rhsExpr, _)) s CommitStartScope cgbuf startScopeMarkOpt GenExpr cenv cgbuf eenv SPSuppress cctorBody discard - | Method (topValInfo, _, mspec, _, ctps, mtps, curriedArgInfos, paramInfos, witnessInfos, argTys, retInfo) -> + | Method (topValInfo, _, mspec, mspecW, _, ctps, mtps, curriedArgInfos, paramInfos, witnessInfos, argTys, retInfo) -> + let methLambdaTypars, methLambdaCtorThisValOpt, methLambdaBaseValOpt, methLambdaCurriedVars, methLambdaBody, methLambdaBodyTy = IteratedAdjustArityOfLambda cenv.g cenv.amap topValInfo rhsExpr + let methLambdaVars = List.concat methLambdaCurriedVars + CommitStartScope cgbuf startScopeMarkOpt - GenMethodForBinding cenv cgbuf eenv (vspec, mspec, access, ctps, mtps, witnessInfos, curriedArgInfos, paramInfos, argTys, retInfo, topValInfo, methLambdaCtorThisValOpt, methLambdaBaseValOpt, methLambdaTypars, methLambdaVars, methLambdaBody, methLambdaBodyTy) + + GenMethodForBinding cenv cgbuf eenv (vspec, mspec, false, access, ctps, mtps, [], curriedArgInfos, paramInfos, argTys, retInfo, topValInfo, methLambdaCtorThisValOpt, methLambdaBaseValOpt, methLambdaTypars, methLambdaVars, methLambdaBody, methLambdaBodyTy) + + // If generating witnesses, then generate the second entry point with additional arguments. + // Take a copy of the expression to ensure generated names are unique. + if cenv.g.generateWitnesses && not witnessInfos.IsEmpty then + let copyOfLambdaBody = copyExpr cenv.g CloneAll methLambdaBody + GenMethodForBinding cenv cgbuf eenv (vspec, mspecW, true, access, ctps, mtps, witnessInfos, curriedArgInfos, paramInfos, argTys, retInfo, topValInfo, methLambdaCtorThisValOpt, methLambdaBaseValOpt, methLambdaTypars, methLambdaVars, copyOfLambdaBody, methLambdaBodyTy) | StaticProperty (ilGetterMethSpec, optShadowLocal) -> @@ -5627,10 +5699,11 @@ and ComputeMethodImplAttribs cenv (_v:Val) attrs = and GenMethodForBinding cenv cgbuf eenv - (v:Val, mspec, access, ctps, mtps, witnessInfos, curriedArgInfos, paramInfos, argTys, retInfo, topValInfo, + (v:Val, mspec, hasWitnessArgs, access, ctps, mtps, witnessInfos, curriedArgInfos, paramInfos, argTys, retInfo, topValInfo, ctorThisValOpt, baseValOpt, methLambdaTypars, methLambdaVars, methLambdaBody, returnTy) = let m = v.Range + let selfMethodVars, nonSelfMethodVars, compileAsInstance = match v.MemberInfo with | Some _ when ValSpecIsCompiledAsInstance cenv.g v -> @@ -5649,14 +5722,17 @@ and GenMethodForBinding // for the big lambda ("tlambda") of the implementation of the method. let eenvUnderMethLambdaTypars = EnvForTypars methLambdaTypars eenv let eenvUnderMethTypeClassTypars = EnvForTypars ctps eenv - let eenvUnderMethTypeTypars = EnvForTypars mtps eenvUnderMethTypeClassTypars + let eenvUnderMethTypeTypars = AddTyparsToEnv mtps eenvUnderMethTypeClassTypars // Add the arguments to the environment. We add an implicit 'this' argument to constructors let isCtor = v.IsConstructor let methLambdaWitnessInfos = - let methLambdaParentTypars, methLambdaMethTypars = List.splitAt ctps.Length methLambdaTypars - GetTraitWitnessInfosOfTypars cenv.g methLambdaParentTypars methLambdaMethTypars + if hasWitnessArgs then + let methLambdaParentTypars, methLambdaMethTypars = List.splitAt ctps.Length methLambdaTypars + GetTraitWitnessInfosOfTypars cenv.g methLambdaParentTypars methLambdaMethTypars + else + [] // If this assert fails then there is a mismatch in the number of trait constraints on the method type and the number // on the method implementation. @@ -5665,8 +5741,12 @@ and GenMethodForBinding let eenvForMeth = let eenvForMeth = eenvUnderMethLambdaTypars let numImplicitArgs = if isCtor then 1 else 0 - let eenvForMeth = AddStorageForLocalWitnesses eenvForMeth (methLambdaWitnessInfos |> List.mapi (fun i w -> (w, Arg (numImplicitArgs+i)))) - let numImplicitArgs = numImplicitArgs + List.length witnessInfos + let eenvForMeth = + if hasWitnessArgs then + AddStorageForLocalWitnesses eenvForMeth (methLambdaWitnessInfos |> List.mapi (fun i w -> (w, Arg (numImplicitArgs+i)))) + else + eenvForMeth + let numImplicitArgs = numImplicitArgs + (if hasWitnessArgs then List.length witnessInfos else 0) let eenvForMeth = AddStorageForLocalVals cenv.g (List.mapi (fun i v -> (v, Arg (numImplicitArgs+i))) nonUnitMethodVars) eenvForMeth eenvForMeth @@ -5691,9 +5771,12 @@ and GenMethodForBinding | _ -> // Replace the body of ValInline.PseudoVal "must inline" methods with a 'throw' - // However still generate the code for reflection etc. + // For witness-passing methods, don't do this is `isLegacy` flag specified + // on the attribute. let bodyExpr = - if HasFSharpAttribute cenv.g cenv.g.attrib_NoDynamicInvocationAttribute v.Attribs then + let attr = TryFindFSharpBoolAttributeAssumeFalse cenv.g cenv.g.attrib_NoDynamicInvocationAttribute v.Attribs + if (not hasWitnessArgs && attr.IsSome) || + (hasWitnessArgs && attr = Some false) then let exnArg = mkString cenv.g m (FSComp.SR.ilDynamicInvocationNotSupported(v.CompiledName)) let exnExpr = MakeNotSupportedExnExpr cenv eenv (exnArg, m) mkThrow m returnTy exnExpr @@ -5741,99 +5824,77 @@ and GenMethodForBinding let methName = mspec.Name let tref = mspec.MethodRef.DeclaringTypeRef - let EmitTheMethodDef (mdef:ILMethodDef) = - // Does the function have an explicit [] attribute? - let isExplicitEntryPoint = HasFSharpAttribute cenv.g cenv.g.attrib_EntryPointAttribute attrs - - let mdef = - mdef - .WithSecurity(not (List.isEmpty securityAttributes)) - .WithPInvoke(hasDllImport) - .WithPreserveSig(hasPreserveSigImplFlag || hasPreserveSigNamedArg) - .WithSynchronized(hasSynchronizedImplFlag) - .WithNoInlining(hasNoInliningFlag) - .WithAggressiveInlining(hasAggressiveInliningImplFlag) - .With(isEntryPoint=isExplicitEntryPoint, securityDecls=secDecls) - - let mdef = - if // operator names - mdef.Name.StartsWithOrdinal("op_") || - // active pattern names - mdef.Name.StartsWithOrdinal("|") || - // event add/remove method - v.val_flags.IsGeneratedEventVal then - mdef.WithSpecialName - else - mdef - CountMethodDef() - cgbuf.mgbuf.AddMethodDef(tref, mdef) - - match v.MemberInfo with // don't generate unimplemented abstracts | Some(memberInfo) when memberInfo.MemberFlags.IsDispatchSlot && not memberInfo.IsImplemented -> // skipping unimplemented abstract method () - | Some(memberInfo) when not v.IsExtensionMember -> - - let ilMethTypars = ilTypars |> List.drop mspec.DeclaringType.GenericArgs.Length - if memberInfo.MemberFlags.MemberKind = MemberKind.Constructor then - assert (isNil ilMethTypars) - let mdef = mkILCtor (access, ilParams, ilMethodBody) - let mdef = mdef.With(customAttrs= mkILCustomAttrs (ilAttrsThatGoOnPrimaryItem @ sourceNameAttribs @ ilAttrsCompilerGenerated)) - EmitTheMethodDef mdef - - elif memberInfo.MemberFlags.MemberKind = MemberKind.ClassConstructor then - assert (isNil ilMethTypars) - let mdef = mkILClassCtor ilMethodBody - let mdef = mdef.With(customAttrs= mkILCustomAttrs (ilAttrsThatGoOnPrimaryItem @ sourceNameAttribs @ ilAttrsCompilerGenerated)) - EmitTheMethodDef mdef - - // Generate virtual/override methods + method-impl information if needed - else - let mdef = - if not compileAsInstance then - mkILStaticMethod (ilMethTypars, v.CompiledName, access, ilParams, ilReturn, ilMethodBody) - elif (memberInfo.MemberFlags.IsDispatchSlot && memberInfo.IsImplemented) || - memberInfo.MemberFlags.IsOverrideOrExplicitImpl then + | Some(memberInfo) when (match memberInfo.MemberFlags.MemberKind with (MemberKind.PropertySet | MemberKind.PropertyGet) -> CompileAsEvent cenv.g v.Attribs | _ -> false) -> + // skip method generation for compiling the property as a .NET event + // Emit the pseudo-property as an event (but not if its a private method impl) + if access <> ILMemberAccess.Private then + let edef = GenEventForProperty cenv eenvForMeth mspec v ilAttrsThatGoOnPrimaryItem m returnTy + cgbuf.mgbuf.AddEventDef(tref, edef) + () - let flagFixups = ComputeFlagFixupsForMemberBinding cenv (v, memberInfo) - let mdef = mkILGenericVirtualMethod (v.CompiledName, ILMemberAccess.Public, ilMethTypars, ilParams, ilReturn, ilMethodBody) - let mdef = List.fold (fun mdef f -> f mdef) mdef flagFixups + | _ -> + + let mdef = + match v.MemberInfo with + | Some(memberInfo) when not v.IsExtensionMember -> + + let ilMethTypars = ilTypars |> List.drop mspec.DeclaringType.GenericArgs.Length + if memberInfo.MemberFlags.MemberKind = MemberKind.Constructor then + assert (isNil ilMethTypars) + let mdef = mkILCtor (access, ilParams, ilMethodBody) + let mdef = mdef.With(customAttrs= mkILCustomAttrs (ilAttrsThatGoOnPrimaryItem @ sourceNameAttribs @ ilAttrsCompilerGenerated)) + mdef - // fixup can potentially change name of reflected definition that was already recorded - patch it if necessary - cgbuf.mgbuf.ReplaceNameOfReflectedDefinition(v, mdef.Name) - mdef - else - mkILGenericNonVirtualMethod (v.CompiledName, access, ilMethTypars, ilParams, ilReturn, ilMethodBody) + elif memberInfo.MemberFlags.MemberKind = MemberKind.ClassConstructor then + assert (isNil ilMethTypars) + let mdef = mkILClassCtor ilMethodBody + let mdef = mdef.With(customAttrs= mkILCustomAttrs (ilAttrsThatGoOnPrimaryItem @ sourceNameAttribs @ ilAttrsCompilerGenerated)) + mdef + + // Generate virtual/override methods + method-impl information if needed + else + let mdef = + if not compileAsInstance then + mkILStaticMethod (ilMethTypars, v.CompiledName, access, ilParams, ilReturn, ilMethodBody) + + elif (memberInfo.MemberFlags.IsDispatchSlot && memberInfo.IsImplemented) || + memberInfo.MemberFlags.IsOverrideOrExplicitImpl then - let isAbstract = - memberInfo.MemberFlags.IsDispatchSlot && - let tcref = v.MemberApparentEntity - not tcref.Deref.IsFSharpDelegateTycon + let flagFixups = ComputeFlagFixupsForMemberBinding cenv (v, memberInfo) + let mdef = mkILGenericVirtualMethod (v.CompiledName, ILMemberAccess.Public, ilMethTypars, ilParams, ilReturn, ilMethodBody) + let mdef = List.fold (fun mdef f -> f mdef) mdef flagFixups + + // fixup can potentially change name of reflected definition that was already recorded - patch it if necessary + cgbuf.mgbuf.ReplaceNameOfReflectedDefinition(v, mdef.Name) + mdef + else + mkILGenericNonVirtualMethod (v.CompiledName, access, ilMethTypars, ilParams, ilReturn, ilMethodBody) - let mdef = - if mdef.IsVirtual then - mdef.WithFinal(memberInfo.MemberFlags.IsFinal).WithAbstract(isAbstract) - else mdef + let isAbstract = + memberInfo.MemberFlags.IsDispatchSlot && + let tcref = v.MemberApparentEntity + not tcref.Deref.IsFSharpDelegateTycon - match memberInfo.MemberFlags.MemberKind with + let mdef = + if mdef.IsVirtual then + mdef.WithFinal(memberInfo.MemberFlags.IsFinal).WithAbstract(isAbstract) + else mdef + + match memberInfo.MemberFlags.MemberKind with - | (MemberKind.PropertySet | MemberKind.PropertyGet) -> - if not (isNil ilMethTypars) then - error(InternalError("A property may not be more generic than the enclosing type - constrain the polymorphism in the expression", v.Range)) + | (MemberKind.PropertySet | MemberKind.PropertyGet) -> + if not (isNil ilMethTypars) then + error(InternalError("A property may not be more generic than the enclosing type - constrain the polymorphism in the expression", v.Range)) - // Check if we're compiling the property as a .NET event - if CompileAsEvent cenv.g v.Attribs then + // Check if we're compiling the property as a .NET event + assert not (CompileAsEvent cenv.g v.Attribs) - // Emit the pseudo-property as an event, but not if its a private method impl - if mdef.Access <> ILMemberAccess.Private then - let edef = GenEventForProperty cenv eenvForMeth mspec v ilAttrsThatGoOnPrimaryItem m returnTy - cgbuf.mgbuf.AddEventDef(tref, edef) - // The method def is dropped on the floor here - - else // Emit the property, but not if its a private method impl if mdef.Access <> ILMemberAccess.Private then let vtyp = ReturnTypeOfPropertyVal cenv.g v @@ -5844,26 +5905,53 @@ and GenMethodForBinding // Add the special name flag for all properties let mdef = mdef.WithSpecialName.With(customAttrs= mkILCustomAttrs ((GenAttrs cenv eenv attrsAppliedToGetterOrSetter) @ sourceNameAttribs @ ilAttrsCompilerGenerated)) - EmitTheMethodDef mdef - | _ -> - let mdef = mdef.With(customAttrs= mkILCustomAttrs (ilAttrsThatGoOnPrimaryItem @ sourceNameAttribs @ ilAttrsCompilerGenerated)) - EmitTheMethodDef mdef + mdef + | _ -> + let mdef = mdef.With(customAttrs= mkILCustomAttrs (ilAttrsThatGoOnPrimaryItem @ sourceNameAttribs @ ilAttrsCompilerGenerated)) + mdef - | _ -> - let mdef = mkILStaticMethod (ilTypars, methName, access, ilParams, ilReturn, ilMethodBody) + | _ -> + let mdef = mkILStaticMethod (ilTypars, methName, access, ilParams, ilReturn, ilMethodBody) + + // For extension properties, also emit attrsAppliedToGetterOrSetter on the getter or setter method + let ilAttrs = + match v.MemberInfo with + | Some memberInfo when v.IsExtensionMember -> + match memberInfo.MemberFlags.MemberKind with + | (MemberKind.PropertySet | MemberKind.PropertyGet) -> ilAttrsThatGoOnPrimaryItem @ GenAttrs cenv eenv attrsAppliedToGetterOrSetter + | _ -> ilAttrsThatGoOnPrimaryItem + | _ -> ilAttrsThatGoOnPrimaryItem + + let ilCustomAttrs = mkILCustomAttrs (ilAttrs @ sourceNameAttribs @ ilAttrsCompilerGenerated) + let mdef = mdef.With(customAttrs= ilCustomAttrs) + mdef - // For extension properties, also emit attrsAppliedToGetterOrSetter on the getter or setter method - let ilAttrs = - match v.MemberInfo with - | Some memberInfo when v.IsExtensionMember -> - match memberInfo.MemberFlags.MemberKind with - | (MemberKind.PropertySet | MemberKind.PropertyGet) -> ilAttrsThatGoOnPrimaryItem @ GenAttrs cenv eenv attrsAppliedToGetterOrSetter - | _ -> ilAttrsThatGoOnPrimaryItem - | _ -> ilAttrsThatGoOnPrimaryItem - - let ilCustomAttrs = mkILCustomAttrs (ilAttrs @ sourceNameAttribs @ ilAttrsCompilerGenerated) - let mdef = mdef.With(customAttrs= ilCustomAttrs) - EmitTheMethodDef mdef + // Does the function have an explicit [] attribute? + let isExplicitEntryPoint = HasFSharpAttribute cenv.g cenv.g.attrib_EntryPointAttribute attrs + + let mdef = + mdef + .WithSecurity(not (List.isEmpty securityAttributes)) + .WithPInvoke(hasDllImport) + .WithPreserveSig(hasPreserveSigImplFlag || hasPreserveSigNamedArg) + .WithSynchronized(hasSynchronizedImplFlag) + .WithNoInlining(hasNoInliningFlag) + .WithAggressiveInlining(hasAggressiveInliningImplFlag) + .With(isEntryPoint=isExplicitEntryPoint, securityDecls=secDecls) + + let mdef = + if // operator names + mdef.Name.StartsWithOrdinal("op_") || + // active pattern names + mdef.Name.StartsWithOrdinal("|") || + // event add/remove method + v.val_flags.IsGeneratedEventVal then + mdef.WithSpecialName + else + mdef + CountMethodDef() + cgbuf.mgbuf.AddMethodDef(tref, mdef) + and GenPInvokeMethod (nm, dll, namedArgs) = let decoder = AttributeDecoder namedArgs @@ -5970,7 +6058,7 @@ and GenSetStorage m cgbuf storage = | StaticProperty (ilGetterMethSpec, _) -> error(Error(FSComp.SR.ilStaticMethodIsNotLambda(ilGetterMethSpec.Name), m)) - | Method (_, _, mspec, m, _, _, _, _, _, _, _) -> + | Method (_, _, mspec, _, m, _, _, _, _, _, _, _) -> error(Error(FSComp.SR.ilStaticMethodIsNotLambda(mspec.Name), m)) | Null -> @@ -6018,7 +6106,7 @@ and GenGetStorageAndSequel cenv cgbuf eenv m (ty, ilTy) storage fetchSequel = CG.EmitInstr cgbuf (pop 0) (Push [ilTy]) (I_call (Normalcall, ilGetterMethSpec, None)) CommitGetStorageSequel cenv cgbuf eenv m ty None fetchSequel - | Method (topValInfo, vref, mspec, _, _, _, _, _, _, _, _) -> + | Method (topValInfo, vref, _, _, _, _, _, _, _, _, _, _) -> // Get a toplevel value as a first-class value. // We generate a lambda expression and that simply calls // the toplevel method. However we optimize the case where we are @@ -6034,7 +6122,7 @@ and GenGetStorageAndSequel cenv cgbuf eenv m (ty, ilTy) storage fetchSequel = GenLambda cenv cgbuf eenv false None expr Continue | Some (tyargs', args, m, sequel) -> let specializedExpr = - if isNil args && isNil tyargs' then failwith ("non-lambda at use of method " + mspec.Name) + if isNil args && isNil tyargs' then failwith ("non-lambda at use of method " + vref.CompiledName) MakeApplicationAndBetaReduce cenv.g (expr, exprty, [tyargs'], args, m) GenExpr cenv cgbuf eenv SPSuppress specializedExpr sequel @@ -6275,7 +6363,7 @@ and GenAttr amap g eenv (Attrib(_, k, args, props, _, _, _)) = | ILAttrib(mref) -> mkILMethSpec(mref, AsObject, [], []) | FSAttrib(vref) -> assert(vref.IsMember) - let mspec, _, _, _, _, _, _, _ = GetMethodSpecForMemberVal amap g (Option.get vref.MemberInfo) vref + let mspec, _, _, _, _, _, _, _, _ = GetMethodSpecForMemberVal amap g (Option.get vref.MemberInfo) vref mspec let ilArgs = List.map2 (fun (AttribExpr(_, vexpr)) ty -> GenAttribArg amap g eenv vexpr ty) args mspec.FormalArgTypes mkILCustomAttribMethRef g.ilg (mspec, ilArgs, props) @@ -6598,17 +6686,22 @@ and GenFieldInit m c = | _ -> error(Error(FSComp.SR.ilTypeCannotBeUsedForLiteralField(), m)) and GenWitnessParams cenv eenv m (witnessInfos: TraitWitnessInfos) = - let witnessTys = GenWitnessTys cenv.g witnessInfos - witnessTys |> List.mapi (fun i ty -> - { Name=Some ("_witness" + string i) - Type= GenType cenv.amap m eenv.tyenv ty - Default=None - Marshal=None - IsIn=false - IsOut=false - IsOptional=false - CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs []) - MetadataIndex = NoMetadataIdx }: ILParameter) + ((Set.empty, 0), witnessInfos) ||> List.mapFold (fun (used,i) witnessInfo -> + let ty = GenWitnessTy cenv.g witnessInfo + let nm = String.uncapitalize witnessInfo.MemberName + let nm = if used.Contains nm then nm + string i else nm + let ilParam = + { Name=Some nm + Type= GenType cenv.amap m eenv.tyenv ty + Default=None + Marshal=None + IsIn=false + IsOut=false + IsOptional=false + CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs []) + MetadataIndex = NoMetadataIdx }: ILParameter + ilParam, (used.Add nm, i + 1)) + |> fst and GenAbstractBinding cenv eenv tref (vref:ValRef) = assert(vref.IsMember) @@ -6621,11 +6714,15 @@ and GenAbstractBinding cenv eenv tref (vref:ValRef) = [ yield! GenAttrs cenv eenv attribs yield! GenCompilationArgumentCountsAttr cenv vref.Deref ] - let mspec, ctps, mtps, _curriedArgInfos, argInfos, retInfo, witnessInfos, methArgTys = GetMethodSpecForMemberVal cenv.amap cenv.g memberInfo vref + let mspec, _mspecW, ctps, mtps, _curriedArgInfos, argInfos, retInfo, witnessInfos, methArgTys = + GetMethodSpecForMemberVal cenv.amap cenv.g memberInfo vref + + assert witnessInfos.IsEmpty + let eenvForMeth = EnvForTypars (ctps@mtps) eenv let ilMethTypars = GenGenericParams cenv eenvForMeth mtps let ilReturn = GenReturnInfo cenv eenvForMeth mspec.FormalReturnType retInfo - let ilParams = GenParams cenv eenvForMeth m mspec witnessInfos argInfos methArgTys None + let ilParams = GenParams cenv eenvForMeth m mspec [] argInfos methArgTys None let compileAsInstance = ValRefIsCompiledAsInstanceMember cenv.g vref let mdef = mkILGenericVirtualMethod (vref.CompiledName, ILMemberAccess.Public, ilMethTypars, ilParams, ilReturn, MethodBody.Abstract) @@ -6666,7 +6763,7 @@ and GenAbstractBinding cenv eenv tref (vref:ValRef) = and GenToStringMethod cenv eenv ilThisTy m = [ match (eenv.valsInScope.TryFind cenv.g.sprintf_vref.Deref, eenv.valsInScope.TryFind cenv.g.new_format_vref.Deref) with - | Some(Lazy(Method(_, _, sprintfMethSpec, _, _, _, _, _, _, _, _))), Some(Lazy(Method(_, _, newFormatMethSpec, _, _, _, _, _, _, _, _))) -> + | Some(Lazy(Method(_, _, sprintfMethSpec, _, _, _, _, _, _, _, _, _))), Some(Lazy(Method(_, _, newFormatMethSpec, _, _, _, _, _, _, _, _, _))) -> // The type returned by the 'sprintf' call let funcTy = EraseClosures.mkILFuncTy cenv.g.ilxPubCloEnv ilThisTy cenv.g.ilg.typ_String // Give the instantiation of the printf format object, i.e. a Format`5 object compatible with StringFormat @@ -6995,7 +7092,7 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon:Tycon) = let (|Lazy|) (x:Lazy<_>) = x.Force() match (eenv.valsInScope.TryFind cenv.g.sprintf_vref.Deref, eenv.valsInScope.TryFind cenv.g.new_format_vref.Deref) with - | Some(Lazy(Method(_, _, sprintfMethSpec, _, _, _, _, _, _, _, _))), Some(Lazy(Method(_, _, newFormatMethSpec, _, _, _, _, _, _, _, _))) -> + | Some(Lazy(Method(_, _, sprintfMethSpec, _, _, _, _, _, _, _, _, _))), Some(Lazy(Method(_, _, newFormatMethSpec, _, _, _, _, _, _, _, _, _))) -> // The type returned by the 'sprintf' call let funcTy = EraseClosures.mkILFuncTy cenv.g.ilxPubCloEnv ilThisTy cenv.g.ilg.typ_String // Give the instantiation of the printf format object, i.e. a Format`5 object compatible with StringFormat diff --git a/src/fsharp/MethodCalls.fs b/src/fsharp/MethodCalls.fs index 150eb0a2980..c309114bdd8 100644 --- a/src/fsharp/MethodCalls.fs +++ b/src/fsharp/MethodCalls.fs @@ -1424,18 +1424,9 @@ let GenWitnessExpr amap g m (traitInfo: TraitConstraintInfo) argExprs = | Choice5Of5 () -> None -(* -let MakeNotSupportedExnExpr amap g eenv (argExpr, m) = - let ety = mkAppTy (cenv.g.FindSysTyconRef ["System"] "NotSupportedException") [] - let ilty = GenType cenv.amap m eenv.tyenv ety - let mref = mkILCtorMethSpecForTy(ilty, [cenv.g.ilg.typ_String]).MethodRef - Expr.Op(TOp.ILCall(false, false, false, true, NormalValUse, false, false, mref, [], [], [ety]), [], [argExpr], m) -*) - let GenWitnessExprLambda amap g m (traitInfo: TraitConstraintInfo) = - // TODO: use arg infos - let argtysl = GenWitnessArgTys traitInfo.TraitKey - let vse = argtysl |> List.mapiSquared (fun i j ty -> mkCompGenLocal m ("_warg" + string i + "_" + string j) ty) + let argtysl = GenWitnessArgTys g traitInfo.TraitKey + let vse = argtysl |> List.mapiSquared (fun i j ty -> mkCompGenLocal m ("arg" + string i + "_" + string j) ty) let vsl = List.mapSquared fst vse match GenWitnessExpr amap g m traitInfo (List.concat (List.mapSquared snd vse)) with | Some expr -> diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index 5b16fe345a3..30ff5d6ecbb 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -2303,6 +2303,6 @@ let CheckTopImpl (g, amap, reportErrors, infoReader, internalsVisibleToPaths, vi CheckModuleExpr cenv env mexpr CheckAttribs cenv env extraAttribs - if cenv.usesQuotations && QuotationTranslator.QuotationGenerationScope.ComputeQuotationFormat(g) = QuotationTranslator.QuotationSerializationFormat.FSharp_20_Plus then + if cenv.usesQuotations && not (QuotationTranslator.QuotationGenerationScope.ComputeQuotationFormat(g).SupportsDeserializeEx) then viewCcu.UsesFSharp20PlusQuotations <- true cenv.entryPointGiven, cenv.anonRecdTypes diff --git a/src/fsharp/QuotationPickler.fs b/src/fsharp/QuotationPickler.fs index c0e0360f6e8..85a8088dba2 100644 --- a/src/fsharp/QuotationPickler.fs +++ b/src/fsharp/QuotationPickler.fs @@ -46,14 +46,13 @@ type VarData = vType: TypeData vMutable: bool } -type FieldData = NamedTypeData * string -type RecdFieldData = NamedTypeData * string type PropInfoData = NamedTypeData * string * TypeData * TypeData list type CombOp = | AppOp | CondOp | ModuleValueOp of NamedTypeData * string * bool + | ModuleValueWOp of NamedTypeData * string * bool * int | LetRecOp | LetRecCombOp | LetOp @@ -83,6 +82,7 @@ type CombOp = | FieldGetOp of NamedTypeData * string | CtorCallOp of CtorData | MethodCallOp of MethodData + | MethodCallWOp of MethodData * MethodData * int | CoerceOp | NewArrayOp | DelegateOp @@ -126,7 +126,11 @@ let mkQuoteRaw40 (a) = QuoteRawExpr (a) let mkCond (x1, x2, x3) = CombExpr(CondOp, [], [x1;x2;x3]) -let mkModuleValueApp (tcref, nm, isProp, tyargs, args: ExprData list list) = CombExpr(ModuleValueOp(tcref, nm, isProp), tyargs, List.concat args) +let mkModuleValueApp (tcref, nm, isProp, tyargs, args: ExprData list) = + CombExpr(ModuleValueOp(tcref, nm, isProp), tyargs, args) + +let mkModuleValueWApp (tcref, nm, isProp, nWitnesses, tyargs, args: ExprData list) = + CombExpr(ModuleValueWOp(tcref, nm, isProp, nWitnesses), tyargs, args) let mkTuple (ty, x) = CombExpr(TupleMkOp, [ty], x) @@ -146,15 +150,15 @@ let mkLetRec (ves, body) = let mkRecdMk (n, tys, args) = CombExpr(RecdMkOp n, tys, args) -let mkRecdGet ((d1, d2), tyargs, args) = CombExpr(RecdGetOp(d1, d2), tyargs, args) +let mkRecdGet (d1, d2, tyargs, args) = CombExpr(RecdGetOp(d1, d2), tyargs, args) -let mkRecdSet ((d1, d2), tyargs, args) = CombExpr(RecdSetOp(d1, d2), tyargs, args) +let mkRecdSet (d1, d2, tyargs, args) = CombExpr(RecdSetOp(d1, d2), tyargs, args) -let mkUnion ((d1, d2), tyargs, args) = CombExpr(SumMkOp(d1, d2), tyargs, args) +let mkUnion (d1, d2, tyargs, args) = CombExpr(SumMkOp(d1, d2), tyargs, args) -let mkUnionFieldGet ((d1, d2, d3), tyargs, arg) = CombExpr(SumFieldGetOp(d1, d2, d3), tyargs, [arg]) +let mkUnionFieldGet (d1, d2, d3, tyargs, arg) = CombExpr(SumFieldGetOp(d1, d2, d3), tyargs, [arg]) -let mkUnionCaseTagTest ((d1, d2), tyargs, arg) = CombExpr(SumTagTestOp(d1, d2), tyargs, [arg]) +let mkUnionCaseTagTest (d1, d2, tyargs, arg) = CombExpr(SumTagTestOp(d1, d2), tyargs, [arg]) let mkTupleGet (ty, n, e) = CombExpr(TupleGetOp n, [ty], [e]) @@ -216,14 +220,16 @@ let mkPropGet (d, tyargs, args) = CombExpr(PropGetOp(d), tyargs, args) let mkPropSet (d, tyargs, args) = CombExpr(PropSetOp(d), tyargs, args) -let mkFieldGet ((d1, d2), tyargs, args) = CombExpr(FieldGetOp(d1, d2), tyargs, args) +let mkFieldGet (d1, d2, tyargs, args) = CombExpr(FieldGetOp(d1, d2), tyargs, args) -let mkFieldSet ((d1, d2), tyargs, args) = CombExpr(FieldSetOp(d1, d2), tyargs, args) +let mkFieldSet (d1, d2, tyargs, args) = CombExpr(FieldSetOp(d1, d2), tyargs, args) let mkCtorCall (d, tyargs, args) = CombExpr(CtorCallOp(d), tyargs, args) let mkMethodCall (d, tyargs, args) = CombExpr(MethodCallOp(d), tyargs, args) +let mkMethodCallW (d1, d2, d3, tyargs, args) = CombExpr(MethodCallWOp(d1, d2, d3), tyargs, args) + let mkAttributedExpression(e, attr) = AttrExpr(e, [attr]) let isAttributedExpression e = match e with AttrExpr(_, _) -> true | _ -> false @@ -410,7 +416,11 @@ let p_PropInfoData a st = let p_CombOp x st = match x with | CondOp -> p_byte 0 st - | ModuleValueOp (x, y, z) -> p_byte 1 st; p_tup3 p_NamedType p_string p_bool (x, y, z) st + | ModuleValueOp (x, y, z) -> + p_byte 1 st + p_NamedType x st + p_string y st + p_bool z st | LetRecOp -> p_byte 2 st | RecdMkOp a -> p_byte 3 st; p_NamedType a st | RecdGetOp (x, y) -> p_byte 4 st; p_recdFieldSpec (x, y) st @@ -457,6 +467,17 @@ let p_CombOp x st = | TryFinallyOp -> p_byte 47 st | TryWithOp -> p_byte 48 st | ExprSetOp -> p_byte 49 st + | MethodCallWOp (a, b, c) -> + p_byte 50 st + p_MethodData a st + p_MethodData b st + p_int c st + | ModuleValueWOp (x, y, z, n) -> + p_byte 51 st + p_int n st + p_NamedType x st + p_string y st + p_bool z st let rec p_expr x st = match x with @@ -475,7 +496,7 @@ type ModuleDefnData = IsProperty: bool } type MethodBaseData = - | ModuleDefn of ModuleDefnData + | ModuleDefn of ModuleDefnData * int | Method of MethodData | Ctor of CtorData @@ -483,11 +504,18 @@ let pickle = pickle_obj p_expr let p_MethodBase x st = match x with - | ModuleDefn md -> - p_byte 0 st - p_NamedType md.Module st - p_string md.Name st - p_bool md.IsProperty st + | ModuleDefn (md, nWitnesses) -> + if nWitnesses = 0 then + p_byte 0 st + p_NamedType md.Module st + p_string md.Name st + p_bool md.IsProperty st + else + p_byte 3 st + p_int nWitnesses st + p_NamedType md.Module st + p_string md.Name st + p_bool md.IsProperty st | Method md -> p_byte 1 st p_MethodData md st diff --git a/src/fsharp/QuotationPickler.fsi b/src/fsharp/QuotationPickler.fsi index ffe23215886..618dfd588d8 100644 --- a/src/fsharp/QuotationPickler.fsi +++ b/src/fsharp/QuotationPickler.fsi @@ -47,12 +47,10 @@ type ModuleDefnData = IsProperty: bool } type MethodBaseData = - | ModuleDefn of ModuleDefnData + | ModuleDefn of ModuleDefnData * int | Method of MethodData | Ctor of CtorData -type FieldData = NamedTypeData * string -type RecdFieldData = NamedTypeData * string type PropInfoData = NamedTypeData * string * TypeData * TypeData list val mkVar : int -> ExprData @@ -63,15 +61,16 @@ val mkLambda : VarData * ExprData -> ExprData val mkQuote : ExprData -> ExprData val mkQuoteRaw40 : ExprData -> ExprData // only available for FSharp.Core 4.4.0.0+ val mkCond : ExprData * ExprData * ExprData -> ExprData -val mkModuleValueApp : NamedTypeData * string * bool * TypeData list * ExprData list list -> ExprData +val mkModuleValueApp : NamedTypeData * string * bool * TypeData list * ExprData list -> ExprData +val mkModuleValueWApp : NamedTypeData * string * bool * int * TypeData list * ExprData list -> ExprData val mkLetRec : (VarData * ExprData) list * ExprData -> ExprData val mkLet : (VarData * ExprData) * ExprData -> ExprData val mkRecdMk : NamedTypeData * TypeData list * ExprData list -> ExprData -val mkRecdGet : RecdFieldData * TypeData list * ExprData list -> ExprData -val mkRecdSet : RecdFieldData * TypeData list * ExprData list -> ExprData -val mkUnion : (NamedTypeData * string) * TypeData list * ExprData list -> ExprData -val mkUnionFieldGet : (NamedTypeData * string * int) * TypeData list * ExprData -> ExprData -val mkUnionCaseTagTest : (NamedTypeData * string) * TypeData list * ExprData -> ExprData +val mkRecdGet : NamedTypeData * string * TypeData list * ExprData list -> ExprData +val mkRecdSet : NamedTypeData * string * TypeData list * ExprData list -> ExprData +val mkUnion : NamedTypeData * string * TypeData list * ExprData list -> ExprData +val mkUnionFieldGet : NamedTypeData * string * int * TypeData list * ExprData -> ExprData +val mkUnionCaseTagTest : NamedTypeData * string * TypeData list * ExprData -> ExprData val mkTuple : TypeData * ExprData list -> ExprData val mkTupleGet : TypeData * int * ExprData -> ExprData val mkCoerce : TypeData * ExprData -> ExprData @@ -104,10 +103,11 @@ val mkTryWith : ExprData * VarData * ExprData * VarData * ExprData -> ExprData val mkDelegate : TypeData * ExprData -> ExprData val mkPropGet : PropInfoData * TypeData list * ExprData list -> ExprData val mkPropSet : PropInfoData * TypeData list * ExprData list -> ExprData -val mkFieldGet : FieldData * TypeData list * ExprData list -> ExprData -val mkFieldSet : FieldData * TypeData list * ExprData list -> ExprData +val mkFieldGet : NamedTypeData * string * TypeData list * ExprData list -> ExprData +val mkFieldSet : NamedTypeData * string * TypeData list * ExprData list -> ExprData val mkCtorCall : CtorData * TypeData list * ExprData list -> ExprData val mkMethodCall : MethodData * TypeData list * ExprData list -> ExprData +val mkMethodCallW : MethodData * MethodData * int * TypeData list * ExprData list -> ExprData val mkAttributedExpression : ExprData * ExprData -> ExprData val pickle : (ExprData -> byte[]) val isAttributedExpression : ExprData -> bool diff --git a/src/fsharp/QuotationTranslator.fs b/src/fsharp/QuotationTranslator.fs index 19d42466128..daba3b67353 100644 --- a/src/fsharp/QuotationTranslator.fs +++ b/src/fsharp/QuotationTranslator.fs @@ -28,9 +28,13 @@ type IsReflectedDefinition = [] type QuotationSerializationFormat = - /// Indicates that type references are emitted as integer indexes into a supplied table - | FSharp_40_Plus - | FSharp_20_Plus + { + /// Indicates that witness parameters are recorded + SupportsWitnesses: bool + + /// Indicates that type references are emitted as integer indexes into a supplied table + SupportsDeserializeEx: bool + } type QuotationGenerationScope = { g: TcGlobals @@ -67,11 +71,8 @@ type QuotationGenerationScope = cenv.exprSplices |> ResizeArray.toList static member ComputeQuotationFormat g = - let deserializeExValRef = ValRefForIntrinsic g.deserialize_quoted_FSharp_40_plus_info - if ValueOptionInternal.isSome deserializeExValRef.TryDeref then - QuotationSerializationFormat.FSharp_40_Plus - else - QuotationSerializationFormat.FSharp_20_Plus + { SupportsDeserializeEx = (ValRefForIntrinsic g.deserialize_quoted_FSharp_40_plus_info).TryDeref.IsSome + SupportsWitnesses = (ValRefForIntrinsic g.call_with_witnesses_info).TryDeref.IsSome } type QuotationTranslationEnv = { @@ -243,8 +244,7 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP. let (numEnclTypeArgs, _, isNewObj, valUseFlags, isSelfInit, takesInstanceArg, isPropGet, isPropSet) = GetMemberCallInfo cenv.g (vref, vFlags) - // TODO: numEnclTypeArgs/ctps for constraints - let isMember, tps, _cxs, curriedArgInfos, retTy = + let isMember, tps, cxs, curriedArgInfos, retTy = match vref.MemberInfo with | Some _ when not vref.IsExtensionMember -> // This is an application of a member method @@ -305,8 +305,14 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP. if verboseCReflect then dprintfn "vref.DisplayName = %A , after unit adjust, #untupledCurriedArgs = %A, #curriedArgInfos = %d" vref.DisplayName (List.map List.length untupledCurriedArgs) curriedArgInfos.Length - let witnessArgs = ConstraintSolver.CodegenWitnessesForTyparInst cenv.tcVal cenv.g cenv.amap m tps tyargs |> CommitOperationResult - + let witnessArgTys = GenWitnessTys cenv.g cxs + let witnessArgs = + if cenv.g.generateWitnesses then + ConstraintSolver.CodegenWitnessesForTyparInst cenv.tcVal cenv.g cenv.amap m tps tyargs + |> CommitOperationResult + else + [] + let subCall = if isMember then @@ -317,15 +323,15 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP. // The signature types are w.r.t. to the formal context let envinner = BindFormalTypars env tps let argTys = curriedArgInfos |> List.concat |> List.map fst + let witnessArgTypesR = ConvTypes cenv envinner m witnessArgTys let methArgTypesR = ConvTypes cenv envinner m argTys let methRetTypeR = ConvReturnType cenv envinner m retTy let methName = vref.CompiledName let numGenericArgs = tyargs.Length - numEnclTypeArgs - ConvObjectModelCall cenv env m (isPropGet, isPropSet, isNewObj, parentTyconR, methArgTypesR, methRetTypeR, methName, tyargs, numGenericArgs, callArgs) + ConvObjectModelCall cenv env m (isPropGet, isPropSet, isNewObj, parentTyconR, witnessArgTypesR, methArgTypesR, methRetTypeR, methName, tyargs, numGenericArgs, callArgs) else // This is an application of the module value. - // TODO: witnessArgs - ConvModuleValueApp cenv env m vref tyargs untupledCurriedArgs + ConvModuleValueApp cenv env m vref tyargs witnessArgs untupledCurriedArgs match curriedArgs, curriedArgInfos with // static member and module value unit argument elimination @@ -389,7 +395,7 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP. | Expr.Quote(ast, _, _, _, ety) -> // F# 2.0-3.1 had a bug with nested 'raw' quotations. F# 4.0 + FSharp.Core 4.4.0.0+ allows us to do the right thing. - if cenv.quotationFormat = QuotationSerializationFormat.FSharp_40_Plus && + if cenv.quotationFormat.SupportsDeserializeEx && // Look for a 'raw' quotation tyconRefEq cenv.g (tcrefOfAppTy cenv.g ety) cenv.g.raw_expr_tcr then @@ -421,16 +427,15 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP. | Expr.Op(op, tyargs, args, m) -> match op, tyargs, args with | TOp.UnionCase ucref, _, _ -> - let mkR = ConvUnionCaseRef cenv ucref m + let tcR, s = ConvUnionCaseRef cenv ucref m let tyargsR = ConvTypes cenv env m tyargs let argsR = ConvExprs cenv env args - QP.mkUnion(mkR, tyargsR, argsR) - + QP.mkUnion(tcR, s, tyargsR, argsR) | TOp.Tuple tupInfo, tyargs, _ -> let tyR = ConvType cenv env m (mkAnyTupledTy cenv.g tupInfo tyargs) let argsR = ConvExprs cenv env args - QP.mkTuple(tyR, argsR) // TODO: propagate to quotations + QP.mkTuple(tyR, argsR) | TOp.Recd (_, tcref), _, _ -> let rgtypR = ConvTyconRef cenv tcref m @@ -450,7 +455,7 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP. let rgtypR = ConvILTypeRef cenv tref let tyargsR = ConvTypes cenv env m tyargs let argsR = ConvExprs cenv env args - QP.mkRecdGet((rgtypR, anonInfo.SortedNames.[n]), tyargsR, argsR) + QP.mkRecdGet(rgtypR, anonInfo.SortedNames.[n], tyargsR, argsR) | TOp.UnionCaseFieldGet (ucref, n), tyargs, [e] -> ConvUnionFieldGet cenv env m ucref n tyargs e @@ -482,7 +487,7 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP. let tyargsR = ConvTypes cenv env m enclTypeArgs let parentTyconR = ConvILTypeRefUnadjusted cenv m fspec.DeclaringTypeRef let argsR = ConvLValueArgs cenv env args - QP.mkFieldSet( (parentTyconR, fspec.Name), tyargsR, argsR) + QP.mkFieldSet(parentTyconR, fspec.Name, tyargsR, argsR) | TOp.ILAsm([ AI_ceq ], _), _, [arg1;arg2] -> let ty = tyOfExpr cenv.g arg1 @@ -513,15 +518,15 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP. | TOp.ValFieldSet rfref, _tinst, args -> let argsR = ConvLValueArgs cenv env args let tyargsR = ConvTypes cenv env m tyargs - let ((_parentTyconR, fldOrPropName) as projR) = ConvRecdFieldRef cenv rfref m + let parentTyconR, fldOrPropName = ConvRecdFieldRef cenv rfref m if rfref.TyconRef.IsRecordTycon then - QP.mkRecdSet(projR, tyargsR, argsR) + QP.mkRecdSet(parentTyconR, fldOrPropName, tyargsR, argsR) else let fspec = rfref.RecdField let tcref = rfref.TyconRef let parentTyconR = ConvTyconRef cenv tcref m if useGenuineField tcref.Deref fspec then - QP.mkFieldSet( projR, tyargsR, argsR) + QP.mkFieldSet(parentTyconR, fldOrPropName, tyargsR, argsR) else let envinner = BindFormalTypars env (tcref.TyparsNoRange) let propRetTypeR = ConvType cenv envinner m fspec.FormalType @@ -593,7 +598,7 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP. let isPropGet = isProp && methName.StartsWithOrdinal("get_") let isPropSet = isProp && methName.StartsWithOrdinal("set_") let tyargs = (enclTypeArgs@methTypeArgs) - ConvObjectModelCall cenv env m (isPropGet, isPropSet, isNewObj, parentTyconR, methArgTypesR, methRetTypeR, methName, tyargs, methTypeArgs.Length, callArgs) + ConvObjectModelCall cenv env m (isPropGet, isPropSet, isNewObj, parentTyconR, [], methArgTypesR, methRetTypeR, methName, tyargs, methTypeArgs.Length, callArgs) | TOp.TryFinally _, [_resty], [Expr.Lambda(_, _, _, [_], e1, _, _); Expr.Lambda(_, _, _, [_], e2, _, _)] -> QP.mkTryFinally(ConvExpr cenv env e1, ConvExpr cenv env e2) @@ -627,14 +632,13 @@ and ConvLdfld cenv env m (fspec: ILFieldSpec) enclTypeArgs args = let tyargsR = ConvTypes cenv env m enclTypeArgs let parentTyconR = ConvILTypeRefUnadjusted cenv m fspec.DeclaringTypeRef let argsR = ConvLValueArgs cenv env args - QP.mkFieldGet( (parentTyconR, fspec.Name), tyargsR, argsR) + QP.mkFieldGet(parentTyconR, fspec.Name, tyargsR, argsR) and ConvUnionFieldGet cenv env m ucref n tyargs e = let tyargsR = ConvTypes cenv env m tyargs let tcR, s = ConvUnionCaseRef cenv ucref m - let projR = (tcR, s, n) let eR = ConvLValueExpr cenv env e - QP.mkUnionFieldGet(projR, tyargsR, eR) + QP.mkUnionFieldGet(tcR, s, n, tyargsR, eR) and ConvClassOrRecdFieldGet cenv env m rfref tyargs args = EmitDebugInfoIfNecessary cenv env m (ConvClassOrRecdFieldGetCore cenv env m rfref tyargs args) @@ -642,14 +646,14 @@ and ConvClassOrRecdFieldGet cenv env m rfref tyargs args = and private ConvClassOrRecdFieldGetCore cenv env m rfref tyargs args = let tyargsR = ConvTypes cenv env m tyargs let argsR = ConvLValueArgs cenv env args - let ((parentTyconR, fldOrPropName) as projR) = ConvRecdFieldRef cenv rfref m + let (parentTyconR, fldOrPropName) = ConvRecdFieldRef cenv rfref m if rfref.TyconRef.IsRecordTycon then - QP.mkRecdGet(projR, tyargsR, argsR) + QP.mkRecdGet(parentTyconR, fldOrPropName, tyargsR, argsR) else let fspec = rfref.RecdField let tcref = rfref.TyconRef if useGenuineField tcref.Deref fspec then - QP.mkFieldGet(projR, tyargsR, argsR) + QP.mkFieldGet(parentTyconR, fldOrPropName, tyargsR, argsR) else let envinner = BindFormalTypars env tcref.TyparsNoRange let propRetTypeR = ConvType cenv envinner m fspec.FormalType @@ -712,11 +716,12 @@ and ConvLValueExprCore cenv env expr = and ConvObjectModelCall cenv env m callInfo = EmitDebugInfoIfNecessary cenv env m (ConvObjectModelCallCore cenv env m callInfo) -and ConvObjectModelCallCore cenv env m (isPropGet, isPropSet, isNewObj, parentTyconR, methArgTypesR, methRetTypeR, methName, tyargs, numGenericArgs, callArgs) = +and ConvObjectModelCallCore cenv env m (isPropGet, isPropSet, isNewObj, parentTyconR, witnessArgTypesR, methArgTypesR, methRetTypeR, methName, tyargs, numGenericArgs, callArgs) = let tyargsR = ConvTypes cenv env m tyargs let callArgsR = ConvLValueArgs cenv env callArgs if isPropGet || isPropSet then + assert witnessArgTypesR.IsEmpty let propName = ChopPropertyName methName if isPropGet then QP.mkPropGet( (parentTyconR, propName, methRetTypeR, methArgTypesR), tyargsR, callArgsR) @@ -725,12 +730,14 @@ and ConvObjectModelCallCore cenv env m (isPropGet, isPropSet, isNewObj, parentTy QP.mkPropSet( (parentTyconR, propName, propTy, args), tyargsR, callArgsR) elif isNewObj then + assert witnessArgTypesR.IsEmpty let ctorR : QuotationPickler.CtorData = { ctorParent = parentTyconR ctorArgTypes = methArgTypesR } QP.mkCtorCall(ctorR, tyargsR, callArgsR) - else + elif witnessArgTypesR.IsEmpty then + let methR : QuotationPickler.MethodData = { methParent = parentTyconR methArgTypes = methArgTypesR @@ -739,20 +746,39 @@ and ConvObjectModelCallCore cenv env m (isPropGet, isPropSet, isNewObj, parentTy numGenericArgs = numGenericArgs } QP.mkMethodCall(methR, tyargsR, callArgsR) -and ConvModuleValueApp cenv env m (vref:ValRef) tyargs (args: Expr list list) = - EmitDebugInfoIfNecessary cenv env m (ConvModuleValueAppCore cenv env m vref tyargs args) + else + + let methR : QuotationPickler.MethodData = + { methParent = parentTyconR + methArgTypes = methArgTypesR + methRetType = methRetTypeR + methName = methName + numGenericArgs = numGenericArgs } + let methWR : QuotationPickler.MethodData = + { methParent = parentTyconR + methArgTypes = witnessArgTypesR @ methArgTypesR + methRetType = methRetTypeR + methName = methName + numGenericArgs = numGenericArgs } + QP.mkMethodCallW(methR, methWR, List.length witnessArgTypesR, tyargsR, callArgsR) + +and ConvModuleValueApp cenv env m (vref:ValRef) tyargs witnessArgs (args: Expr list list) = + EmitDebugInfoIfNecessary cenv env m (ConvModuleValueAppCore cenv env m vref tyargs witnessArgs args) -and ConvModuleValueAppCore cenv env m (vref:ValRef) tyargs (curriedArgs: Expr list list) = +and ConvModuleValueAppCore cenv env m (vref:ValRef) tyargs witnessArgs (curriedArgs: Expr list list) = match vref.DeclaringEntity with - | ParentNone -> failwith "ConvModuleValueApp" + | ParentNone -> failwith "ConvModuleValueAppCore" | Parent(tcref) -> let isProperty = IsCompiledAsStaticProperty cenv.g vref.Deref let tcrefR = ConvTyconRef cenv tcref m let tyargsR = ConvTypes cenv env m tyargs let nm = vref.CompiledName - let argsR = List.map (ConvExprs cenv env) curriedArgs - // TODO: augment mkModuleValueApp with hidden witness args and hidden entry point - QP.mkModuleValueApp(tcrefR, nm, isProperty, tyargsR, argsR) + let argsR = ConvExprs cenv env (List.concat (witnessArgs::curriedArgs)) + let nWitnesses = witnessArgs.Length + if nWitnesses = 0 then + QP.mkModuleValueApp(tcrefR, nm, isProperty, tyargsR, argsR) + else + QP.mkModuleValueWApp(tcrefR, nm, isProperty, nWitnesses, tyargsR, argsR) and ConvExprs cenv env args = List.map (ConvExpr cenv env) args @@ -780,10 +806,19 @@ and private ConvValRefCore holeOk cenv env m (vref:ValRef) tyargs = // References to local values are embedded by value if not holeOk then wfail(Error(FSComp.SR.crefNoSetOfHole(), m)) let idx = cenv.exprSplices.Count - cenv.exprSplices.Add((mkCallLiftValueWithName cenv.g m vty v.LogicalName (exprForValRef m vref), m)) + let liftExpr = mkCallLiftValueWithName cenv.g m vty v.LogicalName (exprForValRef m vref) + cenv.exprSplices.Add((liftExpr, m)) QP.mkHole(ConvType cenv env m vty, idx) + | Parent _ -> - ConvModuleValueApp cenv env m vref tyargs [] + + let witnessArgs = + if cenv.g.generateWitnesses then + ConstraintSolver.CodegenWitnessesForTyparInst cenv.tcVal cenv.g cenv.amap m vref.Typars tyargs + |> CommitOperationResult + else [] + + ConvModuleValueApp cenv env m vref tyargs witnessArgs [] and ConvUnionCaseRef cenv (ucref:UnionCaseRef) m = let ucgtypR = ConvTyconRef cenv ucref.TyconRef m @@ -889,9 +924,9 @@ and ConvDecisionTree cenv env tgs typR x = match discrim with | DecisionTreeTest.UnionCase (ucref, tyargs) -> let e1R = ConvLValueExpr cenv env e1 - let ucR = ConvUnionCaseRef cenv ucref m + let tcR, s = ConvUnionCaseRef cenv ucref m let tyargsR = ConvTypes cenv env m tyargs - QP.mkCond (QP.mkUnionCaseTagTest (ucR, tyargsR, e1R), ConvDecisionTree cenv env tgs typR dtree, acc) + QP.mkCond (QP.mkUnionCaseTagTest (tcR, s, tyargsR, e1R), ConvDecisionTree cenv env tgs typR dtree, acc) | DecisionTreeTest.Const (Const.Bool true) -> let e1R = ConvExpr cenv env e1 @@ -980,8 +1015,7 @@ and ConvILTypeRefUnadjusted cenv m (tr:ILTypeRef) = ConvILTypeRef cenv trefAdjusted and ConvILTypeRef cenv (tr:ILTypeRef) = - match cenv.quotationFormat with - | QuotationSerializationFormat.FSharp_40_Plus -> + if cenv.quotationFormat.SupportsDeserializeEx then let idx = match cenv.referencedTypeDefsTable.TryGetValue tr with | true, idx -> idx @@ -992,7 +1026,7 @@ and ConvILTypeRef cenv (tr:ILTypeRef) = idx QP.Idx idx - | QuotationSerializationFormat.FSharp_20_Plus -> + else let assemblyRef = match tr.Scope with | ILScopeRef.Local -> "." @@ -1068,8 +1102,7 @@ let ConvMethodBase cenv env (methName, v:Val) = | Some vspr when not v.IsExtensionMember -> let vref = mkLocalValRef v - // TODO: representation of witnesses - let tps, _cxs, argInfos, retTy, _ = GetTypeOfMemberInMemberForm cenv.g vref + let tps, cxs, argInfos, retTy, _ = GetTypeOfMemberInMemberForm cenv.g vref let numEnclTypeArgs = vref.MemberApparentEntity.TyparsNoRange.Length let argTys = argInfos |> List.concat |> List.map fst @@ -1077,46 +1110,51 @@ let ConvMethodBase cenv env (methName, v:Val) = // The signature types are w.r.t. to the formal context let envinner = BindFormalTypars env tps + let witnessArgTysR = ConvTypes cenv envinner m (GenWitnessTys cenv.g cxs) let methArgTypesR = ConvTypes cenv envinner m argTys let methRetTypeR = ConvReturnType cenv envinner m retTy let numGenericArgs = tps.Length-numEnclTypeArgs if isNewObj then - QP.MethodBaseData.Ctor - { ctorParent = parentTyconR - ctorArgTypes = methArgTypesR } + assert witnessArgTysR.IsEmpty + QP.MethodBaseData.Ctor + { ctorParent = parentTyconR + ctorArgTypes = methArgTypesR } else - QP.MethodBaseData.Method + QP.MethodBaseData.Method { methParent = parentTyconR - methArgTypes = methArgTypesR + methArgTypes = witnessArgTysR @ methArgTypesR methRetType = methRetTypeR methName = methName numGenericArgs=numGenericArgs } | _ when v.IsExtensionMember -> - // TODO: witnesses? - let tps, _cxs, argInfos, retTy, _ = GetTopValTypeInCompiledForm cenv.g v.ValReprInfo.Value v.Type v.Range + let tps, cxs, argInfos, retTy, _ = GetTopValTypeInCompiledForm cenv.g v.ValReprInfo.Value v.Type v.Range let argTys = argInfos |> List.concat |> List.map fst let envinner = BindFormalTypars env tps + let witnessArgTysR = ConvTypes cenv envinner m (GenWitnessTys cenv.g cxs) let methArgTypesR = ConvTypes cenv envinner m argTys let methRetTypeR = ConvReturnType cenv envinner m retTy let numGenericArgs = tps.Length QP.MethodBaseData.Method { methParent = parentTyconR - methArgTypes = methArgTypesR + methArgTypes = witnessArgTysR @ methArgTypesR methRetType = methRetTypeR methName = methName numGenericArgs=numGenericArgs } - | _ -> + | _ -> + let tps, cxs, _argInfos, _retTy, _ = GetTopValTypeInCompiledForm cenv.g v.ValReprInfo.Value v.Type v.Range + let envinner = BindFormalTypars env tps + let witnessArgTysR = ConvTypes cenv envinner m (GenWitnessTys cenv.g cxs) + let nWitnesses = witnessArgTysR.Length QP.MethodBaseData.ModuleDefn - { Name = methName - Module = parentTyconR - IsProperty = IsCompiledAsStaticProperty cenv.g v } - + ({ Name = methName + Module = parentTyconR + IsProperty = IsCompiledAsStaticProperty cenv.g v }, nWitnesses) // FSComp.SR.crefQuotationsCantContainLiteralByteArrays diff --git a/src/fsharp/QuotationTranslator.fsi b/src/fsharp/QuotationTranslator.fsi index 930a56879ad..da4db77b083 100755 --- a/src/fsharp/QuotationTranslator.fsi +++ b/src/fsharp/QuotationTranslator.fsi @@ -26,9 +26,13 @@ type IsReflectedDefinition = [] type QuotationSerializationFormat = - /// Indicates that type references are emitted as integer indexes into a supplied table - | FSharp_40_Plus - | FSharp_20_Plus + { + /// Indicates that witness parameters are recorded + SupportsWitnesses: bool + + /// Indicates that type references are emitted as integer indexes into a supplied table + SupportsDeserializeEx: bool + } [] type QuotationGenerationScope = diff --git a/src/fsharp/TastOps.fs b/src/fsharp/TastOps.fs index 729eec7cce2..e1fe6593b3f 100644 --- a/src/fsharp/TastOps.fs +++ b/src/fsharp/TastOps.fs @@ -4770,8 +4770,12 @@ type StaticOptimizationAnswer = | No = -1y | Unknown = 0y -let decideStaticOptimizationConstraint g c = +let decideStaticOptimizationConstraint g c haveWitnesses = match c with + // When witnesses are available in generic code during codegen, "when ^T : ^T" resolves StaticOptimizationAnswer.Yes + // This doesn't apply to "when 'T : 'T" use for "FastGenericEqualityComparer" and others. + | TTyconEqualsTycon (a, b) when haveWitnesses && typeEquiv g a b && (match tryDestTyparTy g a with ValueSome tp -> tp.StaticReq = TyparStaticReq.HeadTypeStaticReq | _ -> false) -> + StaticOptimizationAnswer.Yes | TTyconEqualsTycon (a, b) -> // Both types must be nominal for a definite result let rec checkTypes a b = @@ -4807,17 +4811,17 @@ let decideStaticOptimizationConstraint g c = | ValueSome tcref1 -> if tcref1.IsStructOrEnumTycon then StaticOptimizationAnswer.Yes else StaticOptimizationAnswer.No | ValueNone -> StaticOptimizationAnswer.Unknown -let rec DecideStaticOptimizations g cs = +let rec DecideStaticOptimizations g cs haveWitnesses = match cs with | [] -> StaticOptimizationAnswer.Yes | h::t -> - let d = decideStaticOptimizationConstraint g h + let d = decideStaticOptimizationConstraint g h haveWitnesses if d = StaticOptimizationAnswer.No then StaticOptimizationAnswer.No - elif d = StaticOptimizationAnswer.Yes then DecideStaticOptimizations g t + elif d = StaticOptimizationAnswer.Yes then DecideStaticOptimizations g t haveWitnesses else StaticOptimizationAnswer.Unknown let mkStaticOptimizationExpr g (cs, e1, e2, m) = - let d = DecideStaticOptimizations g cs in + let d = DecideStaticOptimizations g cs false if d = StaticOptimizationAnswer.No then e2 elif d = StaticOptimizationAnswer.Yes then e1 else Expr.StaticOptimization(cs, e1, e2, m) @@ -7644,21 +7648,26 @@ let LinearizeTopMatch g parent = function // Witnesses //--------------------------------------------------------------------------- -let GenWitnessArgTys (traitInfo: TraitWitnessInfo) = +let GenWitnessArgTys (g: TcGlobals) (traitInfo: TraitWitnessInfo) = let (TraitWitnessInfo(tys, _nm, memFlags, argtys, _rty)) = traitInfo + let argtys = if argtys.IsEmpty then [g.unit_ty] else argtys let argtysl = List.map List.singleton argtys match tys with | _ when not memFlags.IsInstance -> argtysl - | [ty] when memFlags.IsInstance -> [ty] :: argtysl - | _ -> failwith "can't generate choosy instance members yet" + | [ty] -> [ty] :: argtysl + | [_; _] -> [g.obj_ty] :: argtysl + | _ -> failwith "unexpected empty type support for trait constraint" let GenWitnessTy (g: TcGlobals) (traitInfo: TraitWitnessInfo) = let rty = match traitInfo.ReturnType with None -> g.unit_ty | Some ty -> ty - let argtysl = GenWitnessArgTys traitInfo + let argtysl = GenWitnessArgTys g traitInfo mkMethodTy g argtysl rty let GenWitnessTys (g: TcGlobals) (cxs: TraitWitnessInfos) = - cxs |> List.map (GenWitnessTy g) + if g.generateWitnesses then + cxs |> List.map (GenWitnessTy g) + else + [] //--------------------------------------------------------------------------- // XmlDoc signatures @@ -7763,7 +7772,6 @@ let XmlDocSigOfVal g path (v:Val) = // separately when really it would be cleaner to make sure GetTopValTypeInFSharpForm, GetMemberTypeInFSharpForm etc. // were lined up so code paths like this could be uniform - // TODO: representation of constraint witnesses match v.MemberInfo with | Some membInfo when not v.IsExtensionMember -> // Methods, Properties etc. diff --git a/src/fsharp/TastOps.fsi b/src/fsharp/TastOps.fsi index 9b3ae08a8eb..4c7f16b651d 100755 --- a/src/fsharp/TastOps.fsi +++ b/src/fsharp/TastOps.fsi @@ -2153,7 +2153,7 @@ type StaticOptimizationAnswer = | No = -1y | Unknown = 0y -val DecideStaticOptimizations : TcGlobals -> StaticOptimization list -> StaticOptimizationAnswer +val DecideStaticOptimizations : TcGlobals -> StaticOptimization list -> haveWitnesses: bool -> StaticOptimizationAnswer val mkStaticOptimizationExpr : TcGlobals -> StaticOptimization list * Expr * Expr * range -> Expr @@ -2283,7 +2283,7 @@ val isThreadOrContextStatic: TcGlobals -> Attrib list -> bool val mkUnitDelayLambda: TcGlobals -> range -> Expr -> Expr -val GenWitnessArgTys: TraitWitnessInfo -> TType list list +val GenWitnessArgTys: TcGlobals -> TraitWitnessInfo -> TType list list val GenWitnessTys: TcGlobals -> TraitWitnessInfos -> TType list diff --git a/src/fsharp/TcGlobals.fs b/src/fsharp/TcGlobals.fs index 86cea705baf..fd56558a41b 100755 --- a/src/fsharp/TcGlobals.fs +++ b/src/fsharp/TcGlobals.fs @@ -708,6 +708,7 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d let v_new_decimal_info = makeIntrinsicValRef(fslib_MFIntrinsicFunctions_nleref, "MakeDecimal" , None , None , [], ([[v_int_ty]; [v_int_ty]; [v_int_ty]; [v_bool_ty]; [v_byte_ty]], v_decimal_ty)) let v_deserialize_quoted_FSharp_20_plus_info = makeIntrinsicValRef(fslib_MFQuotations_nleref, "Deserialize" , Some "Expr" , None , [], ([[v_system_Type_ty ;mkListTy v_system_Type_ty ;mkListTy mkRawQuotedExprTy ; mkArrayType 1 v_byte_ty]], mkRawQuotedExprTy )) let v_deserialize_quoted_FSharp_40_plus_info = makeIntrinsicValRef(fslib_MFQuotations_nleref, "Deserialize40" , Some "Expr" , None , [], ([[v_system_Type_ty ;mkArrayType 1 v_system_Type_ty; mkArrayType 1 v_system_Type_ty; mkArrayType 1 mkRawQuotedExprTy; mkArrayType 1 v_byte_ty]], mkRawQuotedExprTy )) + let v_call_with_witnesses_info = makeIntrinsicValRef(fslib_MFQuotations_nleref, "CallWithWitnesses" , Some "Expr" , None , [], ([[v_system_Reflection_MethodInfo_ty; v_system_Reflection_MethodInfo_ty; mkListTy mkRawQuotedExprTy; mkListTy mkRawQuotedExprTy]], mkRawQuotedExprTy)) let v_cast_quotation_info = makeIntrinsicValRef(fslib_MFQuotations_nleref, "Cast" , Some "Expr" , None , [vara], ([[mkRawQuotedExprTy]], mkQuotedExprTy varaTy)) let v_lift_value_info = makeIntrinsicValRef(fslib_MFQuotations_nleref, "Value" , Some "Expr" , None , [vara], ([[varaTy]], mkRawQuotedExprTy)) let v_lift_value_with_name_info = makeIntrinsicValRef(fslib_MFQuotations_nleref, "ValueWithName" , Some "Expr" , None , [vara], ([[varaTy; v_string_ty]], mkRawQuotedExprTy)) @@ -1407,6 +1408,7 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d member __.deserialize_quoted_FSharp_20_plus_info = v_deserialize_quoted_FSharp_20_plus_info member __.deserialize_quoted_FSharp_40_plus_info = v_deserialize_quoted_FSharp_40_plus_info + member __.call_with_witnesses_info = v_call_with_witnesses_info member __.cast_quotation_info = v_cast_quotation_info member __.lift_value_info = v_lift_value_info member __.lift_value_with_name_info = v_lift_value_with_name_info @@ -1442,9 +1444,14 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d // Note that the suppression checks for the precise name of the type // so the lowercase versions are visible member __.suppressed_types = v_suppressed_types + /// Are we assuming all code gen is for F# interactive, with no static linking member __.isInteractive=isInteractive + /// Indicates if we are generating witness arguments for SRTP constraints. Only done if the FSharp.Core + /// supports witness arguments. + member g.generateWitnesses = compilingFslib || (ValRefForIntrinsic g.call_with_witnesses_info).TryDeref.IsSome + member __.FindSysTyconRef path nm = findSysTyconRef path nm member __.TryFindSysTyconRef path nm = tryFindSysTyconRef path nm member __.FindSysILTypeRef nm = findSysILTypeRef nm diff --git a/src/fsharp/fsc.fs b/src/fsharp/fsc.fs index 5fb034373fc..a991e818be2 100644 --- a/src/fsharp/fsc.fs +++ b/src/fsharp/fsc.fs @@ -886,10 +886,10 @@ module MainModuleBuilder = |> List.map (fun (referencedTypeDefs, reflectedDefinitionBytes) -> let reflectedDefinitionResourceName = QuotationPickler.SerializedReflectedDefinitionsResourceNameBase+"-"+assemblyName+"-"+string(newUnique())+"-"+string(hash reflectedDefinitionBytes) let reflectedDefinitionAttrs = - match QuotationTranslator.QuotationGenerationScope.ComputeQuotationFormat tcGlobals with - | QuotationTranslator.QuotationSerializationFormat.FSharp_40_Plus -> + let qf = QuotationTranslator.QuotationGenerationScope.ComputeQuotationFormat tcGlobals + if qf.SupportsDeserializeEx then [ mkCompilationMappingAttrForQuotationResource tcGlobals (reflectedDefinitionResourceName, referencedTypeDefs) ] - | QuotationTranslator.QuotationSerializationFormat.FSharp_20_Plus -> + else [ ] let reflectedDefinitionResource = { Name=reflectedDefinitionResourceName diff --git a/tests/fsharp/core/quotes/test.fsx b/tests/fsharp/core/quotes/test.fsx index 289988569de..37d66b392ec 100644 --- a/tests/fsharp/core/quotes/test.fsx +++ b/tests/fsharp/core/quotes/test.fsx @@ -460,8 +460,7 @@ module TypedTest = begin test "check AddressOf rebuild" (try rebuild <@ let mutable a = 10 in increment(&a) @> |> ignore; true with _ -> false) test "check AddressOf argument" (<@ let mutable a = 10 in increment(&a) @> |> function Let(_, _, Call(None, _, [AddressOf(_)])) -> true | _ -> false) test "check AddressOf type" (<@ let mutable a = 10 in increment(&a) @> |> function Let(_, _, Call(None, _, [AddressOf(_) as e])) -> (try e.Type = typeof.MakeByRefType() with _ -> false) | _ -> false) - - + // Test basic expression splicing let f8383 (x:int) (y:string) = 0 let test2 = @@ -553,6 +552,7 @@ module TypedTest = begin end #endif + end (* @@ -3177,6 +3177,120 @@ module TestMatchBang = testSimpleMatchBang() +module WitnessTests = + test "check CallWithWitness" + (<@ 1 + 1 @> + |> function + | CallWithWitnesses(None, minfo1, minfo2, witnessArgs, args) -> + minfo1.Name = "op_Addition" && + minfo1.GetParameters().Length = 2 && + minfo2.Name = "op_Addition" && + minfo2.GetParameters().Length = 3 && + (printfn "checking witnessArgs.Length = %d... args.Length"; true) && + witnessArgs.Length = 1 && + (printfn "checking args.Length = %d... args.Length"; true) && + args.Length = 2 && + (printfn "checking witnessArgs is a Lambda..."; true) && + (match args with [ Lambda _ ] -> true | _ -> false) + (printfn "checking args..."; true) && + (match args with [ Int32 _; Int32 _ ] -> true | _ -> false) + | _ -> false) + + test "check CallWithWitness (DateTime + TimeSpan)" + (<@ System.DateTime.Now + System.TimeSpan.Zero @> + |> function + | CallWithWitnesses(None, minfo1, minfo2, witnessArgs, args) -> + minfo1.Name = "op_Addition" && + (printfn "checking minfo1.GetParameters().Length..."; true) && + minfo1.GetParameters().Length = 2 && + minfo2.Name = "op_Addition" && + (printfn "checking minfo2.GetParameters().Length..."; true) && + minfo2.GetParameters().Length = 3 && + (printfn "checking args.Length..."; true) && + witnessArgs.Length = 1 && + args.Length = 2 && + (printfn "checking args..."; true) && + (match args with [ _; _ ] -> true | _ -> false) && + (match witnessArgs with [ Lambda _ ] -> true | _ -> false) + | CallWithWitnesses _ -> + printfn "no object" + false + | _ -> + printfn "incorrect node" + false) + + test "check CallWithWitness (DateTime + TimeSpan)" + (<@ System.DateTime.Now + System.TimeSpan.Zero @> + |> function + | CallWithWitnesses(None, minfo1, minfo2, witnessArgs, args) -> + minfo1.Name = "op_Addition" && + (printfn "checking minfo1.GetParameters().Length..."; true) && + minfo1.GetParameters().Length = 2 && + minfo2.Name = "op_Addition" && + (printfn "checking minfo2.GetParameters().Length..."; true) && + minfo2.GetParameters().Length = 3 && + (printfn "checking minfo2.GetParameters().[0].Name = %s..." (minfo2.GetParameters().[0].Name); true) && + //minfo2.GetParameters().[0].Name = "op_Addition" && + witnessArgs.Length = 1 && + args.Length = 2 && + (match witnessArgs with [ Lambda _ ] -> true | _ -> false) && + (match args with [ _; _ ] -> true | _ -> false) + | _ -> false) + + type C() = + static member inline StaticAdd (x, y) = x + y + member inline __.InstanceAdd (x, y) = x + y + + test "check CallWithWitness (DateTime + TimeSpan) using static member" + (<@ C.StaticAdd(System.DateTime.Now, System.TimeSpan.Zero) @> + |> function + | CallWithWitnesses(None, minfo1, minfo2, witnessArgs, args) -> + minfo1.IsStatic && + minfo1.Name = "StaticAdd" && + (printfn "checking minfo1.GetParameters().Length..."; true) && + minfo1.GetParameters().Length = 2 && + minfo2.IsStatic && + minfo2.Name = "StaticAdd" && + (printfn "checking minfo2.GetParameters().Length = %d..." (minfo2.GetParameters().Length); true) && + minfo2.GetParameters().Length = 3 && + (printfn "checking witnessArgs.Length..."; true) && + witnessArgs.Length = 1 && + (printfn "checking args.Length..."; true) && + args.Length = 2 && + (printfn "witnessArgs..."; true) && + (match witnessArgs with [ Lambda _ ] -> true | _ -> false) && + (printfn "args..."; true) && + (match args with [ _; _ ] -> true | _ -> false) + | CallWithWitnesses(None, minfo1, minfo2, witnessArgs, args) -> + printfn "no object..." + false + | _ -> false) + + test "check CallWithWitness (DateTime + TimeSpan) using instance member" + (<@ C().InstanceAdd(System.DateTime.Now, System.TimeSpan.Zero) @> + |> function + | CallWithWitnesses(Some _obj, minfo1, minfo2, witnessArgs, args) -> + not minfo1.IsStatic && + minfo1.Name = "InstanceAdd" && + (printfn "checking minfo1.GetParameters().Length..."; true) && + minfo1.GetParameters().Length = 2 && + not minfo2.IsStatic && + minfo2.Name = "InstanceAdd" && + (printfn "checking minfo2.GetParameters().Length = %d..." (minfo2.GetParameters().Length); true) && + minfo2.GetParameters().Length = 3 && + (printfn "checking witnessArgs.Length..."; true) && + witnessArgs.Length = 1 && + (printfn "checking args.Length..."; true) && + args.Length = 2 && + (printfn "witnessArgs..."; true) && + (match witnessArgs with [ Lambda _ ] -> true | _ -> false) && + (printfn "args..."; true) && + (match args with [ _; _ ] -> true | _ -> false) + | CallWithWitnesses(None, minfo1, minfo2, witnessArgs, args) -> + printfn "no object..." + false + | _ -> false) + #if !FX_RESHAPED_REFLECTION module TestAssemblyAttributes = From ba0a56b49abd86d3e33354679bd6ed66de8de57c Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 22 Mar 2019 12:18:49 +0000 Subject: [PATCH 03/77] skip Proto binaries in version check --- scripts/AssemblyVersionCheck.fsx | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/AssemblyVersionCheck.fsx b/scripts/AssemblyVersionCheck.fsx index 0f3816a2e6c..4c547d19cae 100644 --- a/scripts/AssemblyVersionCheck.fsx +++ b/scripts/AssemblyVersionCheck.fsx @@ -26,6 +26,7 @@ module AssemblyVersionCheck = |> List.map (fun p -> Directory.EnumerateFiles(binariesPath, p, SearchOption.AllDirectories)) |> Seq.concat |> List.ofSeq + |> List.filter (fun p -> not (p.Contains("Proto"))) |> List.filter (fun p -> (Set.contains (Path.GetFileName(p)) excludedAssemblies) |> not) // verify that all assemblies have a version number other than 0.0.0.0 or 1.0.0.0 From 1f562f22f7077c5f7dbf45444f0de6f8ebd6dfce Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 22 Mar 2019 17:45:13 +0000 Subject: [PATCH 04/77] Add WithWitnesses suffix and fix build --- src/fsharp/FSharp.Core/quotations.fs | 41 +++++---- src/fsharp/IlxGen.fs | 127 +++++++++++++++++---------- src/fsharp/PrettyNaming.fs | 4 +- src/fsharp/QuotationPickler.fs | 37 ++++---- src/fsharp/QuotationPickler.fsi | 4 +- src/fsharp/QuotationTranslator.fs | 13 ++- tests/fsharp/core/quotes/test.fsx | 18 ++-- 7 files changed, 146 insertions(+), 98 deletions(-) diff --git a/src/fsharp/FSharp.Core/quotations.fs b/src/fsharp/FSharp.Core/quotations.fs index 31d5256f7a5..ab037b22984 100644 --- a/src/fsharp/FSharp.Core/quotations.fs +++ b/src/fsharp/FSharp.Core/quotations.fs @@ -1489,7 +1489,7 @@ module Patterns = let case,i = u_tup2 u_UnionCaseInfo u_int st (fun tyargs -> getUnionCaseInfoField(case tyargs,i)) - and u_ModuleDefn nWitnesses st = + and u_ModuleDefn witnessInfo st = let (ty,nm,isProp) = u_tup3 u_NamedType u_string u_bool st if isProp then Unique(StaticPropGetOp(bindModuleProperty(ty,nm))) else @@ -1497,21 +1497,30 @@ module Patterns = match meths with | [||] -> raise <| System.InvalidOperationException (String.Format(SR.GetString(SR.QcannotBindFunction), nm, ty.ToString())) - | [| res |] -> - Unique(StaticMethodCallOp(res)) - | [| res1; res2 |] when nWitnesses > 0 -> - if res1.GetParameters().Length < res2.GetParameters().Length then - Unique(StaticMethodCallWOp(res1, res2, nWitnesses)) - else - Unique(StaticMethodCallWOp(res2, res1, nWitnesses)) + | [| minfo |] -> + match witnessInfo with + | None -> + Unique(StaticMethodCallOp(minfo)) + | Some (nmW, nWitnesses) -> + let methsW = ty.GetMethods(staticBindingFlags) |> Array.filter (fun mi -> mi.Name = nmW) + match methsW with + | [||] -> + raise <| System.InvalidOperationException (String.Format(SR.GetString(SR.QcannotBindFunction), nmW, ty.ToString())) + | [| minfoW |] -> + Unique(StaticMethodCallWOp(minfo, minfoW, nWitnesses)) + | _ -> + Ambiguous(fun argTypes tyargs -> + let minfoW = bindModuleFunctionWithCallSiteArgs(ty, nm, argTypes, tyargs) + StaticMethodCallWOp(minfo, minfoW, nWitnesses)) | _ -> Ambiguous(fun argTypes tyargs -> - if nWitnesses = 0 then + match witnessInfo with + | None -> let minfo = bindModuleFunctionWithCallSiteArgs(ty, nm, argTypes, tyargs) StaticMethodCallOp minfo - else + | Some (nmW, nWitnesses) -> let minfo = bindModuleFunctionWithCallSiteArgs(ty, nm, List.skip nWitnesses argTypes, tyargs) - let minfoW = bindModuleFunctionWithCallSiteArgs(ty, nm, argTypes, tyargs) + let minfoW = bindModuleFunctionWithCallSiteArgs(ty, nmW, argTypes, tyargs) StaticMethodCallWOp(minfo, minfoW, nWitnesses)) and u_MethodInfoData st = @@ -1527,7 +1536,7 @@ module Patterns = let tag = u_byte_as_int st match tag with | 0 -> - match u_ModuleDefn 0 st with + match u_ModuleDefn None st with | Unique(StaticMethodCallOp(minfo)) -> (minfo :> MethodBase) | Unique(StaticPropGetOp(pinfo)) -> (pinfo.GetGetMethod(true) :> MethodBase) | Ambiguous(_) -> raise (System.Reflection.AmbiguousMatchException()) @@ -1545,8 +1554,9 @@ module Patterns = let cinfo = bindGenericCtor(data) (cinfo :> MethodBase) | 3 -> + let methNameW = u_string st let nWitnesses = u_int st - match u_ModuleDefn nWitnesses st with + match u_ModuleDefn (Some (methNameW, nWitnesses)) st with | Unique(StaticMethodCallOp(minfo)) -> (minfo :> MethodBase) | Unique(StaticMethodCallWOp(_minfo, minfoW, _)) -> (minfoW :> MethodBase) | Unique(StaticPropGetOp(pinfo)) -> (pinfo.GetGetMethod(true) :> MethodBase) @@ -1565,12 +1575,13 @@ module Patterns = and u_opSpec st = let tag = u_byte_as_int st if tag = 1 then - match u_ModuleDefn 0 st with + match u_ModuleDefn None st with | Unique(r) -> Unique(instModuleDefnOp r) | Ambiguous(f) -> Ambiguous(fun argTypes tyargs -> instModuleDefnOp (f argTypes tyargs) tyargs) elif tag = 51 then + let nmW = u_string st let nWitnesses = u_int st - match u_ModuleDefn nWitnesses st with + match u_ModuleDefn (Some (nmW, nWitnesses)) st with | Unique(r) -> Unique(instModuleDefnOp r) | Ambiguous(f) -> Ambiguous(fun argTypes tyargs -> instModuleDefnOp (f argTypes tyargs) tyargs) else diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 1b55c5ea7c8..9f20a1d13fc 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -965,7 +965,7 @@ let GetMethodSpecForMemberVal amap g (memberInfo: ValMemberInfo) (vref: ValRef) mspec else let ilWitnessArgTys = GenTypes amap m tyenvUnderTypars (GenWitnessTys g cxs) - mkILInstanceMethSpecInTy (ilTy, vref.CompiledName, ilWitnessArgTys @ ilMethodArgTys, ilActualRetTy, ilMethodInst) + mkILInstanceMethSpecInTy (ilTy, ExtraWitnessMethodName vref.CompiledName, ilWitnessArgTys @ ilMethodArgTys, ilActualRetTy, ilMethodInst) mspec, mspecW, ctps, mtps, curriedArgInfos, paramInfos, retInfo, cxs, methodArgTys else @@ -978,7 +978,7 @@ let GetMethodSpecForMemberVal amap g (memberInfo: ValMemberInfo) (vref: ValRef) mspec else let ilWitnessArgTys = GenTypes amap m tyenvUnderTypars (GenWitnessTys g cxs) - mkILStaticMethSpecInTy (ilTy, vref.CompiledName, ilWitnessArgTys @ ilMethodArgTys, ilActualRetTy, ilMethodInst) + mkILStaticMethSpecInTy (ilTy, ExtraWitnessMethodName vref.CompiledName, ilWitnessArgTys @ ilMethodArgTys, ilActualRetTy, ilMethodInst) mspec, mspecW, ctps, mtps, curriedArgInfos, paramInfos, retInfo, cxs, methodArgTys @@ -1038,7 +1038,7 @@ let ComputeStorageForFSharpFunctionOrFSharpExtensionMember amap g cloc topValInf mspec else let ilWitnessArgTys = GenTypes amap m tyenvUnderTypars (GenWitnessTys g cxs) - mkILStaticMethSpecInTy (ilLocTy, nm, (ilWitnessArgTys @ ilMethodArgTys), ilRetTy, ilMethodInst) + mkILStaticMethSpecInTy (ilLocTy, ExtraWitnessMethodName nm, (ilWitnessArgTys @ ilMethodArgTys), ilRetTy, ilMethodInst) Method (topValInfo, vref, mspec, mspecW, m, [], tps, curriedArgInfos, paramInfos, cxs, argTys, retInfo) /// Determine if an F#-declared value, method or function is compiled as a method. @@ -5634,41 +5634,52 @@ and GenEventForProperty cenv eenvForMeth (mspec: ILMethodSpec) (v: Val) ilAttrsT otherMethods= [], customAttrs = mkILCustomAttrs ilAttrsThatGoOnPrimaryItem) -and ComputeFlagFixupsForMemberBinding cenv (v: Val, memberInfo: ValMemberInfo) = - if isNil memberInfo.ImplementedSlotSigs then - [fixupVirtualSlotFlags] - else - memberInfo.ImplementedSlotSigs |> List.map (fun slotsig -> - let oty = slotsig.ImplementedType - let otcref = tcrefOfAppTy cenv.g oty - let tcref = v.MemberApparentEntity - - let useMethodImpl = - // REVIEW: it would be good to get rid of this special casing of Compare and GetHashCode during code generation - isInterfaceTy cenv.g oty && - (let isCompare = - Option.isSome tcref.GeneratedCompareToValues && - (typeEquiv cenv.g oty cenv.g.mk_IComparable_ty || - tyconRefEq cenv.g cenv.g.system_GenericIComparable_tcref otcref) - - not isCompare) && - - (let isGenericEquals = - Option.isSome tcref.GeneratedHashAndEqualsWithComparerValues && tyconRefEq cenv.g cenv.g.system_GenericIEquatable_tcref otcref - - not isGenericEquals) && - (let isStructural = - (Option.isSome tcref.GeneratedCompareToWithComparerValues && typeEquiv cenv.g oty cenv.g.mk_IStructuralComparable_ty) || - (Option.isSome tcref.GeneratedHashAndEqualsWithComparerValues && typeEquiv cenv.g oty cenv.g.mk_IStructuralEquatable_ty) +and ComputeUseMethodImpl cenv (v: Val, slotsig: SlotSig) = + let oty = slotsig.ImplementedType + let otcref = tcrefOfAppTy cenv.g oty + let tcref = v.MemberApparentEntity + // REVIEW: it would be good to get rid of this special casing of Compare and GetHashCode during code generation + isInterfaceTy cenv.g oty && + (let isCompare = + Option.isSome tcref.GeneratedCompareToValues && + (typeEquiv cenv.g oty cenv.g.mk_IComparable_ty || + tyconRefEq cenv.g cenv.g.system_GenericIComparable_tcref otcref) + + not isCompare) && - not isStructural) + (let isGenericEquals = + Option.isSome tcref.GeneratedHashAndEqualsWithComparerValues && tyconRefEq cenv.g cenv.g.system_GenericIEquatable_tcref otcref + + not isGenericEquals) && + (let isStructural = + (Option.isSome tcref.GeneratedCompareToWithComparerValues && typeEquiv cenv.g oty cenv.g.mk_IStructuralComparable_ty) || + (Option.isSome tcref.GeneratedHashAndEqualsWithComparerValues && typeEquiv cenv.g oty cenv.g.mk_IStructuralEquatable_ty) - let nameOfOverridingMethod = GenNameOfOverridingMethod cenv (useMethodImpl, slotsig) + not isStructural) +and ComputeMethodImplNameFixupForMemberBinding cenv (v: Val, memberInfo: ValMemberInfo) = + if isNil memberInfo.ImplementedSlotSigs then + None + else + let slotsig = memberInfo.ImplementedSlotSigs |> List.last + let useMethodImpl = ComputeUseMethodImpl cenv (v, slotsig) + let nameOfOverridingMethod = GenNameOfOverridingMethod cenv (useMethodImpl, slotsig) + Some nameOfOverridingMethod + +and ComputeFlagFixupsForMemberBinding cenv (v: Val, memberInfo: ValMemberInfo) = + [ if isNil memberInfo.ImplementedSlotSigs then + yield fixupVirtualSlotFlags + else + for slotsig in memberInfo.ImplementedSlotSigs do + let useMethodImpl = ComputeUseMethodImpl cenv (v, slotsig) + if useMethodImpl then - fixupMethodImplFlags >> renameMethodDef nameOfOverridingMethod + yield fixupMethodImplFlags else - fixupVirtualSlotFlags >> renameMethodDef nameOfOverridingMethod) + yield fixupVirtualSlotFlags + match ComputeMethodImplNameFixupForMemberBinding cenv (v, memberInfo) with + | Some nm -> yield renameMethodDef nm + | None -> () ] and ComputeMethodImplAttribs cenv (_v: Val) attrs = let implflags = @@ -5763,7 +5774,7 @@ and GenMethodForBinding match TryFindFSharpAttributeOpt cenv.g cenv.g.attrib_DllImportAttribute v.Attribs with | Some (Attrib(_, _, [ AttribStringArg(dll) ], namedArgs, _, _, m)) -> if not (isNil methLambdaTypars) then error(Error(FSComp.SR.ilSignatureForExternalFunctionContainsTypeParameters(), m)) - let hasPreserveSigNamedArg, mbody = GenPInvokeMethod (v.CompiledName, dll, namedArgs) + let hasPreserveSigNamedArg, mbody = GenPInvokeMethod (mspec.Name, dll, namedArgs) hasPreserveSigNamedArg, mbody, true | Some (Attrib(_, _, _, _, _, _, m)) -> @@ -5777,7 +5788,7 @@ and GenMethodForBinding let attr = TryFindFSharpBoolAttributeAssumeFalse cenv.g cenv.g.attrib_NoDynamicInvocationAttribute v.Attribs if (not hasWitnessArgs && attr.IsSome) || (hasWitnessArgs && attr = Some false) then - let exnArg = mkString cenv.g m (FSComp.SR.ilDynamicInvocationNotSupported(v.CompiledName)) + let exnArg = mkString cenv.g m (FSComp.SR.ilDynamicInvocationNotSupported(mspec.Name)) let exnExpr = MakeNotSupportedExnExpr cenv eenv (exnArg, m) mkThrow m returnTy exnExpr else @@ -5826,17 +5837,41 @@ and GenMethodForBinding match v.MemberInfo with // don't generate unimplemented abstracts - | Some(memberInfo) when memberInfo.MemberFlags.IsDispatchSlot && not memberInfo.IsImplemented -> + | Some memberInfo when memberInfo.MemberFlags.IsDispatchSlot && not memberInfo.IsImplemented -> // skipping unimplemented abstract method () - | Some(memberInfo) when (match memberInfo.MemberFlags.MemberKind with (MemberKind.PropertySet | MemberKind.PropertyGet) -> CompileAsEvent cenv.g v.Attribs | _ -> false) -> - // skip method generation for compiling the property as a .NET event - // Emit the pseudo-property as an event (but not if its a private method impl) - if access <> ILMemberAccess.Private then - let edef = GenEventForProperty cenv eenvForMeth mspec v ilAttrsThatGoOnPrimaryItem m returnTy - cgbuf.mgbuf.AddEventDef(tref, edef) - () + // compiling CLIEvent properties + | Some memberInfo + when not v.IsExtensionMember && + (match memberInfo.MemberFlags.MemberKind with + | (MemberKind.PropertySet | MemberKind.PropertyGet) -> CompileAsEvent cenv.g v.Attribs + | _ -> false) -> + + let useMethodImpl = + if compileAsInstance && + ((memberInfo.MemberFlags.IsDispatchSlot && memberInfo.IsImplemented) || + memberInfo.MemberFlags.IsOverrideOrExplicitImpl) then + + let useMethodImpl = memberInfo.ImplementedSlotSigs |> List.exists (fun slotsig -> ComputeUseMethodImpl cenv (v, slotsig)) + + let nameOfOverridingMethod = + match ComputeMethodImplNameFixupForMemberBinding cenv (v, memberInfo) with + | None -> mspec.Name + | Some nm -> nm + + // Fixup can potentially change name of reflected definition that was already recorded - patch it if necessary + cgbuf.mgbuf.ReplaceNameOfReflectedDefinition(v, nameOfOverridingMethod) + useMethodImpl + else + false + + // skip method generation for compiling the property as a .NET event + // Instead emit the pseudo-property as an event. + // on't do this if it's a private method impl. + if not useMethodImpl then + let edef = GenEventForProperty cenv eenvForMeth mspec v ilAttrsThatGoOnPrimaryItem m returnTy + cgbuf.mgbuf.AddEventDef(tref, edef) | _ -> @@ -5861,20 +5896,20 @@ and GenMethodForBinding else let mdef = if not compileAsInstance then - mkILStaticMethod (ilMethTypars, v.CompiledName, access, ilParams, ilReturn, ilMethodBody) + mkILStaticMethod (ilMethTypars, mspec.Name, access, ilParams, ilReturn, ilMethodBody) elif (memberInfo.MemberFlags.IsDispatchSlot && memberInfo.IsImplemented) || memberInfo.MemberFlags.IsOverrideOrExplicitImpl then let flagFixups = ComputeFlagFixupsForMemberBinding cenv (v, memberInfo) - let mdef = mkILGenericVirtualMethod (v.CompiledName, ILMemberAccess.Public, ilMethTypars, ilParams, ilReturn, ilMethodBody) + let mdef = mkILGenericVirtualMethod (mspec.Name, ILMemberAccess.Public, ilMethTypars, ilParams, ilReturn, ilMethodBody) let mdef = List.fold (fun mdef f -> f mdef) mdef flagFixups // fixup can potentially change name of reflected definition that was already recorded - patch it if necessary cgbuf.mgbuf.ReplaceNameOfReflectedDefinition(v, mdef.Name) mdef else - mkILGenericNonVirtualMethod (v.CompiledName, access, ilMethTypars, ilParams, ilReturn, ilMethodBody) + mkILGenericNonVirtualMethod (mspec.Name, access, ilMethTypars, ilParams, ilReturn, ilMethodBody) let isAbstract = memberInfo.MemberFlags.IsDispatchSlot && diff --git a/src/fsharp/PrettyNaming.fs b/src/fsharp/PrettyNaming.fs index 4c11b9054d3..d37604ac0fd 100755 --- a/src/fsharp/PrettyNaming.fs +++ b/src/fsharp/PrettyNaming.fs @@ -697,4 +697,6 @@ module public FSharp.Compiler.PrettyNaming | _ -> Some (defaultArgName, actualArgValue)) mangleProvidedTypeName (nm, nonDefaultArgs) - let outArgCompilerGeneratedName = "outArg" \ No newline at end of file + let outArgCompilerGeneratedName = "outArg" + + let ExtraWitnessMethodName nm = nm + "WithWitnesses" \ No newline at end of file diff --git a/src/fsharp/QuotationPickler.fs b/src/fsharp/QuotationPickler.fs index 85a8088dba2..1f10b994310 100644 --- a/src/fsharp/QuotationPickler.fs +++ b/src/fsharp/QuotationPickler.fs @@ -52,7 +52,7 @@ type CombOp = | AppOp | CondOp | ModuleValueOp of NamedTypeData * string * bool - | ModuleValueWOp of NamedTypeData * string * bool * int + | ModuleValueWOp of NamedTypeData * string * bool * string * int | LetRecOp | LetRecCombOp | LetOp @@ -129,8 +129,8 @@ let mkCond (x1, x2, x3) = CombExpr(CondOp, [], [x1;x2;x3]) let mkModuleValueApp (tcref, nm, isProp, tyargs, args: ExprData list) = CombExpr(ModuleValueOp(tcref, nm, isProp), tyargs, args) -let mkModuleValueWApp (tcref, nm, isProp, nWitnesses, tyargs, args: ExprData list) = - CombExpr(ModuleValueWOp(tcref, nm, isProp, nWitnesses), tyargs, args) +let mkModuleValueWApp (tcref, nm, isProp, nmW, nWitnesses, tyargs, args: ExprData list) = + CombExpr(ModuleValueWOp(tcref, nm, isProp, nmW, nWitnesses), tyargs, args) let mkTuple (ty, x) = CombExpr(TupleMkOp, [ty], x) @@ -472,9 +472,10 @@ let p_CombOp x st = p_MethodData a st p_MethodData b st p_int c st - | ModuleValueWOp (x, y, z, n) -> + | ModuleValueWOp (x, y, z, nmW, nWitnesses) -> p_byte 51 st - p_int n st + p_string nmW st + p_int nWitnesses st p_NamedType x st p_string y st p_bool z st @@ -496,7 +497,7 @@ type ModuleDefnData = IsProperty: bool } type MethodBaseData = - | ModuleDefn of ModuleDefnData * int + | ModuleDefn of ModuleDefnData * (string * int) option | Method of MethodData | Ctor of CtorData @@ -504,18 +505,18 @@ let pickle = pickle_obj p_expr let p_MethodBase x st = match x with - | ModuleDefn (md, nWitnesses) -> - if nWitnesses = 0 then - p_byte 0 st - p_NamedType md.Module st - p_string md.Name st - p_bool md.IsProperty st - else - p_byte 3 st - p_int nWitnesses st - p_NamedType md.Module st - p_string md.Name st - p_bool md.IsProperty st + | ModuleDefn (md, None) -> + p_byte 0 st + p_NamedType md.Module st + p_string md.Name st + p_bool md.IsProperty st + | ModuleDefn (md, Some (nmW, nWitnesses)) -> + p_byte 3 st + p_string nmW st + p_int nWitnesses st + p_NamedType md.Module st + p_string md.Name st + p_bool md.IsProperty st | Method md -> p_byte 1 st p_MethodData md st diff --git a/src/fsharp/QuotationPickler.fsi b/src/fsharp/QuotationPickler.fsi index 618dfd588d8..7ac1f1ad996 100644 --- a/src/fsharp/QuotationPickler.fsi +++ b/src/fsharp/QuotationPickler.fsi @@ -47,7 +47,7 @@ type ModuleDefnData = IsProperty: bool } type MethodBaseData = - | ModuleDefn of ModuleDefnData * int + | ModuleDefn of ModuleDefnData * (string * int) option | Method of MethodData | Ctor of CtorData @@ -62,7 +62,7 @@ val mkQuote : ExprData -> ExprData val mkQuoteRaw40 : ExprData -> ExprData // only available for FSharp.Core 4.4.0.0+ val mkCond : ExprData * ExprData * ExprData -> ExprData val mkModuleValueApp : NamedTypeData * string * bool * TypeData list * ExprData list -> ExprData -val mkModuleValueWApp : NamedTypeData * string * bool * int * TypeData list * ExprData list -> ExprData +val mkModuleValueWApp : NamedTypeData * string * bool * string * int * TypeData list * ExprData list -> ExprData val mkLetRec : (VarData * ExprData) list * ExprData -> ExprData val mkLet : (VarData * ExprData) * ExprData -> ExprData val mkRecdMk : NamedTypeData * TypeData list * ExprData list -> ExprData diff --git a/src/fsharp/QuotationTranslator.fs b/src/fsharp/QuotationTranslator.fs index f2f85a322a6..3c26bafb06a 100644 --- a/src/fsharp/QuotationTranslator.fs +++ b/src/fsharp/QuotationTranslator.fs @@ -744,22 +744,27 @@ and ConvObjectModelCallCore cenv env m (isPropGet, isPropSet, isNewObj, parentTy methRetType = methRetTypeR methName = methName numGenericArgs = numGenericArgs } + QP.mkMethodCall(methR, tyargsR, callArgsR) else + // The old method entry point let methR: QuotationPickler.MethodData = { methParent = parentTyconR methArgTypes = methArgTypesR methRetType = methRetTypeR methName = methName numGenericArgs = numGenericArgs } - let methWR QuotationPickler.MethodData = + + // The witness-passing method entry point + let methWR: QuotationPickler.MethodData = { methParent = parentTyconR methArgTypes = witnessArgTypesR @ methArgTypesR methRetType = methRetTypeR - methName = methName + methName = ExtraWitnessMethodName methName numGenericArgs = numGenericArgs } + QP.mkMethodCallW(methR, methWR, List.length witnessArgTypesR, tyargsR, callArgsR) and ConvModuleValueApp cenv env m (vref:ValRef) tyargs witnessArgs (args: Expr list list) = @@ -778,7 +783,7 @@ and ConvModuleValueAppCore cenv env m (vref:ValRef) tyargs witnessArgs (curriedA if nWitnesses = 0 then QP.mkModuleValueApp(tcrefR, nm, isProperty, tyargsR, argsR) else - QP.mkModuleValueWApp(tcrefR, nm, isProperty, nWitnesses, tyargsR, argsR) + QP.mkModuleValueWApp(tcrefR, nm, isProperty, ExtraWitnessMethodName nm, nWitnesses, tyargsR, argsR) and ConvExprs cenv env args = List.map (ConvExpr cenv env) args @@ -1154,7 +1159,7 @@ let ConvMethodBase cenv env (methName, v: Val) = QP.MethodBaseData.ModuleDefn ({ Name = methName Module = parentTyconR - IsProperty = IsCompiledAsStaticProperty cenv.g v }, nWitnesses) + IsProperty = IsCompiledAsStaticProperty cenv.g v }, (if nWitnesses = 0 then None else Some (ExtraWitnessMethodName methName, nWitnesses))) // FSComp.SR.crefQuotationsCantContainLiteralByteArrays diff --git a/tests/fsharp/core/quotes/test.fsx b/tests/fsharp/core/quotes/test.fsx index 37d66b392ec..d5ad0d762cf 100644 --- a/tests/fsharp/core/quotes/test.fsx +++ b/tests/fsharp/core/quotes/test.fsx @@ -3184,7 +3184,7 @@ module WitnessTests = | CallWithWitnesses(None, minfo1, minfo2, witnessArgs, args) -> minfo1.Name = "op_Addition" && minfo1.GetParameters().Length = 2 && - minfo2.Name = "op_Addition" && + minfo2.Name = "op_AdditionWithWitnesses" && minfo2.GetParameters().Length = 3 && (printfn "checking witnessArgs.Length = %d... args.Length"; true) && witnessArgs.Length = 1 && @@ -3203,7 +3203,7 @@ module WitnessTests = minfo1.Name = "op_Addition" && (printfn "checking minfo1.GetParameters().Length..."; true) && minfo1.GetParameters().Length = 2 && - minfo2.Name = "op_Addition" && + minfo2.Name = "op_AdditionWithWitnesses" && (printfn "checking minfo2.GetParameters().Length..."; true) && minfo2.GetParameters().Length = 3 && (printfn "checking args.Length..."; true) && @@ -3219,21 +3219,15 @@ module WitnessTests = printfn "incorrect node" false) - test "check CallWithWitness (DateTime + TimeSpan)" + test "check Call (DateTime + TimeSpan)" (<@ System.DateTime.Now + System.TimeSpan.Zero @> |> function - | CallWithWitnesses(None, minfo1, minfo2, witnessArgs, args) -> + | Call(None, minfo1, args) -> minfo1.Name = "op_Addition" && (printfn "checking minfo1.GetParameters().Length..."; true) && minfo1.GetParameters().Length = 2 && - minfo2.Name = "op_Addition" && - (printfn "checking minfo2.GetParameters().Length..."; true) && - minfo2.GetParameters().Length = 3 && - (printfn "checking minfo2.GetParameters().[0].Name = %s..." (minfo2.GetParameters().[0].Name); true) && //minfo2.GetParameters().[0].Name = "op_Addition" && - witnessArgs.Length = 1 && args.Length = 2 && - (match witnessArgs with [ Lambda _ ] -> true | _ -> false) && (match args with [ _; _ ] -> true | _ -> false) | _ -> false) @@ -3250,7 +3244,7 @@ module WitnessTests = (printfn "checking minfo1.GetParameters().Length..."; true) && minfo1.GetParameters().Length = 2 && minfo2.IsStatic && - minfo2.Name = "StaticAdd" && + minfo2.Name = "StaticAddWithWitnesses" && (printfn "checking minfo2.GetParameters().Length = %d..." (minfo2.GetParameters().Length); true) && minfo2.GetParameters().Length = 3 && (printfn "checking witnessArgs.Length..."; true) && @@ -3275,7 +3269,7 @@ module WitnessTests = (printfn "checking minfo1.GetParameters().Length..."; true) && minfo1.GetParameters().Length = 2 && not minfo2.IsStatic && - minfo2.Name = "InstanceAdd" && + minfo2.Name = "InstanceAddWithWitnesses" && (printfn "checking minfo2.GetParameters().Length = %d..." (minfo2.GetParameters().Length); true) && minfo2.GetParameters().Length = 3 && (printfn "checking witnessArgs.Length..."; true) && From a320095cb8b941743328c0f97f76fb4c89e942ff Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 26 Mar 2019 23:49:48 +0000 Subject: [PATCH 05/77] fix build --- src/fsharp/IlxGen.fs | 105 +------------------------------------------ 1 file changed, 2 insertions(+), 103 deletions(-) diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 5501d861b47..de3424fec59 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -230,11 +230,7 @@ type cenv = /// The ImportMap for reading IL amap: ImportMap -<<<<<<< HEAD /// A callback for tcVal in the typechecker. Used to generalize values when finding witnesses. -======= - /// A callback for TcVal in the typechecker. Used to generalize values when finding witnesses. ->>>>>>> 87cbf6f2faf76e0f4fbbbc4eee0a5bb6efe0786a /// It is unfortunate this is needed but it is until we supply witnesses through the compiation. tcVal: ConstraintSolver.TcValF @@ -743,21 +739,12 @@ type ValStorage = /// Indicates the value is stored in a static field. | StaticField of ILFieldSpec * ValRef * (*hasLiteralAttr:*)bool * ILType * string * ILType * ILMethodRef * ILMethodRef * OptionalShadowLocal -<<<<<<< HEAD /// Indicates the value is represented as a property that recomputes it each time it is referenced. Used for simple constants that do not cause initialization triggers | StaticProperty of ILMethodSpec * OptionalShadowLocal -======= - /// Indicates the value is "stored" as a property that recomputes it each time it is referenced. Used for simple constants that do not cause initialization triggers - | StaticProperty of ILMethodSpec * OptionalShadowLocal ->>>>>>> 87cbf6f2faf76e0f4fbbbc4eee0a5bb6efe0786a /// Indicates the value is represented as an IL method (in a "main" class for a F# /// compilation unit, or as a member) according to its inferred or specified arity. -<<<<<<< HEAD | Method of ValReprInfo * ValRef * ILMethodSpec * ILMethodSpec * Range.range * Typars * Typars * CurriedArgInfos * ArgReprInfo list * TraitWitnessInfos * TType list * ArgReprInfo -======= - | Method of ValReprInfo * ValRef * ILMethodSpec * Range.range * ArgReprInfo list * TType list * ArgReprInfo ->>>>>>> 87cbf6f2faf76e0f4fbbbc4eee0a5bb6efe0786a /// Indicates the value is stored at the given position in the closure environment accessed via "ldarg 0" | Env of ILType * int * ILFieldSpec * NamedLocalIlxClosureInfo ref option @@ -829,14 +816,10 @@ and IlxGenEnv = /// All values in scope valsInScope: ValMap> -<<<<<<< HEAD /// All witnesses in scope witnessesInScope: ImmutableDictionary /// For optimizing direct tail recursion to a loop - mark says where to branch to. Length is 0 or 1. -======= - /// For optimizing direct tail recursion to a loop - mark says where to branch to. Length is 0 or 1. ->>>>>>> 87cbf6f2faf76e0f4fbbbc4eee0a5bb6efe0786a /// REVIEW: generalize to arbitrary nested local loops?? innerVals: (ValRef * (BranchCallItem * Mark)) list @@ -2230,19 +2213,12 @@ let rec GenExpr (cenv: cenv) (cgbuf: CodeGenBuffer) eenv sp expr sequel = ) -> // application of local type functions with type parameters = measure types and body = local value - inine the body GenExpr cenv cgbuf eenv sp v sequel -<<<<<<< HEAD | Expr.App(f, fty, tyargs, curriedArgs, m) -> GenApp cenv cgbuf eenv (f, fty, tyargs, curriedArgs, m) sequel | Expr.Val(v,_,m) -> GenGetVal cenv cgbuf eenv (v,m) sequel -======= - | Expr.App(f,fty, tyargs, args, m) -> - GenApp cenv cgbuf eenv (f, fty, tyargs, args, m) sequel - | Expr.Val(v, _, m) -> - GenGetVal cenv cgbuf eenv (v, m) sequel ->>>>>>> 87cbf6f2faf76e0f4fbbbc4eee0a5bb6efe0786a // Most generation of linear expressions is implemented routinely using tailcalls and the correct sequels. // This is because the element of expansion happens to be the final thing generated in most cases. However @@ -2926,13 +2902,8 @@ and GenApp cenv cgbuf eenv (f, fty, tyargs, curriedArgs, m) sequel = (let arityInfo = match kind with | BranchCallClosure arityInfo -<<<<<<< HEAD | BranchCallMethod (arityInfo, _, _, _, _) -> arityInfo arityInfo.Length = curriedArgs.Length -======= - | BranchCallMethod (arityInfo, _, _, _, _) -> arityInfo - arityInfo.Length = args.Length ->>>>>>> 87cbf6f2faf76e0f4fbbbc4eee0a5bb6efe0786a ) && (* no tailcall out of exception handler, etc. *) (match sequelIgnoringEndScopesAndDiscard sequel with Return | ReturnVoid -> true | _ -> false)) @@ -3069,13 +3040,8 @@ and GenApp cenv cgbuf eenv (f, fty, tyargs, curriedArgs, m) sequel = let ilTyArgs = GenTypeArgs cenv.amap m eenv.tyenv tyargs // For instance method calls chop off some type arguments, which are already -<<<<<<< HEAD // carried by the class. Also work out if it's a virtual call. let _, virtualCall, newobj, isSuperInit, isSelfInit, _, _, _ = GetMemberCallInfo cenv.g (vref, valUseFlags) -======= - // carried by the class. Also work out if it's a virtual call. - let _, virtualCall, newobj, isSuperInit, isSelfInit, _, _, _ = GetMemberCallInfo cenv.g (vref, valUseFlags) in ->>>>>>> 87cbf6f2faf76e0f4fbbbc4eee0a5bb6efe0786a // numEnclILTypeArgs will include unit-of-measure args, unfortunately. For now, just cut-and-paste code from GetMemberCallInfo // @REVIEW: refactor this @@ -3174,13 +3140,8 @@ and GenApp cenv cgbuf eenv (f, fty, tyargs, curriedArgs, m) sequel = // However, we know the type instantiation for the value. // In this case we can often generate a type-specific local expression for the value. // This reduces the number of dynamic type applications. -<<<<<<< HEAD | (Expr.Val(vref, _, _), _, _) -> GenGetValRefAndSequel cenv cgbuf eenv m vref (Some (tyargs, curriedArgs, m, sequel)) -======= - | (Expr.Val(vref, _, _), _, _) -> - GenGetValRefAndSequel cenv cgbuf eenv m vref (Some (tyargs, args, m, sequel)) ->>>>>>> 87cbf6f2faf76e0f4fbbbc4eee0a5bb6efe0786a | _ -> (* worst case: generate a first-class function value and call *) @@ -3751,15 +3712,9 @@ and GenQuotation cenv cgbuf eenv (ast, conv, m, ety) sequel = let bytesExpr = Expr.Op(TOp.Bytes(astSerializedBytes), [], [], m) let deserializeExpr = -<<<<<<< HEAD let qf = QuotationTranslator.QuotationGenerationScope.ComputeQuotationFormat cenv.g if qf.SupportsDeserializeEx then let referencedTypeDefExprs = List.map (mkILNonGenericBoxedTy >> mkTypeOfExpr cenv m) referencedTypeDefs -======= - match QuotationTranslator.QuotationGenerationScope.ComputeQuotationFormat cenv.g with - | QuotationTranslator.QuotationSerializationFormat.FSharp_40_Plus -> - let referencedTypeDefExprs = List.map (mkILNonGenericBoxedTy >> mkTypeOfExpr cenv m) referencedTypeDefs ->>>>>>> 87cbf6f2faf76e0f4fbbbc4eee0a5bb6efe0786a let referencedTypeDefsExpr = mkArray (cenv.g.system_Type_ty, referencedTypeDefExprs, m) let spliceTypesExpr = mkArray (cenv.g.system_Type_ty, spliceTypeExprs, m) let spliceArgsExpr = mkArray (rawTy, spliceArgExprs, m) @@ -5291,7 +5246,6 @@ and GenBindingAfterSequencePoint cenv cgbuf eenv sp (TBind(vspec, rhsExpr, _)) s CommitStartScope cgbuf startScopeMarkOpt GenExpr cenv cgbuf eenv SPSuppress cctorBody discard -<<<<<<< HEAD | Method (topValInfo, _, mspec, mspecW, _, ctps, mtps, curriedArgInfos, paramInfos, witnessInfos, argTys, retInfo) -> let methLambdaTypars, methLambdaCtorThisValOpt, methLambdaBaseValOpt, methLambdaCurriedVars, methLambdaBody, methLambdaBodyTy = @@ -5299,11 +5253,6 @@ and GenBindingAfterSequencePoint cenv cgbuf eenv sp (TBind(vspec, rhsExpr, _)) s let methLambdaVars = List.concat methLambdaCurriedVars -======= - | Method (topValInfo, _, mspec, _, paramInfos, methodArgTys, retInfo) -> - let tps, ctorThisValOpt, baseValOpt, vsl, body', bodyty = IteratedAdjustArityOfLambda cenv.g cenv.amap topValInfo rhsExpr - let methodVars = List.concat vsl ->>>>>>> 87cbf6f2faf76e0f4fbbbc4eee0a5bb6efe0786a CommitStartScope cgbuf startScopeMarkOpt GenMethodForBinding cenv cgbuf eenv (vspec, mspec, false, access, ctps, mtps, [], curriedArgInfos, paramInfos, argTys, retInfo, topValInfo, methLambdaCtorThisValOpt, methLambdaBaseValOpt, methLambdaTypars, methLambdaVars, methLambdaBody, methLambdaBodyTy) @@ -5772,11 +5721,7 @@ and GenMethodForBinding match methLambdaVars with | [] -> error(InternalError("Internal error: empty argument list for instance method", v.Range)) | h::t -> [h], t, true -<<<<<<< HEAD | _ -> [], methLambdaVars, false -======= - | _ -> [], methodVars, false ->>>>>>> 87cbf6f2faf76e0f4fbbbc4eee0a5bb6efe0786a let nonUnitNonSelfMethodVars, body = BindUnitVars cenv.g (nonSelfMethodVars, paramInfos, methLambdaBody) let nonUnitMethodVars = selfMethodVars@nonUnitNonSelfMethodVars @@ -5827,15 +5772,9 @@ and GenMethodForBinding // Now generate the code. let hasPreserveSigNamedArg, ilMethodBody, hasDllImport = match TryFindFSharpAttributeOpt cenv.g cenv.g.attrib_DllImportAttribute v.Attribs with -<<<<<<< HEAD | Some (Attrib(_, _, [ AttribStringArg(dll) ], namedArgs, _, _, m)) -> if not (isNil methLambdaTypars) then error(Error(FSComp.SR.ilSignatureForExternalFunctionContainsTypeParameters(), m)) let hasPreserveSigNamedArg, mbody = GenPInvokeMethod (mspec.Name, dll, namedArgs) -======= - | Some (Attrib(_, _, [ AttribStringArg(dll) ], namedArgs, _, _, m)) -> - if not (isNil tps) then error(Error(FSComp.SR.ilSignatureForExternalFunctionContainsTypeParameters(), m)) - let hasPreserveSigNamedArg, mbody = GenPInvokeMethod (v.CompiledName, dll, namedArgs) ->>>>>>> 87cbf6f2faf76e0f4fbbbc4eee0a5bb6efe0786a hasPreserveSigNamedArg, mbody, true | Some (Attrib(_, _, _, _, _, _, m)) -> @@ -5927,19 +5866,12 @@ and GenMethodForBinding else false -<<<<<<< HEAD // skip method generation for compiling the property as a .NET event // Instead emit the pseudo-property as an event. // on't do this if it's a private method impl. if not useMethodImpl then let edef = GenEventForProperty cenv eenvForMeth mspec v ilAttrsThatGoOnPrimaryItem m returnTy cgbuf.mgbuf.AddEventDef(tref, edef) -======= - let isAbstract = - memberInfo.MemberFlags.IsDispatchSlot && - let tcref = v.MemberApparentEntity - not tcref.Deref.IsFSharpDelegateTycon ->>>>>>> 87cbf6f2faf76e0f4fbbbc4eee0a5bb6efe0786a | _ -> @@ -5991,21 +5923,12 @@ and GenMethodForBinding match memberInfo.MemberFlags.MemberKind with -<<<<<<< HEAD | (MemberKind.PropertySet | MemberKind.PropertyGet) -> if not (isNil ilMethTypars) then error(InternalError("A property may not be more generic than the enclosing type - constrain the polymorphism in the expression", v.Range)) // Check if we're compiling the property as a .NET event assert not (CompileAsEvent cenv.g v.Attribs) -======= - | (MemberKind.PropertySet | MemberKind.PropertyGet) -> - if not (isNil ilMethTypars) then - error(InternalError("A property may not be more generic than the enclosing type - constrain the polymorphism in the expression", v.Range)) - - // Check if we're compiling the property as a .NET event - if CompileAsEvent cenv.g v.Attribs then ->>>>>>> 87cbf6f2faf76e0f4fbbbc4eee0a5bb6efe0786a // Emit the property, but not if its a private method impl if mdef.Access <> ILMemberAccess.Private then @@ -6038,7 +5961,6 @@ and GenMethodForBinding let mdef = mdef.With(customAttrs= ilCustomAttrs) mdef -<<<<<<< HEAD // Does the function have an explicit [] attribute? let isExplicitEntryPoint = HasFSharpAttribute cenv.g cenv.g.attrib_EntryPointAttribute attrs @@ -6065,20 +5987,6 @@ and GenMethodForBinding CountMethodDef() cgbuf.mgbuf.AddMethodDef(tref, mdef) -======= - // For extension properties, also emit attrsAppliedToGetterOrSetter on the getter or setter method - let ilAttrs = - match v.MemberInfo with - | Some memberInfo when v.IsExtensionMember -> - match memberInfo.MemberFlags.MemberKind with - | (MemberKind.PropertySet | MemberKind.PropertyGet) -> ilAttrsThatGoOnPrimaryItem @ GenAttrs cenv eenv attrsAppliedToGetterOrSetter - | _ -> ilAttrsThatGoOnPrimaryItem - | _ -> ilAttrsThatGoOnPrimaryItem - - let ilCustomAttrs = mkILCustomAttrs (ilAttrs @ sourceNameAttribs @ ilAttrsCompilerGenerated) - let mdef = mdef.With(customAttrs= ilCustomAttrs) - EmitTheMethodDef mdef ->>>>>>> 87cbf6f2faf76e0f4fbbbc4eee0a5bb6efe0786a and GenPInvokeMethod (nm, dll, namedArgs) = let decoder = AttributeDecoder namedArgs @@ -6226,21 +6134,12 @@ and GenGetStorageAndSequel cenv cgbuf eenv m (ty, ilTy) storage fetchSequel = if hasLiteralAttr then EmitGetStaticField cgbuf ilTy fspec else -<<<<<<< HEAD - CG.EmitInstr cgbuf (pop 0) (Push [ilTy]) (I_call(Normalcall, mkILMethSpecForMethRefInTy (ilGetterMethRef, ilContainerTy, []), None)) - CommitGetStorageSequel cenv cgbuf eenv m ty None fetchSequel - - | StaticProperty (ilGetterMethSpec, _) -> - CG.EmitInstr cgbuf (pop 0) (Push [ilTy]) (I_call (Normalcall, ilGetterMethSpec, None)) - CommitGetStorageSequel cenv cgbuf eenv m ty None fetchSequel -======= CG.EmitInstr cgbuf (pop 0) (Push [ilTy]) (I_call(Normalcall, mkILMethSpecForMethRefInTy (ilGetterMethRef, ilContainerTy, []), None)) - CommitGetStorageSequel cenv cgbuf eenv m ty None storeSequel + CommitGetStorageSequel cenv cgbuf eenv m ty None fetchSequel | StaticProperty (ilGetterMethSpec, _) -> CG.EmitInstr cgbuf (pop 0) (Push [ilTy]) (I_call (Normalcall, ilGetterMethSpec, None)) - CommitGetStorageSequel cenv cgbuf eenv m ty None storeSequel ->>>>>>> 87cbf6f2faf76e0f4fbbbc4eee0a5bb6efe0786a + CommitGetStorageSequel cenv cgbuf eenv m ty None fetchSequel | Method (topValInfo, vref, _, _, _, _, _, _, _, _, _, _) -> // Get a toplevel value as a first-class value. From 6e7e3c4c71a45930227f26c77fdf1de96d9df82c Mon Sep 17 00:00:00 2001 From: Don Syme Date: Wed, 27 Mar 2019 11:57:03 +0000 Subject: [PATCH 06/77] us proto build on mac and linux --- eng/build.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/eng/build.sh b/eng/build.sh index d814dcd04d4..c00b144a859 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -217,6 +217,13 @@ function BuildSolution { cp $artifacts_dir/bin/fslex/$bootstrap_config/netcoreapp2.0/* $bootstrap_dir cp $artifacts_dir/bin/fsyacc/$bootstrap_config/netcoreapp2.0/* $bootstrap_dir + MSBuild "$repo_root/proto.proj" \ + /restore \ + /p:Configuration=$bootstrap_config \ + /t:Build + + cp $artifacts_dir/bin/fsc/$bootstrap_config/netcoreapp2.0/* $bootstrap_dir + # do real build MSBuild $toolset_build_proj \ $bl \ @@ -230,6 +237,7 @@ function BuildSolution { /p:Publish=$publish \ /p:UseRoslynAnalyzers=$enable_analyzers \ /p:ContinuousIntegrationBuild=$ci \ + /p:BootstrapBuildPath="$bootstrap_dir" \ /p:QuietRestore=$quiet_restore \ /p:QuietRestoreBinaryLog="$binary_log" \ $properties From 576d1176143537363dcce0f8c8a7c6683c5bff0f Mon Sep 17 00:00:00 2001 From: Don Syme Date: Wed, 27 Mar 2019 13:18:54 +0000 Subject: [PATCH 07/77] fix instance member trait constraints --- src/fsharp/IlxGen.fs | 2 +- src/fsharp/TastOps.fs | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index de3424fec59..1a5cc878efe 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -3805,7 +3805,7 @@ and GenTraitCall cenv cgbuf eenv (traitInfo: TraitConstraintInfo, argExprs, m) e | None -> // If witnesses are available, we should now always find trait witnesses in scope - assert not eenv.witnessesInScope.IsEmpty + assert eenv.witnessesInScope.IsEmpty let minfoOpt = CommitOperationResult (ConstraintSolver.CodegenWitnessThatTypeSupportsTraitConstraint cenv.tcVal cenv.g cenv.amap m traitInfo argExprs) match minfoOpt with diff --git a/src/fsharp/TastOps.fs b/src/fsharp/TastOps.fs index 479186e7be1..e44b0bfc9cb 100644 --- a/src/fsharp/TastOps.fs +++ b/src/fsharp/TastOps.fs @@ -7650,14 +7650,15 @@ let LinearizeTopMatch g parent = function //--------------------------------------------------------------------------- let GenWitnessArgTys (g: TcGlobals) (traitInfo: TraitWitnessInfo) = - let (TraitWitnessInfo(tys, _nm, memFlags, argtys, _rty)) = traitInfo + let (TraitWitnessInfo(_tys, _nm, _memFlags, argtys, _rty)) = traitInfo let argtys = if argtys.IsEmpty then [g.unit_ty] else argtys let argtysl = List.map List.singleton argtys - match tys with - | _ when not memFlags.IsInstance -> argtysl - | [ty] -> [ty] :: argtysl - | [_; _] -> [g.obj_ty] :: argtysl - | _ -> failwith "unexpected empty type support for trait constraint" + argtysl + //match tys with + //| _ when not memFlags.IsInstance -> argtysl + //| [ty] -> [ty] :: argtysl + //| [_; _] -> [g.obj_ty] :: argtysl + //| _ -> failwith "unexpected empty type support for trait constraint" let GenWitnessTy (g: TcGlobals) (traitInfo: TraitWitnessInfo) = let rty = match traitInfo.ReturnType with None -> g.unit_ty | Some ty -> ty From 39ec26ad4f68b5530675418212fce6fd8e26cd12 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Wed, 27 Mar 2019 13:24:28 +0000 Subject: [PATCH 08/77] build right proto on unix --- proto.proj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto.proj b/proto.proj index c60f17d8426..1d707586ea7 100644 --- a/proto.proj +++ b/proto.proj @@ -8,7 +8,7 @@ TargetFramework=net46 - TargetFramework=netcoreapp2.1 + TargetFramework=netstandard2.0 TargetFramework=net46 From 7cc99ca04b475f2fa3c53b03474e2f2fa085a0f1 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 28 Mar 2019 11:46:15 +0000 Subject: [PATCH 09/77] fix build to really use proto --- eng/build-utils.ps1 | 4 ++-- eng/build.sh | 14 ++++++++------ fcs/build.fsx | 8 +++++--- src/fsharp/ExtensionTyping.fs | 4 ++-- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/eng/build-utils.ps1 b/eng/build-utils.ps1 index 845169db12a..d4f2b625f2b 100644 --- a/eng/build-utils.ps1 +++ b/eng/build-utils.ps1 @@ -242,8 +242,8 @@ function Make-BootstrapBuild() { # prepare FsLex and Fsyacc Run-MSBuild "$RepoRoot\src\buildtools\buildtools.proj" "/restore /t:Build" -logFileName "BuildTools" -configuration $bootstrapConfiguration - Copy-Item "$ArtifactsDir\bin\fslex\$bootstrapConfiguration\netcoreapp2.0\*" -Destination $dir - Copy-Item "$ArtifactsDir\bin\fsyacc\$bootstrapConfiguration\netcoreapp2.0\*" -Destination $dir + Copy-Item "$ArtifactsDir\bin\fslex\$bootstrapConfiguration\$coreclrTargetFramework\*" -Destination $dir + Copy-Item "$ArtifactsDir\bin\fsyacc\$bootstrapConfiguration\$coreclrTargetFramework\*" -Destination $dir # prepare compiler $projectPath = "$RepoRoot\proto.proj" diff --git a/eng/build.sh b/eng/build.sh index c00b144a859..bae5b6a45f7 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -205,6 +205,8 @@ function BuildSolution { quiet_restore=true fi + coreclr_target_framework=netcoreapp2.0 + # build bootstrap tools bootstrap_config=Proto MSBuild "$repo_root/src/buildtools/buildtools.proj" \ @@ -214,15 +216,15 @@ function BuildSolution { bootstrap_dir=$artifacts_dir/Bootstrap mkdir -p "$bootstrap_dir" - cp $artifacts_dir/bin/fslex/$bootstrap_config/netcoreapp2.0/* $bootstrap_dir - cp $artifacts_dir/bin/fsyacc/$bootstrap_config/netcoreapp2.0/* $bootstrap_dir + cp $artifacts_dir/bin/fslex/$bootstrap_config/$coreclr_target_framework/* $bootstrap_dir + cp $artifacts_dir/bin/fsyacc/$bootstrap_config/$coreclr_target_framework/* $bootstrap_dir MSBuild "$repo_root/proto.proj" \ /restore \ /p:Configuration=$bootstrap_config \ /t:Build - cp $artifacts_dir/bin/fsc/$bootstrap_config/netcoreapp2.0/* $bootstrap_dir + cp $artifacts_dir/bin/fsc/$bootstrap_config/netcoreapp2.1/* $bootstrap_dir # do real build MSBuild $toolset_build_proj \ @@ -248,9 +250,9 @@ InitializeDotNetCli $restore BuildSolution if [[ "$test_core_clr" == true ]]; then - TestUsingNUnit --testproject "$repo_root/tests/FSharp.Compiler.UnitTests/FSharp.Compiler.UnitTests.fsproj" --targetframework netcoreapp2.0 - TestUsingNUnit --testproject "$repo_root/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj" --targetframework netcoreapp2.0 - TestUsingNUnit --testproject "$repo_root/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj" --targetframework netcoreapp2.0 + TestUsingNUnit --testproject "$repo_root/tests/FSharp.Compiler.UnitTests/FSharp.Compiler.UnitTests.fsproj" --targetframework $coreclr_target_framework + TestUsingNUnit --testproject "$repo_root/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj" --targetframework $coreclr_target_framework + TestUsingNUnit --testproject "$repo_root/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj" --targetframework $coreclr_target_framework fi ExitWithExitCode 0 diff --git a/fcs/build.fsx b/fcs/build.fsx index 50735795d88..58262f7c40a 100644 --- a/fcs/build.fsx +++ b/fcs/build.fsx @@ -24,6 +24,8 @@ let isMono = false // Utilities // -------------------------------------------------------------------------------------- +let coreclrTargetFramework = "netcoreapp2.0" + let dotnetExePath = // Build.cmd normally downloads a dotnet cli to: \artifacts\toolset\dotnet // check if there is one there to avoid downloading an additional one here @@ -92,13 +94,13 @@ Target "BuildVersion" (fun _ -> Target "Build" (fun _ -> runDotnet __SOURCE_DIRECTORY__ "build ../src/buildtools/buildtools.proj -v n -c Proto" - let fslexPath = __SOURCE_DIRECTORY__ + "/../artifacts/bin/fslex/Proto/netcoreapp2.0/fslex.dll" - let fsyaccPath = __SOURCE_DIRECTORY__ + "/../artifacts/bin/fsyacc/Proto/netcoreapp2.0/fsyacc.dll" + let fslexPath = __SOURCE_DIRECTORY__ + "/../artifacts/bin/fslex/Proto/" + coreclrTargetFramework + "/fslex.dll" + let fsyaccPath = __SOURCE_DIRECTORY__ + "/../artifacts/bin/fsyacc/Proto/" + coreclrTargetFramework + "/fsyacc.dll" runDotnet __SOURCE_DIRECTORY__ (sprintf "build FSharp.Compiler.Service.sln -v n -c Release /p:FsLexPath=%s /p:FsYaccPath=%s" fslexPath fsyaccPath) ) Target "Test" (fun _ -> - // This project file is used for the netcoreapp2.0 tests to work out reference sets + // This project file is used for the tests to work out reference sets runDotnet __SOURCE_DIRECTORY__ "build ../tests/projects/Sample_NETCoreSDK_FSharp_Library_netstandard2_0/Sample_NETCoreSDK_FSharp_Library_netstandard2_0.fsproj -v n /restore /p:DisableCompilerRedirection=true" // Now run the tests diff --git a/src/fsharp/ExtensionTyping.fs b/src/fsharp/ExtensionTyping.fs index 9bf54e3be79..cd0dfdbd2e3 100755 --- a/src/fsharp/ExtensionTyping.fs +++ b/src/fsharp/ExtensionTyping.fs @@ -45,9 +45,9 @@ module internal ExtensionTyping = // Detect the host tooling context let toolingCompatibleVersions() = if typeof.Assembly.GetName().Name = "mscorlib" then - [ "net461"; "net452"; "net451"; "net45"; "netstandard2.0"] + [ "net48"; "net472"; "net471"; "net47"; "net462"; "net461"; "net452"; "net451"; "net45"; "netstandard2.0"] elif typeof.Assembly.GetName().Name = "System.Private.CoreLib" then - [ "netcoreapp2.0"; "netstandard2.0"] + [ "netcoreapp2.1"; "netcoreapp2.0"; "netstandard2.0"] else System.Diagnostics.Debug.Assert(false, "Couldn't determine runtime tooling context, assuming it supports at least .NET Standard 2.0") [ "netstandard2.0"] From 1f8918d6a953d892b094d11a40a8e6f24b523808 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 28 Mar 2019 12:00:05 +0000 Subject: [PATCH 10/77] update FCS dependencies --- .../FSharp.Compiler.Service.MSBuild.v12.fsproj | 2 +- .../FSharp.Compiler.Service.ProjectCracker.fsproj | 8 ++++---- .../FSharp.Compiler.Service.ProjectCracker.targets | 4 ++-- .../FSharp.Compiler.Service.ProjectCrackerTool.fsproj | 2 +- .../CSharp_Analysis/CSharp_Analysis.csproj | 2 +- .../FSharp.Compiler.Service.fsproj | 6 +++--- fcs/RELEASE_NOTES.md | 5 ++++- fcs/docsrc/content/caches.fsx | 2 +- fcs/docsrc/content/compiler.fsx | 2 +- fcs/docsrc/content/corelib.fsx | 2 +- fcs/docsrc/content/editor.fsx | 2 +- fcs/docsrc/content/filesystem.fsx | 2 +- fcs/docsrc/content/interactive.fsx | 2 +- fcs/docsrc/content/ja/compiler.fsx | 2 +- fcs/docsrc/content/ja/corelib.fsx | 2 +- fcs/docsrc/content/ja/editor.fsx | 2 +- fcs/docsrc/content/ja/filesystem.fsx | 2 +- fcs/docsrc/content/ja/interactive.fsx | 2 +- fcs/docsrc/content/ja/project.fsx | 2 +- fcs/docsrc/content/ja/symbols.fsx | 2 +- fcs/docsrc/content/ja/tokenizer.fsx | 2 +- fcs/docsrc/content/ja/untypedtree.fsx | 2 +- fcs/docsrc/content/project.fsx | 4 ++-- fcs/docsrc/content/queue.fsx | 2 +- fcs/docsrc/content/react.fsx | 10 +++++----- fcs/docsrc/content/symbols.fsx | 2 +- fcs/docsrc/content/tokenizer.fsx | 2 +- fcs/docsrc/content/typedtree.fsx | 2 +- fcs/docsrc/content/untypedtree.fsx | 2 +- fcs/docsrc/tools/generate.fsx | 2 +- fcs/docsrc/tools/generate.ja.fsx | 6 +++--- fcs/paket.dependencies | 2 +- fcs/paket.lock | 4 ++-- 33 files changed, 50 insertions(+), 47 deletions(-) diff --git a/fcs/FSharp.Compiler.Service.MSBuild.v12/FSharp.Compiler.Service.MSBuild.v12.fsproj b/fcs/FSharp.Compiler.Service.MSBuild.v12/FSharp.Compiler.Service.MSBuild.v12.fsproj index 1126a60f2b6..adf97c8c6a0 100644 --- a/fcs/FSharp.Compiler.Service.MSBuild.v12/FSharp.Compiler.Service.MSBuild.v12.fsproj +++ b/fcs/FSharp.Compiler.Service.MSBuild.v12/FSharp.Compiler.Service.MSBuild.v12.fsproj @@ -5,7 +5,7 @@ - net45 + net461 true $(DefineConstants);CROSS_PLATFORM_COMPILER $(DefineConstants);ENABLE_MONO_SUPPORT diff --git a/fcs/FSharp.Compiler.Service.ProjectCracker/FSharp.Compiler.Service.ProjectCracker.fsproj b/fcs/FSharp.Compiler.Service.ProjectCracker/FSharp.Compiler.Service.ProjectCracker.fsproj index c132ae80bb1..cd4ef87393b 100644 --- a/fcs/FSharp.Compiler.Service.ProjectCracker/FSharp.Compiler.Service.ProjectCracker.fsproj +++ b/fcs/FSharp.Compiler.Service.ProjectCracker/FSharp.Compiler.Service.ProjectCracker.fsproj @@ -2,7 +2,7 @@ - net45 + net461 true @@ -20,9 +20,9 @@ ProjectCrackerOptions.fs - - - + + + diff --git a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCracker.targets b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCracker.targets index 45e62e6f25a..bd1c93e7979 100644 --- a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCracker.targets +++ b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCracker.targets @@ -1,7 +1,7 @@ - - + + diff --git a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCrackerTool.fsproj b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCrackerTool.fsproj index 9f690c58ea1..7970d6d5a3b 100644 --- a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCrackerTool.fsproj +++ b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCrackerTool.fsproj @@ -6,7 +6,7 @@ Exe - net45 + net461 true $(DefineConstants);CROSS_PLATFORM_COMPILER $(DefineConstants);ENABLE_MONO_SUPPORT diff --git a/fcs/FSharp.Compiler.Service.Tests/CSharp_Analysis/CSharp_Analysis.csproj b/fcs/FSharp.Compiler.Service.Tests/CSharp_Analysis/CSharp_Analysis.csproj index fc00709da42..30d3c96317f 100644 --- a/fcs/FSharp.Compiler.Service.Tests/CSharp_Analysis/CSharp_Analysis.csproj +++ b/fcs/FSharp.Compiler.Service.Tests/CSharp_Analysis/CSharp_Analysis.csproj @@ -1,7 +1,7 @@  - net45;netstandard2.0 + net461;netstandard2.0 false $(NoWarn);0067;1591 diff --git a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj index 602050c09a4..166dc7976b7 100644 --- a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj +++ b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj @@ -6,7 +6,7 @@ - net45;netstandard2.0 + net461;netstandard2.0 true $(DefineConstants);COMPILER_SERVICE_AS_DLL $(DefineConstants);COMPILER @@ -635,7 +635,7 @@ - + @@ -647,7 +647,7 @@ - + diff --git a/fcs/RELEASE_NOTES.md b/fcs/RELEASE_NOTES.md index 67ac7bcc6b9..d925996ddfe 100644 --- a/fcs/RELEASE_NOTES.md +++ b/fcs/RELEASE_NOTES.md @@ -1,3 +1,6 @@ +#### 23.0.1 + * FSharp.Compiler.Service nuget now uses net461, netstandard2.0 and FSharp.Core 4.6.2 + #### 22.0.3 * [Add entity.DeclaringEntity](https://github.com/Microsoft/visualfsharp/pull/4633), [FCS feature request](https://github.com/fsharp/FSharp.Compiler.Service/issues/830) @@ -10,7 +13,7 @@ #### 21.0.1 * Use new .NET SDK project files - * FSharp.Compiler.Service nuget now uses net45 and netstandard2.0 + * FSharp.Compiler.Service nuget now uses net461 and netstandard2.0 * FSharp.Compiler.Service netstandard2.0 now supports type providers #### 19.0.1 diff --git a/fcs/docsrc/content/caches.fsx b/fcs/docsrc/content/caches.fsx index b2cd9317753..a0a198896cb 100644 --- a/fcs/docsrc/content/caches.fsx +++ b/fcs/docsrc/content/caches.fsx @@ -1,5 +1,5 @@ (*** hide ***) -#I "../../../artifacts/bin/fcs/net45" +#I "../../../artifacts/bin/fcs/net461" (** Compiler Services: Notes on the FSharpChecker caches ================================================= diff --git a/fcs/docsrc/content/compiler.fsx b/fcs/docsrc/content/compiler.fsx index a934bc82094..c87f755ed35 100644 --- a/fcs/docsrc/content/compiler.fsx +++ b/fcs/docsrc/content/compiler.fsx @@ -1,5 +1,5 @@ (*** hide ***) -#I "../../../artifacts/bin/fcs/net45" +#I "../../../artifacts/bin/fcs/net461" (** Hosted Compiler =============== diff --git a/fcs/docsrc/content/corelib.fsx b/fcs/docsrc/content/corelib.fsx index 61c249d2ac5..4e175e95eec 100644 --- a/fcs/docsrc/content/corelib.fsx +++ b/fcs/docsrc/content/corelib.fsx @@ -1,5 +1,5 @@ (*** hide ***) -#I "../../../artifacts/bin/fcs/net45" +#I "../../../artifacts/bin/fcs/net461" (** Compiler Services: Notes on FSharp.Core.dll ================================================= diff --git a/fcs/docsrc/content/editor.fsx b/fcs/docsrc/content/editor.fsx index 70b6abff459..b8af9d0117b 100644 --- a/fcs/docsrc/content/editor.fsx +++ b/fcs/docsrc/content/editor.fsx @@ -1,5 +1,5 @@ (*** hide ***) -#I "../../../artifacts/bin/fcs/net45" +#I "../../../artifacts/bin/fcs/net461" (** Compiler Services: Editor services ================================== diff --git a/fcs/docsrc/content/filesystem.fsx b/fcs/docsrc/content/filesystem.fsx index 6c968803bbe..6c4d973d497 100644 --- a/fcs/docsrc/content/filesystem.fsx +++ b/fcs/docsrc/content/filesystem.fsx @@ -1,5 +1,5 @@ (*** hide ***) -#I "../../../artifacts/bin/fcs/net45" +#I "../../../artifacts/bin/fcs/net461" (** Compiler Services: Virtualized File System ========================================== diff --git a/fcs/docsrc/content/interactive.fsx b/fcs/docsrc/content/interactive.fsx index 94a004b36fd..301f77f34e3 100644 --- a/fcs/docsrc/content/interactive.fsx +++ b/fcs/docsrc/content/interactive.fsx @@ -1,5 +1,5 @@ (*** hide ***) -#I "../../../artifacts/bin/fcs/net45" +#I "../../../artifacts/bin/fcs/net461" (** Interactive Service: Embedding F# Interactive ============================================= diff --git a/fcs/docsrc/content/ja/compiler.fsx b/fcs/docsrc/content/ja/compiler.fsx index db49ab825d0..788c715294f 100644 --- a/fcs/docsrc/content/ja/compiler.fsx +++ b/fcs/docsrc/content/ja/compiler.fsx @@ -1,5 +1,5 @@ (*** hide ***) -#I "../../../../artifacts/bin/fcs/net45" +#I "../../../../artifacts/bin/fcs/net461" (** コンパイラã®çµ„ã¿è¾¼ã¿ ==================== diff --git a/fcs/docsrc/content/ja/corelib.fsx b/fcs/docsrc/content/ja/corelib.fsx index fc47377cfaa..4dcd09e1154 100644 --- a/fcs/docsrc/content/ja/corelib.fsx +++ b/fcs/docsrc/content/ja/corelib.fsx @@ -1,5 +1,5 @@ (*** hide ***) -#I "../../../../artifacts/bin/fcs/net45" +#I "../../../../artifacts/bin/fcs/net461" (** コンパイラサービス: FSharp.Core.dll ã«ã¤ã„ã¦ã®ãƒ¡ãƒ¢ ================================================== diff --git a/fcs/docsrc/content/ja/editor.fsx b/fcs/docsrc/content/ja/editor.fsx index 439791d3c5e..f8a33e9a75a 100644 --- a/fcs/docsrc/content/ja/editor.fsx +++ b/fcs/docsrc/content/ja/editor.fsx @@ -1,5 +1,5 @@ (*** hide ***) -#I "../../../../artifacts/bin/fcs/net45" +#I "../../../../artifacts/bin/fcs/net461" (** コンパイラサービス: エディタサービス ==================================== diff --git a/fcs/docsrc/content/ja/filesystem.fsx b/fcs/docsrc/content/ja/filesystem.fsx index 453a145ebaf..6a75cb61961 100644 --- a/fcs/docsrc/content/ja/filesystem.fsx +++ b/fcs/docsrc/content/ja/filesystem.fsx @@ -1,5 +1,5 @@ (*** hide ***) -#I "../../../../artifacts/bin/fcs/net45" +#I "../../../../artifacts/bin/fcs/net461" (** コンパイラサービス: ファイルシステム仮想化 ========================================== diff --git a/fcs/docsrc/content/ja/interactive.fsx b/fcs/docsrc/content/ja/interactive.fsx index c67b5f27464..59bae44f01b 100644 --- a/fcs/docsrc/content/ja/interactive.fsx +++ b/fcs/docsrc/content/ja/interactive.fsx @@ -1,5 +1,5 @@ (*** hide ***) -#I "../../../../artifacts/bin/fcs/net45" +#I "../../../../artifacts/bin/fcs/net461" (** インタラクティブサービス: F# Interactiveã®çµ„ã¿è¾¼ã¿ ================================================== diff --git a/fcs/docsrc/content/ja/project.fsx b/fcs/docsrc/content/ja/project.fsx index 0249107d9c4..8b70e3df5f7 100644 --- a/fcs/docsrc/content/ja/project.fsx +++ b/fcs/docsrc/content/ja/project.fsx @@ -1,5 +1,5 @@ (*** hide ***) -#I "../../../../artifacts/bin/fcs/net45" +#I "../../../../artifacts/bin/fcs/net461" (** コンパイラサービス: プロジェクトã®åˆ†æž ====================================== diff --git a/fcs/docsrc/content/ja/symbols.fsx b/fcs/docsrc/content/ja/symbols.fsx index c4a5097394e..ff62b0de6b2 100644 --- a/fcs/docsrc/content/ja/symbols.fsx +++ b/fcs/docsrc/content/ja/symbols.fsx @@ -1,5 +1,5 @@ (*** hide ***) -#I "../../../../artifacts/bin/fcs/net45" +#I "../../../../artifacts/bin/fcs/net461" (** コンパイラサービス: シンボルã®å‡¦ç† ================================== diff --git a/fcs/docsrc/content/ja/tokenizer.fsx b/fcs/docsrc/content/ja/tokenizer.fsx index 405bdef14ad..4daf29b7ead 100644 --- a/fcs/docsrc/content/ja/tokenizer.fsx +++ b/fcs/docsrc/content/ja/tokenizer.fsx @@ -1,5 +1,5 @@ (*** hide ***) -#I "../../../../artifacts/bin/fcs/net45" +#I "../../../../artifacts/bin/fcs/net461" (** コンパイラサービス:F#トークナイザを使用ã™ã‚‹ ============================================ diff --git a/fcs/docsrc/content/ja/untypedtree.fsx b/fcs/docsrc/content/ja/untypedtree.fsx index 54c78975025..447e3742fff 100644 --- a/fcs/docsrc/content/ja/untypedtree.fsx +++ b/fcs/docsrc/content/ja/untypedtree.fsx @@ -1,5 +1,5 @@ (*** hide ***) -#I "../../../../artifacts/bin/fcs/net45" +#I "../../../../artifacts/bin/fcs/net461" (** ã‚³ãƒ³ãƒ‘ã‚¤ãƒ©ã‚µãƒ¼ãƒ“ã‚¹ï¼šåž‹ç„¡ã—æ§‹æ–‡æœ¨ã®å‡¦ç† ====================================== diff --git a/fcs/docsrc/content/project.fsx b/fcs/docsrc/content/project.fsx index fc9439e6ad7..72bf7993f4b 100644 --- a/fcs/docsrc/content/project.fsx +++ b/fcs/docsrc/content/project.fsx @@ -1,5 +1,5 @@ (*** hide ***) -#I "../../../artifacts/bin/fcs/net45" +#I "../../../artifacts/bin/fcs/net461" (** Compiler Services: Project Analysis ================================== @@ -324,7 +324,7 @@ into the output folder of your application by the build process. If you install using Paket or NuGet, then this will be configured for you automatically. If not, you should reference the provided `.targets` file manually in your application. This can be found in the NuGet -package at `build/net45/FSharp.Compiler.Service.ProjectCrackerTool.targets`. +package at `build/net461/FSharp.Compiler.Service.ProjectCrackerTool.targets`. The reason for this split was so the analysis of an F# project file is performed out of process, in order that the necessary assembly diff --git a/fcs/docsrc/content/queue.fsx b/fcs/docsrc/content/queue.fsx index 31ac1526d6c..ccc7ccabbff 100644 --- a/fcs/docsrc/content/queue.fsx +++ b/fcs/docsrc/content/queue.fsx @@ -1,5 +1,5 @@ (*** hide ***) -#I "../../../artifacts/bin/fcs/net45" +#I "../../../artifacts/bin/fcs/net461" (** Compiler Services: Notes on the FSharpChecker operations queue ================================================= diff --git a/fcs/docsrc/content/react.fsx b/fcs/docsrc/content/react.fsx index 2dfa557238d..496e0fc9482 100644 --- a/fcs/docsrc/content/react.fsx +++ b/fcs/docsrc/content/react.fsx @@ -1,5 +1,5 @@ (*** hide ***) -#I "../../../artifacts/bin/fcs/net45" +#I "../../../artifacts/bin/fcs/net461" (** Compiler Services: Reacting to Changes ============================================ @@ -19,7 +19,7 @@ referenced DLLs may change on disk, or referenced files may change. The ``FSharpChecker`` component from FSharp.Compiler.Service does _not_ actively "listen" to changes in the file system. However ``FSharpChecker`` _does_ repeatedly ask for time stamps from the file system which it uses to decide if recomputation is needed. -FCS doesn’t listen for changes directly - for example, it creates no ``FileWatcher`` object (and the +FCS doesn�t listen for changes directly - for example, it creates no ``FileWatcher`` object (and the ``IFileSystem`` API has no ability to create such objects). This is partly for legacy reasons, and partly because some hosts forbid the creation of FileWatcher objects. @@ -33,7 +33,7 @@ stays up-to-date when changes are observed. If you want to more actively listen for changes, then you should add watchers for the files specified in the ``DependencyFiles`` property of ``FSharpCheckFileResults`` and ``FSharpCheckProjectResults``. -Here’s what you need to do: +Here�s what you need to do: * When your client notices an CHANGE event on a DependencyFile, it should schedule a refresh call to perform the ParseAndCheckFileInProject (or other operation) again. This will result in fresh FileSystem calls to compute time stamps. @@ -42,8 +42,8 @@ Here for all active projects in which the file occurs. This will result in fresh FileSystem calls to compute time stamps, and fresh calls to compute whether files exist. -* Generally clients don’t listen for DELETE events on files. Although it would be logically more consistent - to do so, in practice it’s very irritating for a "project clean" to invalidate all intellisense and +* Generally clients don�t listen for DELETE events on files. Although it would be logically more consistent + to do so, in practice it�s very irritating for a "project clean" to invalidate all intellisense and cause lots of red squiggles. Some source control tools also make a change by removing and adding files, which is best noticed as a single change event. diff --git a/fcs/docsrc/content/symbols.fsx b/fcs/docsrc/content/symbols.fsx index 60eb199f990..74701e8b73d 100644 --- a/fcs/docsrc/content/symbols.fsx +++ b/fcs/docsrc/content/symbols.fsx @@ -1,5 +1,5 @@ (*** hide ***) -#I "../../../artifacts/bin/fcs/net45" +#I "../../../artifacts/bin/fcs/net461" (** Compiler Services: Working with symbols ============================================ diff --git a/fcs/docsrc/content/tokenizer.fsx b/fcs/docsrc/content/tokenizer.fsx index f562c8b0574..7a46a3c91f6 100644 --- a/fcs/docsrc/content/tokenizer.fsx +++ b/fcs/docsrc/content/tokenizer.fsx @@ -1,5 +1,5 @@ (*** hide ***) -#I "../../../artifacts/bin/fcs/net45" +#I "../../../artifacts/bin/fcs/net461" (** Compiler Services: Using the F# tokenizer ========================================= diff --git a/fcs/docsrc/content/typedtree.fsx b/fcs/docsrc/content/typedtree.fsx index b5d20b4dab3..43bb55ba730 100644 --- a/fcs/docsrc/content/typedtree.fsx +++ b/fcs/docsrc/content/typedtree.fsx @@ -1,5 +1,5 @@ (*** hide ***) -#I "../../../artifacts/bin/fcs/net45" +#I "../../../artifacts/bin/fcs/net461" (** Compiler Services: Processing typed expression tree ================================================= diff --git a/fcs/docsrc/content/untypedtree.fsx b/fcs/docsrc/content/untypedtree.fsx index 4dd89a8d8a9..959e14fb944 100644 --- a/fcs/docsrc/content/untypedtree.fsx +++ b/fcs/docsrc/content/untypedtree.fsx @@ -1,5 +1,5 @@ (*** hide ***) -#I "../../../artifacts/bin/fcs/net45" +#I "../../../artifacts/bin/fcs/net461" (** Compiler Services: Processing untyped syntax tree ================================================= diff --git a/fcs/docsrc/tools/generate.fsx b/fcs/docsrc/tools/generate.fsx index 000f25f6a47..3ef4b0a1bde 100644 --- a/fcs/docsrc/tools/generate.fsx +++ b/fcs/docsrc/tools/generate.fsx @@ -32,7 +32,7 @@ open FSharp.MetadataFormat let root = "." // Paths with template/source/output locations -let bin = __SOURCE_DIRECTORY__ @@ "../../../release/fcs/net45" +let bin = __SOURCE_DIRECTORY__ @@ "../../../release/fcs/net461" let content = __SOURCE_DIRECTORY__ @@ "../content" let output = __SOURCE_DIRECTORY__ @@ "../../../docs" let files = __SOURCE_DIRECTORY__ @@ "../files" diff --git a/fcs/docsrc/tools/generate.ja.fsx b/fcs/docsrc/tools/generate.ja.fsx index feaeb592d35..bf9f77ce99e 100644 --- a/fcs/docsrc/tools/generate.ja.fsx +++ b/fcs/docsrc/tools/generate.ja.fsx @@ -18,9 +18,9 @@ let info = // For typical project, no changes are needed below // -------------------------------------------------------------------------------------- -#I "../../packages/FSharpVSPowerTools.Core/lib/net45" +#I "../../packages/FSharpVSPowerTools.Core/lib/net461" #I "../../packages/FSharp.Formatting/lib/net40" -#I "../../packages/FSharp.Compiler.Service/lib/net45" +#I "../../packages/FSharp.Compiler.Service/lib/net461" #I "../../packages/FAKE/tools" #r "FSharpVSPowerTools.Core.dll" #r "System.Web.Razor.dll" @@ -41,7 +41,7 @@ open FSharp.MetadataFormat let root = "." // Paths with template/source/output locations -let bin = __SOURCE_DIRECTORY__ @@ "../../../release/fcs/net45" +let bin = __SOURCE_DIRECTORY__ @@ "../../../release/fcs/net461" let content = __SOURCE_DIRECTORY__ @@ "../content/ja" let outputJa = __SOURCE_DIRECTORY__ @@ "../../../docs/ja" let files = __SOURCE_DIRECTORY__ @@ "../files" diff --git a/fcs/paket.dependencies b/fcs/paket.dependencies index ccaead9f031..1ca82af8c87 100644 --- a/fcs/paket.dependencies +++ b/fcs/paket.dependencies @@ -1,4 +1,4 @@ -framework: net45, net46 +framework: net461 source https://www.nuget.org/api/v2/ diff --git a/fcs/paket.lock b/fcs/paket.lock index 1ead25b452a..8871d61813e 100644 --- a/fcs/paket.lock +++ b/fcs/paket.lock @@ -1,7 +1,7 @@ -RESTRICTION: || (== net45) (== net46) +RESTRICTION: == net461 NUGET remote: https://www.nuget.org/api/v2 - FAKE (4.64.6) + FAKE (5.8.4) FSharp.Compiler.Service (2.0.0.6) FSharp.Formatting (2.14.4) FSharp.Compiler.Service (2.0.0.6) From 8b336e7568b1cb02fc43c6962e93744616e99864 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 28 Mar 2019 12:02:58 +0000 Subject: [PATCH 11/77] update FCS dependencies --- fcs/paket.dependencies | 2 +- fcs/paket.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fcs/paket.dependencies b/fcs/paket.dependencies index 1ca82af8c87..284a402166f 100644 --- a/fcs/paket.dependencies +++ b/fcs/paket.dependencies @@ -2,5 +2,5 @@ framework: net461 source https://www.nuget.org/api/v2/ -nuget FAKE +nuget FAKE 4.64.6 nuget FSharp.Formatting diff --git a/fcs/paket.lock b/fcs/paket.lock index 8871d61813e..908c7de8d1f 100644 --- a/fcs/paket.lock +++ b/fcs/paket.lock @@ -1,7 +1,7 @@ RESTRICTION: == net461 NUGET remote: https://www.nuget.org/api/v2 - FAKE (5.8.4) + FAKE (4.64.6) FSharp.Compiler.Service (2.0.0.6) FSharp.Formatting (2.14.4) FSharp.Compiler.Service (2.0.0.6) From 1cd2401aa0d37c84ebf7f8dd166abeef437dca3d Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 28 Mar 2019 12:31:51 +0000 Subject: [PATCH 12/77] fix up build --- .../FSharp.Compiler.Service.MSBuild.v12.fsproj | 2 +- ...FSharp.Compiler.Service.ProjectCracker.fsproj | 2 +- ...rp.Compiler.Service.ProjectCrackerTool.fsproj | 2 +- .../FSharp.Compiler.Service.Tests.fsproj | 6 +++--- fcs/build.fsx | 2 +- fcs/samples/EditorService/EditorService.fsproj | 6 +++--- fcs/samples/FscExe/FscExe.fsproj | 6 +++--- fcs/samples/FsiExe/FsiExe.fsproj | 6 +++--- .../InteractiveService/InteractiveService.fsproj | 6 +++--- fcs/samples/Tokenizer/Tokenizer.fsproj | 6 +++--- fcs/samples/UntypedTree/UntypedTree.fsproj | 6 +++--- src/absil/illib.fs | 8 -------- src/fsharp/NameResolution.fs | 2 +- src/fsharp/Optimizer.fs | 2 +- src/fsharp/QuotationTranslator.fs | 2 +- src/fsharp/symbols/Symbols.fs | 16 ++++++++-------- src/fsharp/tast.fs | 10 +++++++--- 17 files changed, 43 insertions(+), 47 deletions(-) diff --git a/fcs/FSharp.Compiler.Service.MSBuild.v12/FSharp.Compiler.Service.MSBuild.v12.fsproj b/fcs/FSharp.Compiler.Service.MSBuild.v12/FSharp.Compiler.Service.MSBuild.v12.fsproj index adf97c8c6a0..1c82ed8fcda 100644 --- a/fcs/FSharp.Compiler.Service.MSBuild.v12/FSharp.Compiler.Service.MSBuild.v12.fsproj +++ b/fcs/FSharp.Compiler.Service.MSBuild.v12/FSharp.Compiler.Service.MSBuild.v12.fsproj @@ -28,7 +28,7 @@ - + $(FSharpSourcesRoot)\..\fcs\dependencies\MSBuild.v12.0\Microsoft.Build.Framework.dll diff --git a/fcs/FSharp.Compiler.Service.ProjectCracker/FSharp.Compiler.Service.ProjectCracker.fsproj b/fcs/FSharp.Compiler.Service.ProjectCracker/FSharp.Compiler.Service.ProjectCracker.fsproj index cd4ef87393b..648f66924df 100644 --- a/fcs/FSharp.Compiler.Service.ProjectCracker/FSharp.Compiler.Service.ProjectCracker.fsproj +++ b/fcs/FSharp.Compiler.Service.ProjectCracker/FSharp.Compiler.Service.ProjectCracker.fsproj @@ -27,7 +27,7 @@ - + \ No newline at end of file diff --git a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCrackerTool.fsproj b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCrackerTool.fsproj index 7970d6d5a3b..648aacb3c21 100644 --- a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCrackerTool.fsproj +++ b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCrackerTool.fsproj @@ -23,7 +23,7 @@ - + $(FSharpSourcesRoot)\..\fcs\dependencies\MSBuild.v12.0\Microsoft.Build.Framework.dll false diff --git a/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj b/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj index edb85fcf648..85e345669c4 100644 --- a/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj +++ b/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj @@ -5,7 +5,7 @@ - net46;netcoreapp2.0 + net461;netcoreapp2.0 true $(NoWarn);44;75; true @@ -78,7 +78,7 @@ - + @@ -86,7 +86,7 @@ - + diff --git a/fcs/build.fsx b/fcs/build.fsx index 50735795d88..d1d575c4f76 100644 --- a/fcs/build.fsx +++ b/fcs/build.fsx @@ -31,7 +31,7 @@ let dotnetExePath = if File.Exists(pathToCli) then pathToCli else - DotNetCli.InstallDotNetSDK "2.1.504" + DotNetCli.InstallDotNetSDK "2.2.105" let runDotnet workingDir args = let result = diff --git a/fcs/samples/EditorService/EditorService.fsproj b/fcs/samples/EditorService/EditorService.fsproj index 447906070f0..25795d9299c 100644 --- a/fcs/samples/EditorService/EditorService.fsproj +++ b/fcs/samples/EditorService/EditorService.fsproj @@ -2,7 +2,7 @@ - net46;netcoreapp2.0 + net461;netcoreapp2.0 true Exe false @@ -12,11 +12,11 @@ - + - + diff --git a/fcs/samples/FscExe/FscExe.fsproj b/fcs/samples/FscExe/FscExe.fsproj index b2b146913a1..a160f690d2f 100644 --- a/fcs/samples/FscExe/FscExe.fsproj +++ b/fcs/samples/FscExe/FscExe.fsproj @@ -2,7 +2,7 @@ - net46 + net461 true Exe false @@ -14,10 +14,10 @@ - + - + diff --git a/fcs/samples/FsiExe/FsiExe.fsproj b/fcs/samples/FsiExe/FsiExe.fsproj index aae2ba03182..4ce18ab142c 100644 --- a/fcs/samples/FsiExe/FsiExe.fsproj +++ b/fcs/samples/FsiExe/FsiExe.fsproj @@ -2,7 +2,7 @@ - net46 + net461 true Exe false @@ -16,10 +16,10 @@ - + - + diff --git a/fcs/samples/InteractiveService/InteractiveService.fsproj b/fcs/samples/InteractiveService/InteractiveService.fsproj index 387439fcfdd..75686578f21 100644 --- a/fcs/samples/InteractiveService/InteractiveService.fsproj +++ b/fcs/samples/InteractiveService/InteractiveService.fsproj @@ -2,7 +2,7 @@ - net46 + net461 true Exe false @@ -12,10 +12,10 @@ - + - + diff --git a/fcs/samples/Tokenizer/Tokenizer.fsproj b/fcs/samples/Tokenizer/Tokenizer.fsproj index 387439fcfdd..75686578f21 100644 --- a/fcs/samples/Tokenizer/Tokenizer.fsproj +++ b/fcs/samples/Tokenizer/Tokenizer.fsproj @@ -2,7 +2,7 @@ - net46 + net461 true Exe false @@ -12,10 +12,10 @@ - + - + diff --git a/fcs/samples/UntypedTree/UntypedTree.fsproj b/fcs/samples/UntypedTree/UntypedTree.fsproj index 387439fcfdd..75686578f21 100644 --- a/fcs/samples/UntypedTree/UntypedTree.fsproj +++ b/fcs/samples/UntypedTree/UntypedTree.fsproj @@ -2,7 +2,7 @@ - net46 + net461 true Exe false @@ -12,10 +12,10 @@ - + - + diff --git a/src/absil/illib.fs b/src/absil/illib.fs index da0b39dfb1c..b05bcab5640 100644 --- a/src/absil/illib.fs +++ b/src/absil/illib.fs @@ -488,20 +488,12 @@ module ResizeArray = /// in order to prevent long-term storage of those values chunkBySize maxArrayItemCount f inp - -/// Because FSharp.Compiler.Service is a library that will target FSharp.Core 4.5.2 for the forseeable future, -/// we need to stick these functions in this module rather than using the module functions for ValueOption -/// that come after FSharp.Core 4.5.2. module ValueOptionInternal = let inline ofOption x = match x with Some x -> ValueSome x | None -> ValueNone let inline bind f x = match x with ValueSome x -> f x | ValueNone -> ValueNone - let inline isSome x = match x with ValueSome _ -> true | ValueNone -> false - - let inline isNone x = match x with ValueSome _ -> false | ValueNone -> true - type String with member inline x.StartsWithOrdinal(value) = x.StartsWith(value, StringComparison.Ordinal) diff --git a/src/fsharp/NameResolution.fs b/src/fsharp/NameResolution.fs index ff9dbbe52e2..872109989a7 100644 --- a/src/fsharp/NameResolution.fs +++ b/src/fsharp/NameResolution.fs @@ -1100,7 +1100,7 @@ let AddEntityForProvidedType (amap: Import.ImportMap, modref: ModuleOrNamespaceR let tycon = Construct.NewProvidedTycon(resolutionEnvironment, st, importProvidedType, isSuppressRelocate, m) modref.ModuleOrNamespaceType.AddProvidedTypeEntity(tycon) let tcref = modref.NestedTyconRef tycon - System.Diagnostics.Debug.Assert(ValueOptionInternal.isSome modref.TryDeref) + System.Diagnostics.Debug.Assert(modref.TryDeref.IsSome) tcref diff --git a/src/fsharp/Optimizer.fs b/src/fsharp/Optimizer.fs index 250fda33d06..769c3e5c4ae 100644 --- a/src/fsharp/Optimizer.fs +++ b/src/fsharp/Optimizer.fs @@ -3187,7 +3187,7 @@ and OptimizeBinding cenv isRec env (TBind(vref, expr, spBind)) = | None -> false | Some mbrTyconRef -> // Check we can deref system_MarshalByRefObject_tcref. When compiling against the Silverlight mscorlib we can't - if ValueOptionInternal.isSome mbrTyconRef.TryDeref then + if mbrTyconRef.TryDeref.IsSome then // Check if this is a subtype of MarshalByRefObject assert (cenv.g.system_MarshalByRefObject_ty.IsSome) ExistsSameHeadTypeInHierarchy cenv.g cenv.amap vref.Range (generalizedTyconRef tcref) cenv.g.system_MarshalByRefObject_ty.Value diff --git a/src/fsharp/QuotationTranslator.fs b/src/fsharp/QuotationTranslator.fs index 6166906244f..cd71d0b7598 100644 --- a/src/fsharp/QuotationTranslator.fs +++ b/src/fsharp/QuotationTranslator.fs @@ -66,7 +66,7 @@ type QuotationGenerationScope = static member ComputeQuotationFormat g = let deserializeExValRef = ValRefForIntrinsic g.deserialize_quoted_FSharp_40_plus_info - if ValueOptionInternal.isSome deserializeExValRef.TryDeref then + if deserializeExValRef.TryDeref.IsSome then QuotationSerializationFormat.FSharp_40_Plus else QuotationSerializationFormat.FSharp_20_Plus diff --git a/src/fsharp/symbols/Symbols.fs b/src/fsharp/symbols/Symbols.fs index 7adcdfbee4e..e55e073e07e 100644 --- a/src/fsharp/symbols/Symbols.fs +++ b/src/fsharp/symbols/Symbols.fs @@ -86,7 +86,7 @@ module Impl = let entityIsUnresolved(entity:EntityRef) = match entity with | ERefNonLocal(NonLocalEntityRef(ccu, _)) -> - ccu.IsUnresolvedReference && ValueOptionInternal.isNone entity.TryDeref + ccu.IsUnresolvedReference && entity.TryDeref.IsNone | _ -> false let checkEntityIsResolved(entity:EntityRef) = @@ -759,11 +759,11 @@ and FSharpUnionCase(cenv, v: UnionCaseRef) = let isUnresolved() = - entityIsUnresolved v.TyconRef || ValueOptionInternal.isNone v.TryUnionCase + entityIsUnresolved v.TyconRef || v.TryUnionCase.IsNone let checkIsResolved() = checkEntityIsResolved v.TyconRef - if ValueOptionInternal.isNone v.TryUnionCase then + if v.TryUnionCase.IsNone then invalidOp (sprintf "The union case '%s' could not be found in the target type" v.CaseName) member __.IsUnresolved = @@ -878,8 +878,8 @@ and FSharpField(cenv: SymbolEnv, d: FSharpFieldData) = d.TryDeclaringTyconRef |> Option.exists entityIsUnresolved || match d with | AnonField _ -> false - | RecdOrClass v -> ValueOptionInternal.isNone v.TryRecdField - | Union (v, _) -> ValueOptionInternal.isNone v.TryUnionCase + | RecdOrClass v -> v.TryRecdField.IsNone + | Union (v, _) -> v.TryUnionCase.IsNone | ILField _ -> false let checkIsResolved() = @@ -887,10 +887,10 @@ and FSharpField(cenv: SymbolEnv, d: FSharpFieldData) = match d with | AnonField _ -> () | RecdOrClass v -> - if ValueOptionInternal.isNone v.TryRecdField then + if v.TryRecdField.IsNone then invalidOp (sprintf "The record field '%s' could not be found in the target type" v.FieldName) | Union (v, _) -> - if ValueOptionInternal.isNone v.TryUnionCase then + if v.TryUnionCase.IsNone then invalidOp (sprintf "The union case '%s' could not be found in the target type" v.CaseName) | ILField _ -> () @@ -1382,7 +1382,7 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) = let isUnresolved() = match fsharpInfo() with | None -> false - | Some v -> ValueOptionInternal.isNone v.TryDeref + | Some v -> v.TryDeref.IsNone let checkIsResolved() = if isUnresolved() then diff --git a/src/fsharp/tast.fs b/src/fsharp/tast.fs index 687c81ce145..766bff82f6b 100644 --- a/src/fsharp/tast.fs +++ b/src/fsharp/tast.fs @@ -3309,7 +3309,7 @@ and ValueSome tcr.binding /// Is the destination assembly available? - member tcr.CanDeref = ValueOptionInternal.isSome tcr.TryDeref + member tcr.CanDeref = tcr.TryDeref.IsSome /// Gets the data indicating the compiled representation of a type or module in terms of Abstract IL data structures. member x.CompiledRepresentation = x.Deref.CompiledRepresentation @@ -3860,7 +3860,9 @@ and | None -> error(InternalError(sprintf "union case %s not found in type %s" x.CaseName x.TyconRef.LogicalName, x.TyconRef.Range)) /// Try to dereference the reference - member x.TryUnionCase = x.TyconRef.TryDeref |> ValueOptionInternal.bind (fun tcref -> tcref.GetUnionCaseByName x.CaseName |> ValueOptionInternal.ofOption) + member x.TryUnionCase = + x.TyconRef.TryDeref + |> ValueOptionInternal.bind (fun tcref -> tcref.GetUnionCaseByName x.CaseName |> ValueOptionInternal.ofOption) /// Get the attributes associated with the union case member x.Attribs = x.UnionCase.Attribs @@ -3919,7 +3921,9 @@ and | None -> error(InternalError(sprintf "field %s not found in type %s" id tcref.LogicalName, tcref.Range)) /// Try to dereference the reference - member x.TryRecdField = x.TyconRef.TryDeref |> ValueOptionInternal.bind (fun tcref -> tcref.GetFieldByName x.FieldName |> ValueOptionInternal.ofOption) + member x.TryRecdField = + x.TyconRef.TryDeref + |> ValueOptionInternal.bind (fun tcref -> tcref.GetFieldByName x.FieldName |> ValueOptionInternal.ofOption) /// Get the attributes associated with the compiled property of the record field member x.PropertyAttribs = x.RecdField.PropertyAttribs From c15c030bb9ac7246e29ae93e82fb77bfdc5d5090 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 28 Mar 2019 12:38:15 +0000 Subject: [PATCH 13/77] fix build --- eng/build-utils.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/build-utils.ps1 b/eng/build-utils.ps1 index d4f2b625f2b..845169db12a 100644 --- a/eng/build-utils.ps1 +++ b/eng/build-utils.ps1 @@ -242,8 +242,8 @@ function Make-BootstrapBuild() { # prepare FsLex and Fsyacc Run-MSBuild "$RepoRoot\src\buildtools\buildtools.proj" "/restore /t:Build" -logFileName "BuildTools" -configuration $bootstrapConfiguration - Copy-Item "$ArtifactsDir\bin\fslex\$bootstrapConfiguration\$coreclrTargetFramework\*" -Destination $dir - Copy-Item "$ArtifactsDir\bin\fsyacc\$bootstrapConfiguration\$coreclrTargetFramework\*" -Destination $dir + Copy-Item "$ArtifactsDir\bin\fslex\$bootstrapConfiguration\netcoreapp2.0\*" -Destination $dir + Copy-Item "$ArtifactsDir\bin\fsyacc\$bootstrapConfiguration\netcoreapp2.0\*" -Destination $dir # prepare compiler $projectPath = "$RepoRoot\proto.proj" From 9d61ee7e4ef40267ecb178212a6193caf42aedc1 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 28 Mar 2019 17:39:22 +0000 Subject: [PATCH 14/77] update tfms for type providers --- .../ProductVersion.fs | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/FSharp.Compiler.UnitTests/ProductVersion.fs b/tests/FSharp.Compiler.UnitTests/ProductVersion.fs index fe95e82a977..462f621941d 100644 --- a/tests/FSharp.Compiler.UnitTests/ProductVersion.fs +++ b/tests/FSharp.Compiler.UnitTests/ProductVersion.fs @@ -93,21 +93,21 @@ module TypeProviderDesignTimeComponentLoading = let ``check tooling paths for type provider design time component loading`` () = let expected = [ -#if NET46 // only available on net46 - Path.Combine("typeproviders", "fsharp41", "net461") - Path.Combine("tools", "fsharp41", "net461") - Path.Combine("typeproviders", "fsharp41", "net452") - Path.Combine("tools", "fsharp41", "net452") - Path.Combine("typeproviders", "fsharp41", "net451") - Path.Combine("tools", "fsharp41", "net451") - Path.Combine("typeproviders", "fsharp41", "net45") - Path.Combine("tools", "fsharp41", "net45") -#else // only available on netcoreapp2.0 - Path.Combine("typeproviders", "fsharp41", "netcoreapp2.0") - Path.Combine("tools", "fsharp41", "netcoreapp2.0") -#endif // available in both - Path.Combine("typeproviders", "fsharp41", "netstandard2.0") - Path.Combine("tools", "fsharp41", "netstandard2.0") +#if NET46 + // only searched when executing on .NET Framework + for tfm in ["net48"; "net472"; "net471"; "net47"; "net462"; "net461"; "net452"; "net451"; "net45"] do + yield Path.Combine("typeproviders", "fsharp41", tfm) + yield Path.Combine("tools", "fsharp41", tfm) +#else + // only searched when executing on .NET Core + for tfm in ["netcoreapp2.1"; "netcoreapp2.0"] do + yield Path.Combine("typeproviders", "fsharp41", tfm) + yield Path.Combine("tools", "fsharp41", tfm) +#endif + // always searched + for tfm in ["netstandard2.0"] do + yield Path.Combine("typeproviders", "fsharp41", tfm) + yield Path.Combine("tools", "fsharp41", tfm) ] let actual = FSharp.Compiler.ExtensionTyping.toolingCompatiblePaths() printfn "actual = %A" actual From 08d89c70db7bb6f96586613caab69bd634a27120 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 28 Mar 2019 19:25:02 +0000 Subject: [PATCH 15/77] verbose build --- .vsts-pr.yaml | 6 +++--- eng/Build.ps1 | 1 + eng/build.sh | 3 +++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.vsts-pr.yaml b/.vsts-pr.yaml index b7d3862888d..b0186db4e1e 100644 --- a/.vsts-pr.yaml +++ b/.vsts-pr.yaml @@ -11,7 +11,7 @@ jobs: _configuration: Release _testKind: testcoreclr steps: - - script: ./eng/cibuild.sh --configuration $(_configuration) --$(_testKind) + - script: ./eng/cibuild.sh --configuration $(_configuration) --$(_testKind) --verbosity normal - task: PublishBuildArtifacts@1 displayName: Publish Build Logs inputs: @@ -55,7 +55,7 @@ jobs: _configuration: Release _testKind: testcoreclr steps: - - script: ./eng/cibuild.sh --configuration $(_configuration) --$(_testKind) + - script: ./eng/cibuild.sh --configuration $(_configuration) --$(_testKind) --verbosity normal - task: PublishBuildArtifacts@1 displayName: Publish Build Logs inputs: @@ -108,7 +108,7 @@ jobs: _configuration: Release _testKind: testVs steps: - - script: eng\CIBuild.cmd -configuration $(_configuration) -$(_testKind) + - script: eng\CIBuild.cmd -configuration $(_configuration) -$(_testKind) -verbosity normal - task: PublishBuildArtifacts@1 displayName: Publish Build Logs inputs: diff --git a/eng/Build.ps1 b/eng/Build.ps1 index 04afc1b1d46..72a664f1715 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -157,6 +157,7 @@ function BuildSolution() { /p:QuietRestore=$quietRestore ` /p:QuietRestoreBinaryLog=$binaryLog ` /p:TestTargetFrameworks=$testTargetFrameworks ` + /v:$verbosity ` $suppressExtensionDeployment ` @properties } diff --git a/eng/build.sh b/eng/build.sh index bae5b6a45f7..a7c055e7cae 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -211,6 +211,7 @@ function BuildSolution { bootstrap_config=Proto MSBuild "$repo_root/src/buildtools/buildtools.proj" \ /restore \ + /v:$verbosity \ /p:Configuration=$bootstrap_config \ /t:Build @@ -221,6 +222,7 @@ function BuildSolution { MSBuild "$repo_root/proto.proj" \ /restore \ + /v:$verbosity \ /p:Configuration=$bootstrap_config \ /t:Build @@ -229,6 +231,7 @@ function BuildSolution { # do real build MSBuild $toolset_build_proj \ $bl \ + /v:$verbosity \ /p:Configuration=$configuration \ /p:Projects="$projects" \ /p:RepoRoot="$repo_root" \ From 9416ec5f8f7f8f241f012881098f4bfa8cb72885 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 28 Mar 2019 20:39:20 +0000 Subject: [PATCH 16/77] precise witnesses --- src/fsharp/ConstraintSolver.fs | 2 +- src/fsharp/ConstraintSolver.fsi | 2 +- src/fsharp/FSharp.Core/prim-types.fs | 674 ++++++++++++++++++++++++--- src/fsharp/IlxGen.fs | 2 +- src/fsharp/MethodCalls.fs | 61 ++- src/fsharp/Optimizer.fs | 2 +- src/fsharp/TastOps.fs | 4 +- src/fsharp/TastOps.fsi | 4 +- src/fsharp/symbols/Exprs.fs | 4 +- src/fsharp/tast.fs | 7 + 10 files changed, 694 insertions(+), 68 deletions(-) diff --git a/src/fsharp/ConstraintSolver.fs b/src/fsharp/ConstraintSolver.fs index fd5c12d5e70..752cdf1d354 100644 --- a/src/fsharp/ConstraintSolver.fs +++ b/src/fsharp/ConstraintSolver.fs @@ -2759,7 +2759,7 @@ let CreateCodegenState tcVal g amap = ExtraCxs = HashMultiMap(10, HashIdentity.Structural) InfoReader = new InfoReader(g, amap) } -let CodegenWitnessThatTypeSupportsTraitConstraint tcVal g amap m (traitInfo:TraitConstraintInfo) argExprs = trackErrors { +let CodegenWitnessForTraitConstraint tcVal g amap m (traitInfo:TraitConstraintInfo) argExprs = trackErrors { let css = CreateCodegenState tcVal g amap let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m (DisplayEnv.Empty g) let! _res = SolveMemberConstraint csenv true true 0 m NoTrace traitInfo diff --git a/src/fsharp/ConstraintSolver.fsi b/src/fsharp/ConstraintSolver.fsi index 92c642889bd..b648a29113a 100644 --- a/src/fsharp/ConstraintSolver.fsi +++ b/src/fsharp/ConstraintSolver.fsi @@ -140,7 +140,7 @@ val AddCxTypeIsUnmanaged : DisplayEnv -> ConstraintSolverSt val AddCxTypeIsEnum : DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> TType -> unit val AddCxTypeIsDelegate : DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> TType -> TType -> unit -val CodegenWitnessThatTypeSupportsTraitConstraint : TcValF -> TcGlobals -> ImportMap -> range -> TraitConstraintInfo -> Expr list -> OperationResult +val CodegenWitnessForTraitConstraint : TcValF -> TcGlobals -> ImportMap -> range -> TraitConstraintInfo -> Expr list -> OperationResult val CodegenWitnessesForTyparInst : TcValF -> TcGlobals -> ImportMap -> range -> Typars -> TType list -> OperationResult diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 4f98ac972e8..d677b18076c 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -468,6 +468,7 @@ namespace Microsoft.FSharp.Core let inline iscastPrim<'T when 'T : not struct>(x:obj) = (# "isinst !0" type ('T) x : 'T #) + let inline mask (n:int) (m:int) = (# "and" n m : int #) open BasicInlinedOperations @@ -475,7 +476,6 @@ namespace Microsoft.FSharp.Core module TupleUtils = // adapted from System.Tuple::CombineHashCodes - let inline mask (n:int) (m:int) = (# "and" n m : int #) let inline opshl (x:int) (n:int) : int = (# "shl" x (mask n 31) : int #) let inline opxor (x:int) (y:int) : int = (# "xor" x y : int32 #) let inline combineTupleHashes (h1 : int) (h2 : int) = (opxor ((opshl h1 5) + h1) h2) @@ -2454,6 +2454,601 @@ namespace Microsoft.FSharp.Core | 'o' -> parseOctalUInt64 s p l | _ -> UInt64.Parse(s.Substring(p), NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture) + type BuiltInPrimitives = + static member inline op_Addition(x: int32, y: int32) = (# "add" x y : int32 #) + static member inline op_Addition(x: float, y: float) = (# "add" x y : float #) + static member inline op_Addition(x: float32, y: float32) = (# "add" x y : float32 #) + static member inline op_Addition(x: int64, y: int64) = (# "add" x y : int64 #) + static member inline op_Addition(x: uint64, y: uint64) = (# "add" x y : uint64 #) + static member inline op_Addition(x: uint32, y: uint32) = (# "add" x y : uint32 #) + static member inline op_Addition(x: nativeint, y: nativeint) = (# "add" x y : nativeint #) + static member inline op_Addition(x: unativeint, y: unativeint) = (# "add" x y : unativeint #) + static member inline op_Addition(x: int16, y: int16) = (# "conv.i2" (# "add" x y : int32 #) : int16 #) + static member inline op_Addition(x: uint16, y: uint16) = (# "conv.u2" (# "add" x y : uint32 #) : uint16 #) + static member inline op_Addition(x: char, y: char) = (# "conv.u2" (# "add" x y : uint32 #) : char #) + static member inline op_Addition(x: sbyte, y: sbyte) = (# "conv.i1" (# "add" x y : int32 #) : sbyte #) + static member inline op_Addition(x: byte, y: byte) = (# "conv.u1" (# "add" x y : uint32 #) : byte #) + static member inline op_Addition(x: string, y: string) = String.Concat(x, y) + static member inline op_Addition(x: decimal, y: decimal) = Decimal.op_Addition(x, y) + + static member inline op_Multiply(x: int32, y: int32) = (# "mul" x y : int32 #) + static member inline op_Multiply(x: float, y: float) = (# "mul" x y : float #) + static member inline op_Multiply(x: float32, y: float32) = (# "mul" x y : float32 #) + static member inline op_Multiply(x: int64, y: int64) = (# "mul" x y : int64 #) + static member inline op_Multiply(x: uint64, y: uint64) = (# "mul" x y : uint64 #) + static member inline op_Multiply(x: uint32, y: uint32) = (# "mul" x y : uint32 #) + static member inline op_Multiply(x: nativeint, y: nativeint) = (# "mul" x y : nativeint #) + static member inline op_Multiply(x: unativeint, y: unativeint) = (# "mul" x y : unativeint #) + static member inline op_Multiply(x: int16, y: int16) = (# "conv.i2" (# "mul" x y : int32 #) : int16 #) + static member inline op_Multiply(x: uint16, y: uint16) = (# "conv.u2" (# "mul" x y : uint32 #) : uint16 #) + static member inline op_Multiply(x: sbyte, y: sbyte) = (# "conv.i1" (# "mul" x y : int32 #) : sbyte #) + static member inline op_Multiply(x: byte, y: byte) = (# "conv.u1" (# "mul" x y : uint32 #) : byte #) + static member inline op_Multiply(x: decimal, y: decimal) = Decimal.op_Multiply(x, y) + + static member inline op_UnaryNegation(x: int32) = (# "neg" x : int32 #) + static member inline op_UnaryNegation(x: float) = (# "neg" x : float #) + static member inline op_UnaryNegation(x: float32) = (# "neg" x : float32 #) + static member inline op_UnaryNegation(x: int64) = (# "neg" x : int64 #) + static member inline op_UnaryNegation(x: int16) = (# "neg" x : int16 #) + static member inline op_UnaryNegation(x: nativeint) = (# "neg" x : nativeint #) + static member inline op_UnaryNegation(x: sbyte) = (# "neg" x : sbyte #) + static member inline op_UnaryNegation(x: decimal) = Decimal.op_UnaryNegation(x) + + static member inline op_Subtraction(x: int32, y: int32) = (# "sub" x y : int32 #) + static member inline op_Subtraction(x: float, y: float) = (# "sub" x y : float #) + static member inline op_Subtraction(x: float32, y: float32) = (# "sub" x y : float32 #) + static member inline op_Subtraction(x: int64, y: int64) = (# "sub" x y : int64 #) + static member inline op_Subtraction(x: uint64, y: uint64) = (# "sub" x y : uint64 #) + static member inline op_Subtraction(x: uint32, y: uint32) = (# "sub" x y : uint32 #) + static member inline op_Subtraction(x: nativeint, y: nativeint) = (# "sub" x y : nativeint #) + static member inline op_Subtraction(x: unativeint, y: unativeint) = (# "sub" x y : unativeint #) + static member inline op_Subtraction(x: int16, y: int16) = (# "conv.i2" (# "sub" x y : int32 #) : int16 #) + static member inline op_Subtraction(x: uint16, y: uint16) = (# "conv.u2" (# "sub" x y : uint32 #) : uint16 #) + static member inline op_Subtraction(x: sbyte, y: sbyte) = (# "conv.i1" (# "sub" x y : int32 #) : sbyte #) + static member inline op_Subtraction(x: byte, y: byte) = (# "conv.u1" (# "sub" x y : uint32 #) : byte #) + static member inline op_Subtraction(x: decimal, y: decimal) = Decimal.op_Subtraction(x, y) + + static member inline op_Division(x: int32, y: int32) = (# "div" x y : int32 #) + static member inline op_Division(x: float, y: float) = (# "div" x y : float #) + static member inline op_Division(x: float32, y: float32) = (# "div" x y : float32 #) + static member inline op_Division(x: int64, y: int64) = (# "div" x y : int64 #) + static member inline op_Division(x: uint64, y: uint64) = (# "div.un" x y : uint64 #) + static member inline op_Division(x: uint32, y: uint32) = (# "div.un" x y : uint32 #) + static member inline op_Division(x: nativeint, y: nativeint) = (# "div" x y : nativeint #) + static member inline op_Division(x: unativeint, y: unativeint) = (# "div.un" x y : unativeint #) + static member inline op_Division(x: int16, y: int16) = (# "conv.i2" (# "div" x y : int32 #) : int16 #) + static member inline op_Division(x: uint16, y: uint16) = (# "conv.u2" (# "div.un" x y : uint32 #) : uint16 #) + static member inline op_Division(x: sbyte, y: sbyte) = (# "conv.i1" (# "div" x y : int32 #) : sbyte #) + static member inline op_Division(x: byte, y: byte) = (# "conv.u1" (# "div.un" x y : uint32 #) : byte #) + static member inline op_Division(x: decimal, y: decimal) = Decimal.op_Division(x, y) + + static member inline op_Modulus(x: int32, y: int32) = (# "rem" x y : int32 #) + static member inline op_Modulus(x: float, y: float) = (# "rem" x y : float #) + static member inline op_Modulus(x: float32, y: float32) = (# "rem" x y : float32 #) + static member inline op_Modulus(x: int64, y: int64) = (# "rem" x y : int64 #) + static member inline op_Modulus(x: uint64, y: uint64) = (# "rem.un" x y : uint64 #) + static member inline op_Modulus(x: uint32, y: uint32) = (# "rem.un" x y : uint32 #) + static member inline op_Modulus(x: nativeint, y: nativeint) = (# "rem" x y : nativeint #) + static member inline op_Modulus(x: unativeint, y: unativeint) = (# "rem.un" x y : unativeint #) + static member inline op_Modulus(x: int16, y: int16) = (# "conv.i2" (# "rem" x y : int32 #) : int16 #) + static member inline op_Modulus(x: uint16, y: uint16) = (# "conv.u2" (# "rem.un" x y : uint32 #) : uint16 #) + static member inline op_Modulus(x: sbyte, y: sbyte) = (# "conv.i1" (# "rem" x y : int32 #) : sbyte #) + static member inline op_Modulus(x: byte, y: byte) = (# "conv.u1" (# "rem.un" x y : uint32 #) : byte #) + static member inline op_Modulus(x: decimal, y: decimal) = Decimal.op_Modulus(x, y) + + static member inline op_LeftShift(value: int32, shift: int32) = (# "shl" value (mask shift 31) : int #) + static member inline op_LeftShift(value: uint32, shift: int32) = (# "shl" value (mask shift 31) : uint32 #) + static member inline op_LeftShift(value: int64, shift: int32) = (# "shl" value (mask shift 63) : int64 #) + static member inline op_LeftShift(value: uint64, shift: int32) = (# "shl" value (mask shift 63) : uint64 #) + static member inline op_LeftShift(value: nativeint, shift: int32) = (# "shl" value shift : nativeint #) + static member inline op_LeftShift(value: unativeint, shift: int32) = (# "shl" value shift : unativeint #) + static member inline op_LeftShift(value: int16, shift: int32) = (# "conv.i2" (# "shl" value (mask shift 15) : int32 #) : int16 #) + static member inline op_LeftShift(value: uint16, shift: int32) = (# "conv.u2" (# "shl" value (mask shift 15) : uint32 #) : uint16 #) + static member inline op_LeftShift(value: sbyte, shift: int32) = (# "conv.i1" (# "shl" value (mask shift 7) : int32 #) : sbyte #) + static member inline op_LeftShift(value: byte, shift: int32) = (# "conv.u1" (# "shl" value (mask shift 7) : uint32 #) : byte #) + + static member inline op_RightShift(value: byte, shift: int32) = (# "shr" value (mask shift 31) : int32 #) + static member inline op_RightShift(value: byte, shift: int32) = (# "shr.un" value (mask shift 31) : uint32 #) + static member inline op_RightShift(value: byte, shift: int32) = (# "shr" value (mask shift 63) : int64 #) + static member inline op_RightShift(value: byte, shift: int32) = (# "shr.un" value (mask shift 63) : uint64 #) + static member inline op_RightShift(value: byte, shift: int32) = (# "shr" value shift : nativeint #) + static member inline op_RightShift(value: byte, shift: int32) = (# "shr.un" value shift : unativeint #) + static member inline op_RightShift(value: byte, shift: int32) = (# "conv.i2" (# "shr" value (mask shift 15) : int32 #) : int16 #) + static member inline op_RightShift(value: byte, shift: int32) = (# "conv.u2" (# "shr.un" value (mask shift 15) : uint32 #) : uint16 #) + static member inline op_RightShift(value: byte, shift: int32) = (# "conv.i1" (# "shr" value (mask shift 7 ) : int32 #) : sbyte #) + static member inline op_RightShift(value: byte, shift: int32) = (# "conv.u1" (# "shr.un" value (mask shift 7 ) : uint32 #) : byte #) + + static member inline op_BitwiseAnd(x: int32, y: int32) = (# "and" x y : int32 #) + static member inline op_BitwiseAnd(x: int64, y: int64) = (# "and" x y : int64 #) + static member inline op_BitwiseAnd(x: uint64, y: uint64) = (# "and" x y : uint64 #) + static member inline op_BitwiseAnd(x: uint32, y: uint32) = (# "and" x y : uint32 #) + static member inline op_BitwiseAnd(x: int16, y: int16) = (# "and" x y : int16 #) + static member inline op_BitwiseAnd(x: uint16, y: uint16) = (# "and" x y : uint16 #) + static member inline op_BitwiseAnd(x: nativeint, y: nativeint) = (# "and" x y : nativeint #) + static member inline op_BitwiseAnd(x: unativeint, y: unativeint) = (# "and" x y : unativeint #) + static member inline op_BitwiseAnd(x: sbyte, y: sbyte) = (# "and" x y : sbyte #) + static member inline op_BitwiseAnd(x: byte, y: byte) = (# "and" x y : byte #) + + (* +[] +let inline (|||) (x: ^T) (y: ^T) : ^T = + (^T: (static member (|||) : ^T * ^T -> ^T) (x,y)) + when ^T : int32 = (# "or" x y : int32 #) + when ^T : int64 = (# "or" x y : int64 #) + when ^T : uint64 = (# "or" x y : uint64 #) + when ^T : uint32 = (# "or" x y : uint32 #) + when ^T : int16 = (# "or" x y : int16 #) + when ^T : uint16 = (# "or" x y : uint16 #) + when ^T : nativeint = (# "or" x y : nativeint #) + when ^T : unativeint = (# "or" x y : unativeint #) + when ^T : sbyte = (# "or" x y : sbyte #) + when ^T : byte = (# "or" x y : byte #) + + +let inline (^^^) (x: ^T) (y: ^T) : ^T = + (^T: (static member (^^^) : ^T * ^T -> ^T) (x,y)) + when ^T : int32 = (# "xor" x y : int32 #) + when ^T : int64 = (# "xor" x y : int64 #) + when ^T : uint64 = (# "xor" x y : uint64 #) + when ^T : uint32 = (# "xor" x y : uint32 #) + when ^T : int16 = (# "xor" x y : int16 #) + when ^T : uint16 = (# "xor" x y : uint16 #) + when ^T : nativeint = (# "xor" x y : nativeint #) + when ^T : unativeint = (# "xor" x y : unativeint #) + when ^T : sbyte = (# "xor" x y : sbyte #) + when ^T : byte = (# "xor" x y : byte #) + + +let inline (~~~) (value: ^T) : ^T = + (^T: (static member (~~~) : ^T -> ^T) (value)) + when ^T : int32 = (# "not" value : int32 #) + when ^T : int64 = (# "not" value : int64 #) + when ^T : uint64 = (# "not" value : uint64 #) + when ^T : uint32 = (# "not" value : uint32 #) + when ^T : nativeint = (# "not" value : nativeint #) + when ^T : unativeint = (# "not" value : unativeint #) + when ^T : int16 = (# "conv.i2" (# "not" value : int32 #) : int16 #) + when ^T : uint16 = (# "conv.u2" (# "not" value : uint32 #) : uint16 #) + when ^T : sbyte = (# "conv.i1" (# "not" value : int32 #) : sbyte #) + when ^T : byte = (# "conv.u1" (# "not" value : uint32 #) : byte #) + + +let inline byte (value: ^T) = + (^T : (static member op_Explicit: ^T -> byte) (value)) + when ^T : string = parseByte (castToString value) + when ^T : float = (# "conv.u1" value : byte #) + when ^T : float32 = (# "conv.u1" value : byte #) + when ^T : int64 = (# "conv.u1" value : byte #) + when ^T : int32 = (# "conv.u1" value : byte #) + when ^T : int16 = (# "conv.u1" value : byte #) + when ^T : nativeint = (# "conv.u1" value : byte #) + when ^T : sbyte = (# "conv.u1" value : byte #) + when ^T : uint64 = (# "conv.u1" value : byte #) + when ^T : uint32 = (# "conv.u1" value : byte #) + when ^T : uint16 = (# "conv.u1" value : byte #) + when ^T : char = (# "conv.u1" value : byte #) + when ^T : unativeint = (# "conv.u1" value : byte #) + when ^T : byte = (# "conv.u1" value : byte #) + + +let inline sbyte (value: ^T) = + (^T : (static member op_Explicit: ^T -> sbyte) (value)) + when ^T : string = ParseSByte (castToString value) + when ^T : float = (# "conv.i1" value : sbyte #) + when ^T : float32 = (# "conv.i1" value : sbyte #) + when ^T : int64 = (# "conv.i1" value : sbyte #) + when ^T : int32 = (# "conv.i1" value : sbyte #) + when ^T : int16 = (# "conv.i1" value : sbyte #) + when ^T : nativeint = (# "conv.i1" value : sbyte #) + when ^T : sbyte = (# "conv.i1" value : sbyte #) + when ^T : uint64 = (# "conv.i1" value : sbyte #) + when ^T : uint32 = (# "conv.i1" value : sbyte #) + when ^T : uint16 = (# "conv.i1" value : sbyte #) + when ^T : char = (# "conv.i1" value : sbyte #) + when ^T : unativeint = (# "conv.i1" value : sbyte #) + when ^T : byte = (# "conv.i1" value : sbyte #) + + +let inline uint16 (value: ^T) = + (^T : (static member op_Explicit: ^T -> uint16) (value)) + when ^T : string = ParseUInt16 (castToString value) + when ^T : float = (# "conv.u2" value : uint16 #) + when ^T : float32 = (# "conv.u2" value : uint16 #) + when ^T : int64 = (# "conv.u2" value : uint16 #) + when ^T : int32 = (# "conv.u2" value : uint16 #) + when ^T : int16 = (# "conv.u2" value : uint16 #) + when ^T : nativeint = (# "conv.u2" value : uint16 #) + when ^T : sbyte = (# "conv.u2" value : uint16 #) + when ^T : uint64 = (# "conv.u2" value : uint16 #) + when ^T : uint32 = (# "conv.u2" value : uint16 #) + when ^T : uint16 = (# "conv.u2" value : uint16 #) + when ^T : char = (# "conv.u2" value : uint16 #) + when ^T : unativeint = (# "conv.u2" value : uint16 #) + when ^T : byte = (# "conv.u2" value : uint16 #) + + + (^T : (static member op_Explicit: ^T -> int16) (value)) + when ^T : string = ParseInt16 (castToString value) + when ^T : float = (# "conv.i2" value : int16 #) + when ^T : float32 = (# "conv.i2" value : int16 #) + when ^T : int64 = (# "conv.i2" value : int16 #) + when ^T : int32 = (# "conv.i2" value : int16 #) + when ^T : int16 = (# "conv.i2" value : int16 #) + when ^T : nativeint = (# "conv.i2" value : int16 #) + when ^T : sbyte = (# "conv.i2" value : int16 #) + when ^T : uint64 = (# "conv.i2" value : int16 #) + when ^T : uint32 = (# "conv.i2" value : int16 #) + when ^T : uint16 = (# "conv.i2" value : int16 #) + when ^T : char = (# "conv.i2" value : int16 #) + when ^T : unativeint = (# "conv.i2" value : int16 #) + when ^T : byte = (# "conv.i2" value : int16 #) + + +let inline uint32 (value: ^T) = + (^T : (static member op_Explicit: ^T -> uint32) (value)) + when ^T : string = ParseUInt32 (castToString value) + when ^T : float = (# "conv.u4" value : uint32 #) + when ^T : float32 = (# "conv.u4" value : uint32 #) + + when ^T : int64 = (# "conv.u4" value : uint32 #) + when ^T : nativeint = (# "conv.u4" value : uint32 #) + + // For integers shorter that 32 bits, we must first + // sign-widen the signed integer to 32 bits, and then + // "convert" from signed int32 to unsigned int32 + // This is a no-op on IL stack (ECMA 335 Part III 1.5 Tables 8 & 9) + when ^T : int32 = (# "" value : uint32 #) + when ^T : int16 = (# "" value : uint32 #) + when ^T : sbyte = (# "" value : uint32 #) + + when ^T : uint64 = (# "conv.u4" value : uint32 #) + when ^T : uint32 = (# "conv.u4" value : uint32 #) + when ^T : uint16 = (# "conv.u4" value : uint32 #) + when ^T : char = (# "conv.u4" value : uint32 #) + when ^T : unativeint = (# "conv.u4" value : uint32 #) + when ^T : byte = (# "conv.u4" value : uint32 #) + + +let inline int32 (value: ^T) = + (^T : (static member op_Explicit: ^T -> int32) (value)) + when ^T : string = ParseInt32 (castToString value) + when ^T : float = (# "conv.i4" value : int32 #) + when ^T : float32 = (# "conv.i4" value : int32 #) + when ^T : int64 = (# "conv.i4" value : int32 #) + when ^T : nativeint = (# "conv.i4" value : int32 #) + + // For integers shorter that 32 bits, we sign-widen the signed integer to 32 bits + // This is a no-op on IL stack (ECMA 335 Part III 1.5 Tables 8 & 9) + when ^T : int32 = (# "" value : int32 #) + when ^T : int16 = (# "" value : int32 #) + when ^T : sbyte = (# "" value : int32 #) + + when ^T : uint64 = (# "conv.i4" value : int32 #) + when ^T : uint32 = (# "" value : int32 #) // Signed<->Unsigned conversion is a no-op on IL stack + when ^T : uint16 = (# "conv.i4" value : int32 #) + when ^T : char = (# "conv.i4" value : int32 #) + when ^T : unativeint = (# "conv.i4" value : int32 #) + when ^T : byte = (# "conv.i4" value : int32 #) + + +let inline uint64 (value: ^T) = + (^T : (static member op_Explicit: ^T -> uint64) (value)) + when ^T : string = ParseUInt64 (castToString value) + when ^T : float = (# "conv.u8" value : uint64 #) + when ^T : float32 = (# "conv.u8" value : uint64 #) + + // we must first sign-widen the signed integer to 64 bits, and then + // "convert" from signed int64 to unsigned int64 + // conv.i8 sign-widens the input, and on IL stack, + // conversion from signed to unsigned is a no-op (ECMA 335 Part III 1.5 Table 8) + when ^T : int64 = (# "" value : uint64 #) + when ^T : int32 = (# "conv.i8" value : uint64 #) + when ^T : int16 = (# "conv.i8" value : uint64 #) + when ^T : nativeint = (# "conv.i8" value : uint64 #) + when ^T : sbyte = (# "conv.i8" value : uint64 #) + + + when ^T : uint64 = (# "" value : uint64 #) + when ^T : uint32 = (# "conv.u8" value : uint64 #) + when ^T : uint16 = (# "conv.u8" value : uint64 #) + when ^T : char = (# "conv.u8" value : uint64 #) + when ^T : unativeint = (# "conv.u8" value : uint64 #) + when ^T : byte = (# "conv.u8" value : uint64 #) + + +[] +[] +let inline int64 (value: ^T) = + (^T : (static member op_Explicit: ^T -> int64) (value)) + when ^T : string = ParseInt64 (castToString value) + when ^T : float = (# "conv.i8" value : int64 #) + when ^T : float32 = (# "conv.i8" value : int64 #) + when ^T : int64 = (# "conv.i8" value : int64 #) + when ^T : int32 = (# "conv.i8" value : int64 #) + when ^T : int16 = (# "conv.i8" value : int64 #) + when ^T : nativeint = (# "conv.i8" value : int64 #) + when ^T : sbyte = (# "conv.i8" value : int64 #) + + // When converting unsigned integer, we should zero-widen them, NOT sign-widen + // No-op for uint64, conv.u8 for uint32, for smaller types conv.u8 and conv.i8 are identical. + // For nativeint, conv.u8 works correctly both in 32 bit and 64 bit case. + when ^T : uint64 = (# "" value : int64 #) + when ^T : uint32 = (# "conv.u8" value : int64 #) + when ^T : uint16 = (# "conv.u8" value : int64 #) + when ^T : char = (# "conv.u8" value : int64 #) + when ^T : unativeint = (# "conv.u8" value : int64 #) + when ^T : byte = (# "conv.u8" value : int64 #) + + +[] +[] +let inline float32 (value: ^T) = + (^T : (static member op_Explicit: ^T -> float32) (value)) + when ^T : string = ParseSingle (castToString value) + when ^T : float = (# "conv.r4" value : float32 #) + // NOTE: float32 should convert its argument to 32-bit float even when applied to a higher precision float stored in a register. See devdiv2#49888. + when ^T : float32 = (# "conv.r4" value : float32 #) + when ^T : int64 = (# "conv.r4" value : float32 #) + when ^T : int32 = (# "conv.r4" value : float32 #) + when ^T : int16 = (# "conv.r4" value : float32 #) + when ^T : nativeint = (# "conv.r4" value : float32 #) + when ^T : sbyte = (# "conv.r4" value : float32 #) + when ^T : uint64 = (# "conv.r.un conv.r4" value : float32 #) + when ^T : uint32 = (# "conv.r.un conv.r4" value : float32 #) + when ^T : uint16 = (# "conv.r.un conv.r4" value : float32 #) + when ^T : char = (# "conv.r.un conv.r4" value : float32 #) + when ^T : unativeint = (# "conv.r.un conv.r4" value : float32 #) + when ^T : byte = (# "conv.r.un conv.r4" value : float32 #) + + +let inline float (value: ^T) = + (^T : (static member op_Explicit: ^T -> float) (value)) + when ^T : string = ParseDouble (castToString value) + // NOTE: float should convert its argument to 64-bit float even when applied to a higher precision float stored in a register. See devdiv2#49888. + when ^T : float = (# "conv.r8" value : float #) + when ^T : float32 = (# "conv.r8" value : float #) + when ^T : int64 = (# "conv.r8" value : float #) + when ^T : int32 = (# "conv.r8" value : float #) + when ^T : int16 = (# "conv.r8" value : float #) + when ^T : nativeint = (# "conv.r8" value : float #) + when ^T : sbyte = (# "conv.r8" value : float #) + when ^T : uint64 = (# "conv.r.un conv.r8" value : float #) + when ^T : uint32 = (# "conv.r.un conv.r8" value : float #) + when ^T : uint16 = (# "conv.r.un conv.r8" value : float #) + when ^T : char = (# "conv.r.un conv.r8" value : float #) + when ^T : unativeint = (# "conv.r.un conv.r8" value : float #) + when ^T : byte = (# "conv.r.un conv.r8" value : float #) + when ^T : decimal = (System.Convert.ToDouble((# "" value : decimal #))) + + +let inline decimal (value: ^T) = + (^T : (static member op_Explicit: ^T -> decimal) (value)) + when ^T : string = (System.Decimal.Parse(castToString value,NumberStyles.Float,CultureInfo.InvariantCulture)) + when ^T : float = (System.Convert.ToDecimal((# "" value : float #))) + when ^T : float32 = (System.Convert.ToDecimal((# "" value : float32 #))) + when ^T : int64 = (System.Convert.ToDecimal((# "" value : int64 #))) + when ^T : int32 = (System.Convert.ToDecimal((# "" value : int32 #))) + when ^T : int16 = (System.Convert.ToDecimal((# "" value : int16 #))) + when ^T : nativeint = (System.Convert.ToDecimal(int64 (# "" value : nativeint #))) + when ^T : sbyte = (System.Convert.ToDecimal((# "" value : sbyte #))) + when ^T : uint64 = (System.Convert.ToDecimal((# "" value : uint64 #))) + when ^T : uint32 = (System.Convert.ToDecimal((# "" value : uint32 #))) + when ^T : uint16 = (System.Convert.ToDecimal((# "" value : uint16 #))) + when ^T : unativeint = (System.Convert.ToDecimal(uint64 (# "" value : unativeint #))) + when ^T : byte = (System.Convert.ToDecimal((# "" value : byte #))) + when ^T : decimal = (# "" value : decimal #) + + +let inline unativeint (value: ^T) = + (^T : (static member op_Explicit: ^T -> unativeint) (value)) + when ^T : string = ParseUIntPtr (castToString value) + when ^T : float = (# "conv.u" value : unativeint #) + when ^T : float32 = (# "conv.u" value : unativeint #) + + // Narrower signed types we sign-extend. + // Same length signed types we leave as such (so -1 gets reinterpreted as unsigned MaxValue). + // Wider signed types we truncate. + // conv.i does just that for both 32 and 64 bit case of nativeint, and conversion from nativeint is no-op. + when ^T : int64 = (# "conv.i" value : unativeint #) + when ^T : int32 = (# "conv.i" value : unativeint #) + when ^T : int16 = (# "conv.i" value : unativeint #) + when ^T : nativeint = (# "" value : unativeint #) + when ^T : sbyte = (# "conv.i" value : unativeint #) + + when ^T : uint64 = (# "conv.u" value : unativeint #) + when ^T : uint32 = (# "conv.u" value : unativeint #) + when ^T : uint16 = (# "conv.u" value : unativeint #) + when ^T : char = (# "conv.u" value : unativeint #) + when ^T : unativeint = (# "" value : unativeint #) + when ^T : byte = (# "conv.u" value : unativeint #) + + +let inline nativeint (value: ^T) = + (^T : (static member op_Explicit: ^T -> nativeint) (value)) + when ^T : string = ParseIntPtr (castToString value) + when ^T : float = (# "conv.i" value : nativeint #) + when ^T : float32 = (# "conv.i" value : nativeint #) + + when ^T : int64 = (# "conv.i" value : nativeint #) + when ^T : int32 = (# "conv.i" value : nativeint #) + when ^T : int16 = (# "conv.i" value : nativeint #) + when ^T : nativeint = (# "conv.i" value : nativeint #) + when ^T : sbyte = (# "conv.i" value : nativeint #) + + // Narrower unsigned types we zero-extend. + // Same length unsigned types we leave as such (so unsigned MaxValue (all-bits-set) gets reinterpreted as -1). + // Wider unsigned types we truncate. + // conv.u does just that for both 32- and 64-bit-wide nativeint, and conversion from unativeint is no-op. + when ^T : uint64 = (# "conv.u" value : nativeint #) + when ^T : uint32 = (# "conv.u" value : nativeint #) + when ^T : uint16 = (# "conv.u" value : nativeint #) + when ^T : char = (# "conv.u" value : nativeint #) + when ^T : unativeint = (# "" value : nativeint #) + when ^T : byte = (# "conv.i" value : nativeint #) + +let inline string (value: ^T) = + anyToString "" value + // since we have static optimization conditionals for ints below, we need to special-case Enums. + // This way we'll print their symbolic value, as opposed to their integral one (Eg., "A", rather than "1") + when ^T struct = anyToString "" value + when ^T : float = (# "" value : float #).ToString("g",CultureInfo.InvariantCulture) + when ^T : float32 = (# "" value : float32 #).ToString("g",CultureInfo.InvariantCulture) + when ^T : int64 = (# "" value : int64 #).ToString("g",CultureInfo.InvariantCulture) + when ^T : int32 = (# "" value : int32 #).ToString("g",CultureInfo.InvariantCulture) + when ^T : int16 = (# "" value : int16 #).ToString("g",CultureInfo.InvariantCulture) + when ^T : nativeint = (# "" value : nativeint #).ToString() + when ^T : sbyte = (# "" value : sbyte #).ToString("g",CultureInfo.InvariantCulture) + when ^T : uint64 = (# "" value : uint64 #).ToString("g",CultureInfo.InvariantCulture) + when ^T : uint32 = (# "" value : uint32 #).ToString("g",CultureInfo.InvariantCulture) + when ^T : int16 = (# "" value : int16 #).ToString("g",CultureInfo.InvariantCulture) + when ^T : unativeint = (# "" value : unativeint #).ToString() + when ^T : byte = (# "" value : byte #).ToString("g",CultureInfo.InvariantCulture) + +let inline char (value: ^T) = + (^T : (static member op_Explicit: ^T -> char) (value)) + when ^T : string = (System.Char.Parse(castToString value)) + when ^T : float = (# "conv.u2" value : char #) + when ^T : float32 = (# "conv.u2" value : char #) + when ^T : int64 = (# "conv.u2" value : char #) + when ^T : int32 = (# "conv.u2" value : char #) + when ^T : int16 = (# "conv.u2" value : char #) + when ^T : nativeint = (# "conv.u2" value : char #) + when ^T : sbyte = (# "conv.u2" value : char #) + when ^T : uint64 = (# "conv.u2" value : char #) + when ^T : uint32 = (# "conv.u2" value : char #) + when ^T : uint16 = (# "conv.u2" value : char #) + when ^T : char = (# "conv.u2" value : char #) + when ^T : unativeint = (# "conv.u2" value : char #) + when ^T : byte = (# "conv.u2" value : char #) + + +let inline (<) (x:^T) (y:^U) = + ((^T or ^U): (static member (<) : ^T * ^U -> bool) (x,y)) + when ^T : bool = (# "clt" x y : bool #) + when ^T : sbyte = (# "clt" x y : bool #) + when ^T : int16 = (# "clt" x y : bool #) + when ^T : int32 = (# "clt" x y : bool #) + when ^T : int64 = (# "clt" x y : bool #) + when ^T : byte = (# "clt.un" x y : bool #) + when ^T : uint16 = (# "clt.un" x y : bool #) + when ^T : uint32 = (# "clt.un" x y : bool #) + when ^T : uint64 = (# "clt.un" x y : bool #) + when ^T : unativeint = (# "clt.un" x y : bool #) + when ^T : nativeint = (# "clt" x y : bool #) + when ^T : float = (# "clt" x y : bool #) + when ^T : float32= (# "clt" x y : bool #) + when ^T : char = (# "clt" x y : bool #) + when ^T : decimal = System.Decimal.op_LessThan ((# "" x:decimal #), (# "" y:decimal #)) + when ^T : string = (# "clt" (System.String.CompareOrdinal((# "" x : string #),(# "" y : string #))) 0 : bool #) + + +let inline (>) (x:^T) (y:^U) = + ((^T or ^U): (static member (>) : ^T * ^U -> bool) (x,y)) + when 'T : bool = (# "cgt" x y : bool #) + when 'T : sbyte = (# "cgt" x y : bool #) + when 'T : int16 = (# "cgt" x y : bool #) + when 'T : int32 = (# "cgt" x y : bool #) + when 'T : int64 = (# "cgt" x y : bool #) + when 'T : nativeint = (# "cgt" x y : bool #) + when 'T : byte = (# "cgt.un" x y : bool #) + when 'T : uint16 = (# "cgt.un" x y : bool #) + when 'T : uint32 = (# "cgt.un" x y : bool #) + when 'T : uint64 = (# "cgt.un" x y : bool #) + when 'T : unativeint = (# "cgt.un" x y : bool #) + when 'T : float = (# "cgt" x y : bool #) + when 'T : float32 = (# "cgt" x y : bool #) + when 'T : char = (# "cgt" x y : bool #) + when 'T : decimal = System.Decimal.op_GreaterThan ((# "" x:decimal #), (# "" y:decimal #)) + when ^T : string = (# "cgt" (System.String.CompareOrdinal((# "" x : string #),(# "" y : string #))) 0 : bool #) + + +let inline (<=) (x:^T) (y:^U) = + ((^T or ^U): (static member (<=) : ^T * ^U -> bool) (x,y)) + when 'T : bool = not (# "cgt" x y : bool #) + when 'T : sbyte = not (# "cgt" x y : bool #) + when 'T : int16 = not (# "cgt" x y : bool #) + when 'T : int32 = not (# "cgt" x y : bool #) + when 'T : int64 = not (# "cgt" x y : bool #) + when 'T : nativeint = not (# "cgt" x y : bool #) + when 'T : byte = not (# "cgt.un" x y : bool #) + when 'T : uint16 = not (# "cgt.un" x y : bool #) + when 'T : uint32 = not (# "cgt.un" x y : bool #) + when 'T : uint64 = not (# "cgt.un" x y : bool #) + when 'T : unativeint = not (# "cgt.un" x y : bool #) + when 'T : float = not (# "cgt.un" x y : bool #) + when 'T : float32 = not (# "cgt.un" x y : bool #) + when 'T : char = not (# "cgt" x y : bool #) + when 'T : decimal = System.Decimal.op_LessThanOrEqual ((# "" x:decimal #), (# "" y:decimal #)) + when ^T : string = not (# "cgt" (System.String.CompareOrdinal((# "" x : string #),(# "" y : string #))) 0 : bool #) + + +let inline (>=) (x:^T) (y:^U) = + ((^T or ^U): (static member (>=) : ^T * ^U -> bool) (x,y)) + when 'T : bool = not (# "clt" x y : bool #) + when 'T : sbyte = not (# "clt" x y : bool #) + when 'T : int16 = not (# "clt" x y : bool #) + when 'T : int32 = not (# "clt" x y : bool #) + when 'T : int64 = not (# "clt" x y : bool #) + when 'T : nativeint = not (# "clt" x y : bool #) + when 'T : byte = not (# "clt.un" x y : bool #) + when 'T : uint16 = not (# "clt.un" x y : bool #) + when 'T : uint32 = not (# "clt.un" x y : bool #) + when 'T : uint64 = not (# "clt.un" x y : bool #) + when 'T : unativeint = not (# "clt.un" x y : bool #) + when 'T : float = not (# "clt.un" x y : bool #) + when 'T : float32 = not (# "clt.un" x y : bool #) + when 'T : char = not (# "clt" x y : bool #) + when 'T : decimal = System.Decimal.op_GreaterThanOrEqual ((# "" x:decimal #), (# "" y:decimal #)) + when ^T : string = not (# "clt" (System.String.CompareOrdinal((# "" x : string #),(# "" y : string #))) 0 : bool #) + + +let inline (=) (x:^T) (y:^T) = + (^T : (static member (=) : ^T * ^T -> bool) (x,y)) + when ^T : bool = (# "ceq" x y : bool #) + when ^T : sbyte = (# "ceq" x y : bool #) + when ^T : int16 = (# "ceq" x y : bool #) + when ^T : int32 = (# "ceq" x y : bool #) + when ^T : int64 = (# "ceq" x y : bool #) + when ^T : byte = (# "ceq" x y : bool #) + when ^T : uint16 = (# "ceq" x y : bool #) + when ^T : uint32 = (# "ceq" x y : bool #) + when ^T : uint64 = (# "ceq" x y : bool #) + when ^T : float = (# "ceq" x y : bool #) + when ^T : float32 = (# "ceq" x y : bool #) + when ^T : char = (# "ceq" x y : bool #) + when ^T : nativeint = (# "ceq" x y : bool #) + when ^T : unativeint = (# "ceq" x y : bool #) + when ^T : string = System.String.Equals((# "" x : string #),(# "" y : string #)) + when ^T : decimal = System.Decimal.op_Equality((# "" x:decimal #), (# "" y:decimal #)) + + +let inline (<>) (x:^T) (y:^T) = + (^T : (static member (<>) : ^T * ^T -> bool) (x,y)) + when ^T : bool = not (# "ceq" x y : bool #) + when ^T : sbyte = not (# "ceq" x y : bool #) + when ^T : int16 = not (# "ceq" x y : bool #) + when ^T : int32 = not (# "ceq" x y : bool #) + when ^T : int64 = not (# "ceq" x y : bool #) + when ^T : byte = not (# "ceq" x y : bool #) + when ^T : uint16 = not (# "ceq" x y : bool #) + when ^T : uint32 = not (# "ceq" x y : bool #) + when ^T : uint64 = not (# "ceq" x y : bool #) + when ^T : float = not (# "ceq" x y : bool #) + when ^T : float32 = not (# "ceq" x y : bool #) + when ^T : char = not (# "ceq" x y : bool #) + when ^T : nativeint = not (# "ceq" x y : bool #) + when ^T : unativeint = not (# "ceq" x y : bool #) + when ^T : string = not (System.String.Equals((# "" x : string #),(# "" y : string #))) + when ^T : decimal = System.Decimal.op_Inequality((# "" x:decimal #), (# "" y:decimal #)) + +let inline DivideByInt< ^T when ^T : (static member DivideByInt : ^T * int -> ^T) > (x:^T) (y:int) : ^T = + DivideByIntDynamic<'T> x y + when ^T : float = (# "div" x ((# "conv.r8" (y:int) : float #)) : float #) + when ^T : float32 = (# "div" x ((# "conv.r4" (y:int) : float32 #)) : float32 #) + when ^T : decimal = System.Decimal.Divide((retype x:decimal), System.Convert.ToDecimal(y)) + +*) + [] type GenericZeroDynamicImplTable<'T>() = @@ -2571,9 +3166,7 @@ namespace Microsoft.FSharp.Core when ^T : decimal = System.Decimal.Divide((retype x:decimal), System.Convert.ToDecimal(y)) when ^T : ^T = (^T : (static member DivideByInt : ^T * int -> ^T) (x, y)) - // Dynamic implementation of addition operator resolution - [] type AdditionDynamicImplTable<'T,'U,'V>() = static let impl : ('T -> 'U -> 'V) = // The dynamic implementation @@ -2589,19 +3182,19 @@ namespace Microsoft.FSharp.Core | _ -> raise (NotSupportedException (SR.GetString(SR.dyInvOpAddOverload))) if aty.Equals(bty) && bty.Equals(cty) then - if aty.Equals(typeof) then unboxPrim<_> (box (fun (x:sbyte) (y:sbyte) -> (# "conv.i1" (# "add" x y : int32 #) : sbyte #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int16) (y:int16) -> (# "conv.i2" (# "add" x y : int32 #) : int16 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int32) (y:int32) -> (# "add" x y : int32 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int64) (y:int64) -> (# "add" x y : int64 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:nativeint) (y:nativeint) -> (# "add" x y : nativeint #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:byte) (y:byte) -> (# "conv.u1" (# "add" x y : uint32 #) : byte #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint16) (y:uint16) -> (# "conv.u2" (# "add" x y : uint32 #) : uint16 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint32) (y:uint32) -> (# "add" x y : uint32 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint64) (y:uint64) -> (# "add" x y : uint64 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:unativeint) (y:unativeint) -> (# "add" x y : unativeint #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float) (y:float) -> (# "add" x y : float #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float32) (y:float32) -> (# "add" x y : float32 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:string) (y:string) -> System.String.Concat(x,y))) + if aty.Equals(typeof) then unboxPrim<_> (box (fun (x:sbyte) (y:sbyte) -> BuiltInPrimitives.op_Addition(x,y))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int16) (y:int16) -> BuiltInPrimitives.op_Addition(x,y))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int32) (y:int32) -> BuiltInPrimitives.op_Addition(x,y))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int64) (y:int64) -> BuiltInPrimitives.op_Addition(x,y))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:nativeint) (y:nativeint) -> BuiltInPrimitives.op_Addition(x,y))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:byte) (y:byte) -> BuiltInPrimitives.op_Addition(x,y))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint16) (y:uint16) -> BuiltInPrimitives.op_Addition(x,y))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint32) (y:uint32) -> BuiltInPrimitives.op_Addition(x,y))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint64) (y:uint64) -> BuiltInPrimitives.op_Addition(x,y))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:unativeint) (y:unativeint) -> BuiltInPrimitives.op_Addition(x,y))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float) (y:float) -> BuiltInPrimitives.op_Addition(x,y))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float32) (y:float32) -> BuiltInPrimitives.op_Addition(x,y))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:string) (y:string) -> BuiltInPrimitives.op_Addition(x,y))) else dyn() else dyn() @@ -2666,19 +3259,18 @@ namespace Microsoft.FSharp.Core | _ -> raise (NotSupportedException (SR.GetString(SR.dyInvOpMultOverload))) if aty.Equals(bty) && bty.Equals(cty) then - if aty.Equals(typeof) then unboxPrim<_> (box (fun (x:sbyte) (y:sbyte) -> (# "conv.i1" (# "mul" x y : int32 #) : sbyte #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int16) (y:int16) -> (# "conv.i2" (# "mul" x y : int32 #) : int16 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int32) (y:int32) -> (# "mul" x y : int32 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int64) (y:int64) -> (# "mul" x y : int64 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:nativeint) (y:nativeint) -> (# "mul" x y : nativeint #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:byte) (y:byte) -> (# "conv.u1" (# "mul" x y : uint32 #) : byte #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint16) (y:uint16) -> (# "conv.u2" (# "mul" x y : uint32 #) : uint16 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint32) (y:uint32) -> (# "mul" x y : uint32 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint64) (y:uint64) -> (# "mul" x y : uint64 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:unativeint) (y:unativeint) -> (# "mul" x y : unativeint #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float) (y:float) -> (# "mul" x y : float #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float32) (y:float32) -> (# "mul" x y : float32 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:string) (y:string) -> System.String.Concat(x,y))) + if aty.Equals(typeof) then unboxPrim<_> (box (fun (x:sbyte) (y:sbyte) -> BuiltInPrimitives.op_Multiply(x,y))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int16) (y:int16) -> BuiltInPrimitives.op_Multiply(x,y))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int32) (y:int32) -> BuiltInPrimitives.op_Multiply(x,y))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int64) (y:int64) -> BuiltInPrimitives.op_Multiply(x,y))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:nativeint) (y:nativeint) -> BuiltInPrimitives.op_Multiply(x,y))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:byte) (y:byte) -> BuiltInPrimitives.op_Multiply(x,y))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint16) (y:uint16) -> BuiltInPrimitives.op_Multiply(x,y))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint32) (y:uint32) -> BuiltInPrimitives.op_Multiply(x,y))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint64) (y:uint64) -> BuiltInPrimitives.op_Multiply(x,y))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:unativeint) (y:unativeint) -> BuiltInPrimitives.op_Multiply(x,y))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float) (y:float) -> BuiltInPrimitives.op_Multiply(x,y))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float32) (y:float32) -> BuiltInPrimitives.op_Multiply(x,y))) else dyn() else dyn() @@ -2715,7 +3307,6 @@ namespace Microsoft.FSharp.Core elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:unativeint) (y:unativeint) -> (# "mul.ovf.un" x y : unativeint #))) elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float) (y:float) -> (# "mul" x y : float #))) elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float32) (y:float32) -> (# "mul" x y : float32 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:string) (y:string) -> System.String.Concat(x,y))) else dyn() else dyn() @@ -2723,22 +3314,6 @@ namespace Microsoft.FSharp.Core let CheckedMultiplyDynamic<'T,'U,'V> x y = CheckedMultiplyDynamicImplTable<'T,'U,'V>.Impl x y - -namespace System - - open System - open System.Collections - open System.Collections.Generic - open System.Diagnostics - open System.Globalization - open System.Text - open Microsoft.FSharp.Core - open Microsoft.FSharp.Core.BasicInlinedOperations - open Microsoft.FSharp.Core.LanguagePrimitives - open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators - open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicFunctions - - namespace Microsoft.FSharp.Core open System @@ -3595,8 +4170,6 @@ namespace Microsoft.FSharp.Core when ^T : byte = value when ^T : decimal = value - let inline mask (n:int) (m:int) = (# "and" n m : int #) - [] let inline (<<<) (value: ^T) (shift:int) : ^T = (^T: (static member (<<<) : ^T * int -> ^T) (value,shift)) @@ -3973,11 +4546,6 @@ namespace Microsoft.FSharp.Core when ^T : byte = (System.Convert.ToDecimal((# "" value : byte #))) when ^T : decimal = (# "" value : decimal #) - // Recall type names. - // Framework names: sbyte, byte, int16, uint16, int32, uint32, int64, uint64, single, double. - // C# names: sbyte, byte, short, ushort, int, uint, long, ulong, single, double. - // F# names: sbyte, byte, int16, uint16, int, uint32, int64, uint64, float32, float. - [] [] let inline unativeint (value: ^T) = diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 1a5cc878efe..25e92fd8680 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -3807,7 +3807,7 @@ and GenTraitCall cenv cgbuf eenv (traitInfo: TraitConstraintInfo, argExprs, m) e // If witnesses are available, we should now always find trait witnesses in scope assert eenv.witnessesInScope.IsEmpty - let minfoOpt = CommitOperationResult (ConstraintSolver.CodegenWitnessThatTypeSupportsTraitConstraint cenv.tcVal cenv.g cenv.amap m traitInfo argExprs) + let minfoOpt = CommitOperationResult (ConstraintSolver.CodegenWitnessForTraitConstraint cenv.tcVal cenv.g cenv.amap m traitInfo argExprs) match minfoOpt with | None -> let exnArg = mkString cenv.g m (FSComp.SR.ilDynamicInvocationNotSupported(traitInfo.MemberName)) diff --git a/src/fsharp/MethodCalls.fs b/src/fsharp/MethodCalls.fs index 784a6731a05..eb9b7b4c79b 100644 --- a/src/fsharp/MethodCalls.fs +++ b/src/fsharp/MethodCalls.fs @@ -1422,7 +1422,62 @@ let GenWitnessExpr amap g m (traitInfo: TraitConstraintInfo) argExprs = Some (MakeApplicationAndBetaReduce g (expr, tyOfExpr g expr, [], argExprs, m)) | Choice5Of5 () -> - None + let rty = match traitInfo.ReturnType with None -> g.unit_ty | Some ty -> ty + match traitInfo.MemberName, traitInfo.MemberFlags.IsInstance, traitInfo.ArgumentTypes, argExprs with + | "op_Division", false, [argty1;argty2], [arg1; arg2] -> mkCallDivisionOperator g m argty1 argty2 rty arg1 arg2 |> Some + | "op_Addition", false, [argty1;argty2], [arg1; arg2] -> mkCallAdditionOperator g m argty1 argty2 rty arg1 arg2 |> Some +(* + | "op_Multiply", [argty1;argty2], [arg1; arg2] + | "op_Subtraction", [argty1;argty2], [arg1; arg2] + | "op_Modulus", [argty1;argty2], [arg1; arg2] + | "op_LessThan", [argty1;argty2], [arg1; arg2] + | "op_LessThanOrEqual", [argty1;argty2], [arg1; arg2] + | "op_GreaterThan", [argty1;argty2], [arg1; arg2] + | "op_GreaterThanOrEqual", [argty1;argty2], [arg1; arg2] + | "op_Inequality", [argty1;argty2], [arg1; arg2] + | "get_Zero", [argty1;argty2], [arg1; arg2] + | "get_One", [argty1;argty2], [arg1; arg2] + | "DivideByInt", [argty1;argty2], [arg1; arg2] + | "get_Item", true, [argty1], [arg1] when isStringTy g ty + | "get_Item", true, argtys, [arg1] when isArrayTy g ty + | "set_Item", true, argtys, [arg1] when isArrayTy g ty + | "op_BitwiseAnd", [argty1;argty2], [arg1; arg2] + | "op_BitwiseOr", [argty1;argty2], [arg1; arg2] + | "op_ExclusiveOr", [argty1;argty2], [arg1; arg2] + | "op_LeftShift", [argty1;argty2], [arg1; arg2] + | "op_RightShift", [argty1;argty2], [arg1; arg2] + | "op_UnaryPlus", [argty1], [arg1] +*) + | "op_UnaryNegation", false, [argty1], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some +(* + | "get_Sign", [], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "op_LogicalNot", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "op_OnesComplement", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "Abs", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "Sqrt", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "Sin", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "Cos", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "Tan", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "Sinh", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "Cosh", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "Tanh", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "Atan", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "Acos", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "Asin", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "Exp", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "Ceiling", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "Floor", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "Round", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "Truncate", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "Log10", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "Log", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "Sqrt", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "op_Explicit", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "Pow", [argty1; argty2], [arg1; arg2] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "Atan2", [argty1; argty2], [arg1; arg2] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + | "Sqrt", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some +*) + | _ -> None let GenWitnessExprLambda amap g m (traitInfo: TraitConstraintInfo) = let argtysl = GenWitnessArgTys g traitInfo.TraitKey @@ -1432,10 +1487,6 @@ let GenWitnessExprLambda amap g m (traitInfo: TraitConstraintInfo) = | Some expr -> mkMemberLambdas m [] None None vsl (expr, tyOfExpr g expr) | None -> - // TODO: generate builtin - // let exnArg = mkString g m (FSComp.SR.ilDynamicInvocationNotSupported(traitInfo.MemberName)) - // let exnExpr = MakeNotSupportedExnExpr cenv eenv (exnArg, m) - // let replacementExpr = mkThrow m (tyOfExpr cenv.g expr) exnExpr mkOne g m let GenWitnessArgs amap g m (traitInfos: TraitConstraintInfo list) = diff --git a/src/fsharp/Optimizer.fs b/src/fsharp/Optimizer.fs index a91336dde71..ea36eb2890f 100644 --- a/src/fsharp/Optimizer.fs +++ b/src/fsharp/Optimizer.fs @@ -2386,7 +2386,7 @@ and OptimizeWhileLoop cenv env (spWhile, marker, e1, e2, m) = and OptimizeTraitCall cenv env (traitInfo, args, m) = // Resolve the static overloading early (during the compulsory rewrite phase) so we can inline. - match ConstraintSolver.CodegenWitnessThatTypeSupportsTraitConstraint cenv.TcVal cenv.g cenv.amap m traitInfo args with + match ConstraintSolver.CodegenWitnessForTraitConstraint cenv.TcVal cenv.g cenv.amap m traitInfo args with | OkResult (_, Some expr) -> OptimizeExpr cenv env expr diff --git a/src/fsharp/TastOps.fs b/src/fsharp/TastOps.fs index e44b0bfc9cb..ddbc57a4136 100644 --- a/src/fsharp/TastOps.fs +++ b/src/fsharp/TastOps.fs @@ -6669,13 +6669,13 @@ let mkCallGreaterThanOperator (g: TcGlobals) m ty e1 e2 = mkApps g (typedExprFor let mkCallGreaterThanOrEqualsOperator (g: TcGlobals) m ty e1 e2 = mkApps g (typedExprForIntrinsic g m g.greater_than_or_equals_operator, [[ty]], [ e1;e2 ], m) -let mkCallAdditionOperator (g: TcGlobals) m ty e1 e2 = mkApps g (typedExprForIntrinsic g m g.unchecked_addition_info, [[ty; ty; ty]], [e1;e2], m) +let mkCallAdditionOperator (g: TcGlobals) m ty1 ty2 ty3 e1 e2 = mkApps g (typedExprForIntrinsic g m g.unchecked_addition_info, [[ty1; ty2; ty3]], [e1;e2], m) let mkCallSubtractionOperator (g: TcGlobals) m ty e1 e2 = mkApps g (typedExprForIntrinsic g m g.unchecked_subtraction_info, [[ty; ty; ty]], [e1;e2], m) let mkCallMultiplyOperator (g: TcGlobals) m ty e1 e2 = mkApps g (typedExprForIntrinsic g m g.unchecked_multiply_info, [[ty; ty; ty]], [e1;e2], m) -let mkCallDivisionOperator (g: TcGlobals) m ty e1 e2 = mkApps g (typedExprForIntrinsic g m g.unchecked_division_info, [[ty; ty; ty]], [e1;e2], m) +let mkCallDivisionOperator (g: TcGlobals) m ty1 ty2 ty3 e1 e2 = mkApps g (typedExprForIntrinsic g m g.unchecked_division_info, [[ty1; ty2; ty3]], [e1;e2], m) let mkCallModulusOperator (g: TcGlobals) m ty e1 e2 = mkApps g (typedExprForIntrinsic g m g.unchecked_modulus_info, [[ty; ty; ty]], [e1;e2], m) diff --git a/src/fsharp/TastOps.fsi b/src/fsharp/TastOps.fsi index 4c7f16b651d..e37ba7e35ae 100755 --- a/src/fsharp/TastOps.fsi +++ b/src/fsharp/TastOps.fsi @@ -1825,13 +1825,13 @@ val mkCallGreaterThanOperator : TcGlobals -> range -> TType -> Ex val mkCallGreaterThanOrEqualsOperator : TcGlobals -> range -> TType -> Expr -> Expr -> Expr -val mkCallAdditionOperator : TcGlobals -> range -> TType -> Expr -> Expr -> Expr +val mkCallAdditionOperator : TcGlobals -> range -> TType -> TType -> TType -> Expr -> Expr -> Expr val mkCallSubtractionOperator : TcGlobals -> range -> TType -> Expr -> Expr -> Expr val mkCallMultiplyOperator : TcGlobals -> range -> TType -> Expr -> Expr -> Expr -val mkCallDivisionOperator : TcGlobals -> range -> TType -> Expr -> Expr -> Expr +val mkCallDivisionOperator : TcGlobals -> range -> TType -> TType -> TType -> Expr -> Expr -> Expr val mkCallModulusOperator : TcGlobals -> range -> TType -> Expr -> Expr -> Expr diff --git a/src/fsharp/symbols/Exprs.fs b/src/fsharp/symbols/Exprs.fs index fc50346f301..7fecc87f1a9 100644 --- a/src/fsharp/symbols/Exprs.fs +++ b/src/fsharp/symbols/Exprs.fs @@ -212,7 +212,7 @@ module FSharpExprConvert = let (|ILBinaryOp|_|) e = match e with - | AI_add -> Some mkCallAdditionOperator + | AI_add -> Some (fun g m ty -> mkCallAdditionOperator g m ty ty ty) | AI_add_ovf | AI_add_ovf_un -> Some mkCallAdditionChecked | AI_sub -> Some mkCallSubtractionOperator @@ -222,7 +222,7 @@ module FSharpExprConvert = | AI_mul_ovf | AI_mul_ovf_un -> Some mkCallMultiplyChecked | AI_div - | AI_div_un -> Some mkCallDivisionOperator + | AI_div_un -> Some (fun g m ty -> mkCallDivisionOperator g m ty ty ty) | AI_rem | AI_rem_un -> Some mkCallModulusOperator | AI_ceq -> Some mkCallEqualsOperator diff --git a/src/fsharp/tast.fs b/src/fsharp/tast.fs index 10f055a8685..3a6952ce0df 100644 --- a/src/fsharp/tast.fs +++ b/src/fsharp/tast.fs @@ -2397,6 +2397,13 @@ and /// Get the member name associated with the member constraint. member x.MemberName = (let (TTrait(_, nm, _, _, _, _)) = x in nm) + /// Get the member flags associated with the member constraint. + member x.MemberFlags = (let (TTrait(_, _, flags, _, _, _)) = x in flags) + + /// Get the argument types recorded in the member constraint. This includes the object instance type for + /// instance members. + 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) From 088951b942cc7ab1e81a3804b6f87407b46b7c15 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 28 Mar 2019 21:28:32 +0000 Subject: [PATCH 17/77] try to fix build --- FSharpBuild.Directory.Build.props | 4 ++-- eng/Build.ps1 | 1 - eng/build-utils.ps1 | 4 ---- eng/build.sh | 1 - fcs/Directory.Build.props | 4 ---- 5 files changed, 2 insertions(+), 12 deletions(-) diff --git a/FSharpBuild.Directory.Build.props b/FSharpBuild.Directory.Build.props index 31d24301299..93b66901c80 100644 --- a/FSharpBuild.Directory.Build.props +++ b/FSharpBuild.Directory.Build.props @@ -12,7 +12,7 @@ $(RepoRoot)src $(ArtifactsDir)\SymStore $(ArtifactsDir)\Bootstrap - $(ArtifactsDir)/fsc/Proto/netcoreapp2.1 + $(ArtifactsDir)/bin/fsc/Proto/netcoreapp2.1 4.4.0 1182;0025;$(WarningsAsErrors) @@ -80,7 +80,7 @@ - + $(ProtoOutputPath)\Microsoft.FSharp.Targets $(ProtoOutputPath)\Microsoft.FSharp.NetSdk.props $(ProtoOutputPath)\Microsoft.FSharp.NetSdk.targets diff --git a/eng/Build.ps1 b/eng/Build.ps1 index 87d0873deca..46219f4bd56 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -155,7 +155,6 @@ function BuildSolution() { /p:Publish=$publish ` /p:ContinuousIntegrationBuild=$ci ` /p:OfficialBuildId=$officialBuildId ` - /p:BootstrapBuildPath=$bootstrapDir ` /p:QuietRestore=$quietRestore ` /p:QuietRestoreBinaryLog=$binaryLog ` /p:TestTargetFrameworks=$testTargetFrameworks ` diff --git a/eng/build-utils.ps1 b/eng/build-utils.ps1 index c76c9421c19..5f5f7441712 100644 --- a/eng/build-utils.ps1 +++ b/eng/build-utils.ps1 @@ -216,10 +216,6 @@ function Run-MSBuild([string]$projectFilePath, [string]$buildArgs = "", [string] $args += " /p:ContinuousIntegrationBuild=true" } - if ($bootstrapDir -ne "") { - $args += " /p:BootstrapBuildPath=$bootstrapDir" - } - $args += " $buildArgs" $args += " $projectFilePath" $args += " $properties" diff --git a/eng/build.sh b/eng/build.sh index a7c055e7cae..34cc7cf496f 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -242,7 +242,6 @@ function BuildSolution { /p:Publish=$publish \ /p:UseRoslynAnalyzers=$enable_analyzers \ /p:ContinuousIntegrationBuild=$ci \ - /p:BootstrapBuildPath="$bootstrap_dir" \ /p:QuietRestore=$quiet_restore \ /p:QuietRestoreBinaryLog="$binary_log" \ $properties diff --git a/fcs/Directory.Build.props b/fcs/Directory.Build.props index 3179fe221f9..99ac310b2a3 100644 --- a/fcs/Directory.Build.props +++ b/fcs/Directory.Build.props @@ -20,8 +20,4 @@ true - - - $(ArtifactsBinDir)\FSharp.Build\Proto\net46 - From 9c93ac19ed2476668570566679e9b5c24125d3b9 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 28 Mar 2019 21:36:13 +0000 Subject: [PATCH 18/77] don't rebuild proto --- eng/build.sh | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/eng/build.sh b/eng/build.sh index 34cc7cf496f..47e6e57e397 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -216,17 +216,19 @@ function BuildSolution { /t:Build bootstrap_dir=$artifacts_dir/Bootstrap - mkdir -p "$bootstrap_dir" - cp $artifacts_dir/bin/fslex/$bootstrap_config/$coreclr_target_framework/* $bootstrap_dir - cp $artifacts_dir/bin/fsyacc/$bootstrap_config/$coreclr_target_framework/* $bootstrap_dir + if [ ! -d "$bootstrap_dir" ]; then + mkdir -p "$bootstrap_dir" + cp $artifacts_dir/bin/fslex/$bootstrap_config/$coreclr_target_framework/* $bootstrap_dir + cp $artifacts_dir/bin/fsyacc/$bootstrap_config/$coreclr_target_framework/* $bootstrap_dir - MSBuild "$repo_root/proto.proj" \ - /restore \ - /v:$verbosity \ - /p:Configuration=$bootstrap_config \ - /t:Build + MSBuild "$repo_root/proto.proj" \ + /restore \ + /v:$verbosity \ + /p:Configuration=$bootstrap_config \ + /t:Build - cp $artifacts_dir/bin/fsc/$bootstrap_config/netcoreapp2.1/* $bootstrap_dir + cp $artifacts_dir/bin/fsc/$bootstrap_config/netcoreapp2.1/* $bootstrap_dir + fi # do real build MSBuild $toolset_build_proj \ From ddd0ac7e57bad7b66c7ef6c5eb50cf92f5d87421 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 28 Mar 2019 21:44:55 +0000 Subject: [PATCH 19/77] trim list --- src/fsharp/ExtensionTyping.fs | 2 +- tests/FSharp.Compiler.UnitTests/ProductVersion.fs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fsharp/ExtensionTyping.fs b/src/fsharp/ExtensionTyping.fs index cd0dfdbd2e3..97c4feddbc4 100755 --- a/src/fsharp/ExtensionTyping.fs +++ b/src/fsharp/ExtensionTyping.fs @@ -45,7 +45,7 @@ module internal ExtensionTyping = // Detect the host tooling context let toolingCompatibleVersions() = if typeof.Assembly.GetName().Name = "mscorlib" then - [ "net48"; "net472"; "net471"; "net47"; "net462"; "net461"; "net452"; "net451"; "net45"; "netstandard2.0"] + [ "net471"; "net47"; "net462"; "net461"; "net452"; "net451"; "net45"; "netstandard2.0"] elif typeof.Assembly.GetName().Name = "System.Private.CoreLib" then [ "netcoreapp2.1"; "netcoreapp2.0"; "netstandard2.0"] else diff --git a/tests/FSharp.Compiler.UnitTests/ProductVersion.fs b/tests/FSharp.Compiler.UnitTests/ProductVersion.fs index 462f621941d..77ff2e60d3b 100644 --- a/tests/FSharp.Compiler.UnitTests/ProductVersion.fs +++ b/tests/FSharp.Compiler.UnitTests/ProductVersion.fs @@ -95,7 +95,7 @@ module TypeProviderDesignTimeComponentLoading = [ #if NET46 // only searched when executing on .NET Framework - for tfm in ["net48"; "net472"; "net471"; "net47"; "net462"; "net461"; "net452"; "net451"; "net45"] do + for tfm in ["net471"; "net47"; "net462"; "net461"; "net452"; "net451"; "net45"] do yield Path.Combine("typeproviders", "fsharp41", tfm) yield Path.Combine("tools", "fsharp41", tfm) #else From 67717f86770cd66a9863f16369a5c19423959575 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 28 Mar 2019 22:00:10 +0000 Subject: [PATCH 20/77] disable proto compiler for fslex/fsyacc --- FSharpBuild.Directory.Build.props | 2 +- eng/build.sh | 17 +++++++++-------- fcs/Directory.Build.props | 2 +- fcs/build.fsx | 8 ++++---- src/buildtools/buildtools.proj | 1 + 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/FSharpBuild.Directory.Build.props b/FSharpBuild.Directory.Build.props index 93b66901c80..9d1161037b8 100644 --- a/FSharpBuild.Directory.Build.props +++ b/FSharpBuild.Directory.Build.props @@ -80,7 +80,7 @@ - + $(ProtoOutputPath)\Microsoft.FSharp.Targets $(ProtoOutputPath)\Microsoft.FSharp.NetSdk.props $(ProtoOutputPath)\Microsoft.FSharp.NetSdk.targets diff --git a/eng/build.sh b/eng/build.sh index 47e6e57e397..540866dbb1f 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -209,18 +209,19 @@ function BuildSolution { # build bootstrap tools bootstrap_config=Proto - MSBuild "$repo_root/src/buildtools/buildtools.proj" \ - /restore \ - /v:$verbosity \ - /p:Configuration=$bootstrap_config \ - /t:Build - bootstrap_dir=$artifacts_dir/Bootstrap - if [ ! -d "$bootstrap_dir" ]; then + if [ ! -d "$bootstrap_dir/fslex.dll" ]; then + MSBuild "$repo_root/src/buildtools/buildtools.proj" \ + /restore \ + /v:$verbosity \ + /p:Configuration=$bootstrap_config \ + /t:Build + mkdir -p "$bootstrap_dir" cp $artifacts_dir/bin/fslex/$bootstrap_config/$coreclr_target_framework/* $bootstrap_dir cp $artifacts_dir/bin/fsyacc/$bootstrap_config/$coreclr_target_framework/* $bootstrap_dir - + fi + if [ ! -d "$bootstrap_dir/fsc.exe" ]; then MSBuild "$repo_root/proto.proj" \ /restore \ /v:$verbosity \ diff --git a/fcs/Directory.Build.props b/fcs/Directory.Build.props index 99ac310b2a3..e09dc41a671 100644 --- a/fcs/Directory.Build.props +++ b/fcs/Directory.Build.props @@ -17,7 +17,7 @@ $(ArtifactsDir)\obj $(ArtifactsBinDir)\fcs $(ArtifactsObjDir)\fcs - true + true diff --git a/fcs/build.fsx b/fcs/build.fsx index 58262f7c40a..7807d278aea 100644 --- a/fcs/build.fsx +++ b/fcs/build.fsx @@ -24,7 +24,7 @@ let isMono = false // Utilities // -------------------------------------------------------------------------------------- -let coreclrTargetFramework = "netcoreapp2.0" +let fslexyaccTargetFramework = "netcoreapp2.0" let dotnetExePath = // Build.cmd normally downloads a dotnet cli to: \artifacts\toolset\dotnet @@ -94,14 +94,14 @@ Target "BuildVersion" (fun _ -> Target "Build" (fun _ -> runDotnet __SOURCE_DIRECTORY__ "build ../src/buildtools/buildtools.proj -v n -c Proto" - let fslexPath = __SOURCE_DIRECTORY__ + "/../artifacts/bin/fslex/Proto/" + coreclrTargetFramework + "/fslex.dll" - let fsyaccPath = __SOURCE_DIRECTORY__ + "/../artifacts/bin/fsyacc/Proto/" + coreclrTargetFramework + "/fsyacc.dll" + let fslexPath = __SOURCE_DIRECTORY__ + "/../artifacts/bin/fslex/Proto/" + fslexyaccTargetFramework + "/fslex.dll" + let fsyaccPath = __SOURCE_DIRECTORY__ + "/../artifacts/bin/fsyacc/Proto/" + fslexyaccTargetFramework + "/fsyacc.dll" runDotnet __SOURCE_DIRECTORY__ (sprintf "build FSharp.Compiler.Service.sln -v n -c Release /p:FsLexPath=%s /p:FsYaccPath=%s" fslexPath fsyaccPath) ) Target "Test" (fun _ -> // This project file is used for the tests to work out reference sets - runDotnet __SOURCE_DIRECTORY__ "build ../tests/projects/Sample_NETCoreSDK_FSharp_Library_netstandard2_0/Sample_NETCoreSDK_FSharp_Library_netstandard2_0.fsproj -v n /restore /p:DisableCompilerRedirection=true" + runDotnet __SOURCE_DIRECTORY__ "build ../tests/projects/Sample_NETCoreSDK_FSharp_Library_netstandard2_0/Sample_NETCoreSDK_FSharp_Library_netstandard2_0.fsproj -v n /restore /p:DisableProtoCompiler=true" // Now run the tests let logFilePath = Path.Combine(__SOURCE_DIRECTORY__, "..", "artifacts", "TestResults", "Release", "FSharp.Compiler.Service.Test.xml") diff --git a/src/buildtools/buildtools.proj b/src/buildtools/buildtools.proj index 593f086dd07..4e6e42a27bf 100644 --- a/src/buildtools/buildtools.proj +++ b/src/buildtools/buildtools.proj @@ -2,6 +2,7 @@ Debug + true From 2eb152834ad0ae8710b699b2e6725bae696c0d94 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 28 Mar 2019 23:01:44 +0000 Subject: [PATCH 21/77] fix build --- FSharpBuild.Directory.Build.props | 2 +- src/buildtools/buildtools.proj | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/FSharpBuild.Directory.Build.props b/FSharpBuild.Directory.Build.props index 9d1161037b8..bdb8c36c398 100644 --- a/FSharpBuild.Directory.Build.props +++ b/FSharpBuild.Directory.Build.props @@ -80,7 +80,7 @@ - + $(ProtoOutputPath)\Microsoft.FSharp.Targets $(ProtoOutputPath)\Microsoft.FSharp.NetSdk.props $(ProtoOutputPath)\Microsoft.FSharp.NetSdk.targets diff --git a/src/buildtools/buildtools.proj b/src/buildtools/buildtools.proj index 4e6e42a27bf..9e7f671a351 100644 --- a/src/buildtools/buildtools.proj +++ b/src/buildtools/buildtools.proj @@ -11,23 +11,23 @@ - + - + - + - + - + From 713b40fb376d316ffe318046b51ab3787af8b2d0 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 29 Mar 2019 01:07:07 +0000 Subject: [PATCH 22/77] add buildtools props file instead --- src/buildtools/buildtools.proj | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/buildtools/buildtools.proj b/src/buildtools/buildtools.proj index 9e7f671a351..593f086dd07 100644 --- a/src/buildtools/buildtools.proj +++ b/src/buildtools/buildtools.proj @@ -2,7 +2,6 @@ Debug - true @@ -11,23 +10,23 @@ - + - + - + - + - + From feebc9936100b70ea9f23febe2516285d67dc4d0 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 29 Mar 2019 01:23:36 +0000 Subject: [PATCH 23/77] add missing file --- src/buildtools/Directory.Build.props | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/buildtools/Directory.Build.props diff --git a/src/buildtools/Directory.Build.props b/src/buildtools/Directory.Build.props new file mode 100644 index 00000000000..a2a60f76a95 --- /dev/null +++ b/src/buildtools/Directory.Build.props @@ -0,0 +1,7 @@ + + + + true + + + From 385c4d938ad267fc7285767178aea6c72616d6e5 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 29 Mar 2019 02:16:05 +0000 Subject: [PATCH 24/77] proto --- src/buildtools/buildtools.proj | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/buildtools/buildtools.proj b/src/buildtools/buildtools.proj index 593f086dd07..d96cf6a8d8c 100644 --- a/src/buildtools/buildtools.proj +++ b/src/buildtools/buildtools.proj @@ -2,7 +2,8 @@ Debug - + true + @@ -10,23 +11,23 @@ - + - + - + - + - + From 9b4ff938774a7dde85e4aac3cab66d29b83fa3de Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 29 Mar 2019 02:18:25 +0000 Subject: [PATCH 25/77] proto --- src/buildtools/Directory.Build.props | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 src/buildtools/Directory.Build.props diff --git a/src/buildtools/Directory.Build.props b/src/buildtools/Directory.Build.props deleted file mode 100644 index a2a60f76a95..00000000000 --- a/src/buildtools/Directory.Build.props +++ /dev/null @@ -1,7 +0,0 @@ - - - - true - - - From 40bb2de5d8e7ef359469e44adee0818d3cd00065 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 29 Mar 2019 02:41:20 +0000 Subject: [PATCH 26/77] simplify --- FSharpBuild.Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FSharpBuild.Directory.Build.props b/FSharpBuild.Directory.Build.props index bdb8c36c398..9d1161037b8 100644 --- a/FSharpBuild.Directory.Build.props +++ b/FSharpBuild.Directory.Build.props @@ -80,7 +80,7 @@ - + $(ProtoOutputPath)\Microsoft.FSharp.Targets $(ProtoOutputPath)\Microsoft.FSharp.NetSdk.props $(ProtoOutputPath)\Microsoft.FSharp.NetSdk.targets From 2f96a634333c1a0ea4fde0b7d84cc252a21b1183 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 29 Mar 2019 02:46:49 +0000 Subject: [PATCH 27/77] more --- FSharpTests.Directory.Build.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FSharpTests.Directory.Build.props b/FSharpTests.Directory.Build.props index 6c298fe4426..55098121979 100644 --- a/FSharpTests.Directory.Build.props +++ b/FSharpTests.Directory.Build.props @@ -33,8 +33,8 @@ <_FSharpBuildTargetFramework Condition="'$(FSharpTestCompilerVersion)' == 'net40'">net46 - <_FSharpBuildTargetFramework Condition="'$(FSharpTestCompilerVersion)' == 'coreclr'">netstandard2.0 - <_FSharpBuildBinPath>$(MSBuildThisFileDirectory)artifacts\bin\FSharp.Build\$(Configuration)\$(_FSharpBuildTargetFramework) + <_FSharpBuildTargetFramework Condition="'$(FSharpTestCompilerVersion)' == 'coreclr'">netcoreapp2.1 + <_FSharpBuildBinPath>$(MSBuildThisFileDirectory)artifacts\bin\fcs\$(Configuration)\$(_FSharpBuildTargetFramework) $(_FSharpBuildBinPath)\FSharp.Build.dll From 266d69569a86d8d216427c92cf3467dc7dbc3fd5 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 29 Mar 2019 02:50:36 +0000 Subject: [PATCH 28/77] more --- eng/build.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/build.sh b/eng/build.sh index 540866dbb1f..82908aadafc 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -210,7 +210,7 @@ function BuildSolution { # build bootstrap tools bootstrap_config=Proto bootstrap_dir=$artifacts_dir/Bootstrap - if [ ! -d "$bootstrap_dir/fslex.dll" ]; then + if [ ! -e "$bootstrap_dir/fslex.dll" ]; then MSBuild "$repo_root/src/buildtools/buildtools.proj" \ /restore \ /v:$verbosity \ @@ -221,7 +221,7 @@ function BuildSolution { cp $artifacts_dir/bin/fslex/$bootstrap_config/$coreclr_target_framework/* $bootstrap_dir cp $artifacts_dir/bin/fsyacc/$bootstrap_config/$coreclr_target_framework/* $bootstrap_dir fi - if [ ! -d "$bootstrap_dir/fsc.exe" ]; then + if [ ! -e "$bootstrap_dir/fsc.exe" ]; then MSBuild "$repo_root/proto.proj" \ /restore \ /v:$verbosity \ From 0f3ddebff891eae19dd0c6e8dc5287b6539aa854 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 29 Mar 2019 03:03:50 +0000 Subject: [PATCH 29/77] more --- eng/build.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/build.sh b/eng/build.sh index 82908aadafc..c01740d0acf 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -210,7 +210,7 @@ function BuildSolution { # build bootstrap tools bootstrap_config=Proto bootstrap_dir=$artifacts_dir/Bootstrap - if [ ! -e "$bootstrap_dir/fslex.dll" ]; then + if [ ! -f "$bootstrap_dir/fslex.dll" ]; then MSBuild "$repo_root/src/buildtools/buildtools.proj" \ /restore \ /v:$verbosity \ @@ -221,7 +221,7 @@ function BuildSolution { cp $artifacts_dir/bin/fslex/$bootstrap_config/$coreclr_target_framework/* $bootstrap_dir cp $artifacts_dir/bin/fsyacc/$bootstrap_config/$coreclr_target_framework/* $bootstrap_dir fi - if [ ! -e "$bootstrap_dir/fsc.exe" ]; then + if [ ! -f "$bootstrap_dir/fsc.exe" ]; then MSBuild "$repo_root/proto.proj" \ /restore \ /v:$verbosity \ From 7e7fbf04e9697b64dd21b7ee0e5836e5adc45d87 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 29 Mar 2019 03:10:52 +0000 Subject: [PATCH 30/77] proto --- eng/build.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/eng/build.sh b/eng/build.sh index c01740d0acf..d624578d485 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -13,6 +13,7 @@ usage() echo " --binaryLog Create MSBuild binary log (short: -bl)" echo "" echo "Actions:" + echo " --bootstrap Force the build of the bootstrap compiler" echo " --restore Restore projects required to build (short: -r)" echo " --build Build all projects (short: -b)" echo " --rebuild Rebuild all projects" @@ -54,6 +55,7 @@ test_core_clr=false configuration="Debug" verbosity='minimal' binary_log=false +force_bootstrap=false ci=false skip_analyzers=false prepare_machine=false @@ -88,6 +90,9 @@ while [[ $# > 0 ]]; do --binarylog|-bl) binary_log=true ;; + --bootstrap) + force_bootstrap=true + ;; --restore|-r) restore=true ;; @@ -210,6 +215,9 @@ function BuildSolution { # build bootstrap tools bootstrap_config=Proto bootstrap_dir=$artifacts_dir/Bootstrap + if [ $force_bootstrap == "true" ]; then + rm -fr $bootstrap_dir + fi if [ ! -f "$bootstrap_dir/fslex.dll" ]; then MSBuild "$repo_root/src/buildtools/buildtools.proj" \ /restore \ From 6b20514444df10a69e2deaa6a7bc7aeca4786a33 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 29 Mar 2019 03:21:54 +0000 Subject: [PATCH 31/77] try revert --- FSharpTests.Directory.Build.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FSharpTests.Directory.Build.props b/FSharpTests.Directory.Build.props index 55098121979..6c298fe4426 100644 --- a/FSharpTests.Directory.Build.props +++ b/FSharpTests.Directory.Build.props @@ -33,8 +33,8 @@ <_FSharpBuildTargetFramework Condition="'$(FSharpTestCompilerVersion)' == 'net40'">net46 - <_FSharpBuildTargetFramework Condition="'$(FSharpTestCompilerVersion)' == 'coreclr'">netcoreapp2.1 - <_FSharpBuildBinPath>$(MSBuildThisFileDirectory)artifacts\bin\fcs\$(Configuration)\$(_FSharpBuildTargetFramework) + <_FSharpBuildTargetFramework Condition="'$(FSharpTestCompilerVersion)' == 'coreclr'">netstandard2.0 + <_FSharpBuildBinPath>$(MSBuildThisFileDirectory)artifacts\bin\FSharp.Build\$(Configuration)\$(_FSharpBuildTargetFramework) $(_FSharpBuildBinPath)\FSharp.Build.dll From 28cdc002d5ec49c9f92b6872a731f2d04cdcbbc5 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 29 Mar 2019 03:27:50 +0000 Subject: [PATCH 32/77] proto --- FSharpTests.Directory.Build.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FSharpTests.Directory.Build.props b/FSharpTests.Directory.Build.props index 6c298fe4426..55098121979 100644 --- a/FSharpTests.Directory.Build.props +++ b/FSharpTests.Directory.Build.props @@ -33,8 +33,8 @@ <_FSharpBuildTargetFramework Condition="'$(FSharpTestCompilerVersion)' == 'net40'">net46 - <_FSharpBuildTargetFramework Condition="'$(FSharpTestCompilerVersion)' == 'coreclr'">netstandard2.0 - <_FSharpBuildBinPath>$(MSBuildThisFileDirectory)artifacts\bin\FSharp.Build\$(Configuration)\$(_FSharpBuildTargetFramework) + <_FSharpBuildTargetFramework Condition="'$(FSharpTestCompilerVersion)' == 'coreclr'">netcoreapp2.1 + <_FSharpBuildBinPath>$(MSBuildThisFileDirectory)artifacts\bin\fcs\$(Configuration)\$(_FSharpBuildTargetFramework) $(_FSharpBuildBinPath)\FSharp.Build.dll From 44472076a1b24044bec83c95f6eb9da87674bd12 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 29 Mar 2019 11:41:19 +0000 Subject: [PATCH 33/77] try again --- eng/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/build.sh b/eng/build.sh index d624578d485..2a0550e0889 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -215,7 +215,7 @@ function BuildSolution { # build bootstrap tools bootstrap_config=Proto bootstrap_dir=$artifacts_dir/Bootstrap - if [ $force_bootstrap == "true" ]; then + if [[ "$force_bootstrap" == true ]]; then rm -fr $bootstrap_dir fi if [ ! -f "$bootstrap_dir/fslex.dll" ]; then From 6563fa3c903ae68250bb77cd62c68130f4db7510 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 29 Mar 2019 11:43:50 +0000 Subject: [PATCH 34/77] try again --- eng/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/build.sh b/eng/build.sh index 2a0550e0889..a89ea576db4 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -45,7 +45,7 @@ while [[ -h "$source" ]]; do done scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" -restore=false +restore=true build=false rebuild=false pack=false From f1056d7d1c7952fb5c8abb0d015b54f6b9001b4c Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 29 Mar 2019 11:54:11 +0000 Subject: [PATCH 35/77] disable node reuse --- eng/build.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/eng/build.sh b/eng/build.sh index a89ea576db4..f3e5149ef91 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -209,9 +209,11 @@ function BuildSolution { if [[ "$ci" != true ]]; then quiet_restore=true fi - coreclr_target_framework=netcoreapp2.0 + # Node reuse fails because multiple different versions of FSharp.Build.dll get loaded into MSBuild nodes + node_reuse=false + # build bootstrap tools bootstrap_config=Proto bootstrap_dir=$artifacts_dir/Bootstrap From ea11aaefca210f5c9588df07b9bb5d767c413028 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 29 Mar 2019 13:32:53 +0000 Subject: [PATCH 36/77] fix tests --- FSharpTests.Directory.Build.props | 2 +- eng/build.sh | 12 ++++++------ src/scripts/scriptlib.fsx | 4 ---- tests/fsharp/single-test.fs | 4 +++- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/FSharpTests.Directory.Build.props b/FSharpTests.Directory.Build.props index 55098121979..f2e1653a83d 100644 --- a/FSharpTests.Directory.Build.props +++ b/FSharpTests.Directory.Build.props @@ -34,7 +34,7 @@ <_FSharpBuildTargetFramework Condition="'$(FSharpTestCompilerVersion)' == 'net40'">net46 <_FSharpBuildTargetFramework Condition="'$(FSharpTestCompilerVersion)' == 'coreclr'">netcoreapp2.1 - <_FSharpBuildBinPath>$(MSBuildThisFileDirectory)artifacts\bin\fcs\$(Configuration)\$(_FSharpBuildTargetFramework) + <_FSharpBuildBinPath>$(MSBuildThisFileDirectory)artifacts\bin\fsc\$(Configuration)\$(_FSharpBuildTargetFramework) $(_FSharpBuildBinPath)\FSharp.Build.dll diff --git a/eng/build.sh b/eng/build.sh index f3e5149ef91..43803435b56 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -209,7 +209,7 @@ function BuildSolution { if [[ "$ci" != true ]]; then quiet_restore=true fi - coreclr_target_framework=netcoreapp2.0 + fslexyacc_target_framework=netcoreapp2.0 # Node reuse fails because multiple different versions of FSharp.Build.dll get loaded into MSBuild nodes node_reuse=false @@ -228,8 +228,8 @@ function BuildSolution { /t:Build mkdir -p "$bootstrap_dir" - cp $artifacts_dir/bin/fslex/$bootstrap_config/$coreclr_target_framework/* $bootstrap_dir - cp $artifacts_dir/bin/fsyacc/$bootstrap_config/$coreclr_target_framework/* $bootstrap_dir + cp $artifacts_dir/bin/fslex/$bootstrap_config/$fslexyacc_target_framework/* $bootstrap_dir + cp $artifacts_dir/bin/fsyacc/$bootstrap_config/$fslexyacc_target_framework/* $bootstrap_dir fi if [ ! -f "$bootstrap_dir/fsc.exe" ]; then MSBuild "$repo_root/proto.proj" \ @@ -265,9 +265,9 @@ InitializeDotNetCli $restore BuildSolution if [[ "$test_core_clr" == true ]]; then - TestUsingNUnit --testproject "$repo_root/tests/FSharp.Compiler.UnitTests/FSharp.Compiler.UnitTests.fsproj" --targetframework $coreclr_target_framework - TestUsingNUnit --testproject "$repo_root/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj" --targetframework $coreclr_target_framework - TestUsingNUnit --testproject "$repo_root/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj" --targetframework $coreclr_target_framework + TestUsingNUnit --testproject "$repo_root/tests/FSharp.Compiler.UnitTests/FSharp.Compiler.UnitTests.fsproj" --targetframework netcoreapp2.0 + TestUsingNUnit --testproject "$repo_root/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj" --targetframework netcoreapp2.0 + TestUsingNUnit --testproject "$repo_root/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj" --targetframework netcoreapp2.0 fi ExitWithExitCode 0 diff --git a/src/scripts/scriptlib.fsx b/src/scripts/scriptlib.fsx index f5f9276c492..ce9ac2e3cc8 100644 --- a/src/scripts/scriptlib.fsx +++ b/src/scripts/scriptlib.fsx @@ -108,12 +108,8 @@ module Scripting = processInfo.UseShellExecute <- false processInfo.WorkingDirectory <- workDir -#if !NET46 - ignore envs // work out what to do about this -#else envs |> Map.iter (fun k v -> processInfo.EnvironmentVariables.[k] <- v) -#endif let p = new Process() p.EnableRaisingEvents <- true diff --git a/tests/fsharp/single-test.fs b/tests/fsharp/single-test.fs index b0a24ccb8e9..614183b319f 100644 --- a/tests/fsharp/single-test.fs +++ b/tests/fsharp/single-test.fs @@ -219,7 +219,8 @@ let singleTestBuildAndRunCore cfg copyFiles p = let projectBody = generateProjectArtifacts pc targetFramework cfg.BUILD_CONFIG emitFile projectFileName projectBody use testOkFile = new FileGuard(Path.Combine(directory, "test.ok")) - exec { cfg with Directory = directory } cfg.DotNetExe (sprintf "run -f %s" targetFramework) + printfn "executeFsc: cfg.DotNetExe = %s" cfg.DotNetExe + exec { cfg with Directory = directory } cfg.DotNetExe "help" // (sprintf "run -f %s" targetFramework) testOkFile.CheckExists() executeFsc compilerType targetFramework else @@ -229,6 +230,7 @@ let singleTestBuildAndRunCore cfg copyFiles p = let projectBody = generateProjectArtifacts pc targetFramework cfg.BUILD_CONFIG emitFile projectFileName projectBody use testOkFile = new FileGuard(Path.Combine(directory, "test.ok")) + printfn "executeFsi: cfg.DotNetExe = %s" cfg.DotNetExe exec { cfg with Directory = directory } cfg.DotNetExe "build /t:RunFSharpScript" testOkFile.CheckExists() executeFsi compilerType targetFramework From 7865a6a7917e4e89ab23c6250c728f48a7ea9ab6 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 29 Mar 2019 16:55:33 +0000 Subject: [PATCH 37/77] more witnesses --- src/fsharp/FSharp.Core/prim-types.fs | 1634 ++++++++++++------------- src/fsharp/FSharp.Core/prim-types.fsi | 497 +++++++- 2 files changed, 1258 insertions(+), 873 deletions(-) diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index d677b18076c..1dd157f671c 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -419,7 +419,7 @@ namespace Microsoft.FSharp.Core let inline (+..) (x:uint64) (y:uint64) = (# "add" x y : uint64 #) let inline ( *. ) (x:int64) (y:int64) = (# "mul" x y : int64 #) let inline ( *.. ) (x:uint64) (y:uint64) = (# "mul" x y : uint64 #) - let inline (^) (x:string) (y:string) = System.String.Concat(x,y) + let inline (^) (x:string) (y:string) = String.Concat(x,y) let inline (<<<) (x:int) (y:int) = (# "shl" x y : int #) let inline ( * ) (x:int) (y:int) = (# "mul" x y : int #) let inline (-) (x:int) (y:int) = (# "sub" x y : int #) @@ -600,7 +600,7 @@ namespace Microsoft.FSharp.Core then TypeNullnessSemantics_NullNotLiked else TypeNullnessSemantics_NullTrueValue - [] + type TypeInfo<'T>() = // Compute an on-demand per-instantiation static field static let info = getTypeInfo typeof<'T> @@ -834,7 +834,7 @@ namespace Microsoft.FSharp.Core // Use Ordinal comparison for strings | (:? string as x),(:? string as y) -> - System.String.CompareOrdinal(x, y) + String.CompareOrdinal(x, y) // Permit structural comparison on arrays | (:? System.Array as arr1),_ -> @@ -1108,10 +1108,10 @@ namespace Microsoft.FSharp.Core else GenericComparisonWithComparerIntrinsic comp x y when 'T : char = if (# "clt.un" x y : bool #) then (-1) else (# "cgt.un" x y : int #) when 'T : string = - // NOTE: we don't have to null check here because System.String.CompareOrdinal + // NOTE: we don't have to null check here because String.CompareOrdinal // gives reliable results on null values. - System.String.CompareOrdinal((# "" x : string #),(# "" y : string #)) - when 'T : decimal = System.Decimal.Compare((# "" x:decimal #), (# "" y:decimal #)) + String.CompareOrdinal((# "" x : string #),(# "" y : string #)) + when 'T : decimal = Decimal.Compare((# "" x:decimal #), (# "" y:decimal #)) /// Generic comparison. Implements ER mode (where "0" is returned when NaNs are compared) @@ -1186,10 +1186,10 @@ namespace Microsoft.FSharp.Core else (# "ceq" x x : int #) when 'T : char = if (# "clt.un" x y : bool #) then (-1) else (# "cgt.un" x y : int #) when 'T : string = - // NOTE: we don't have to null check here because System.String.CompareOrdinal + // NOTE: we don't have to null check here because String.CompareOrdinal // gives reliable results on null values. - System.String.CompareOrdinal((# "" x : string #),(# "" y : string #)) - when 'T : decimal = System.Decimal.Compare((# "" x:decimal #), (# "" y:decimal #)) + String.CompareOrdinal((# "" x : string #),(# "" y : string #)) + when 'T : decimal = Decimal.Compare((# "" x:decimal #), (# "" y:decimal #)) /// Generic less-than with static optimizations for some well-known cases. let inline GenericLessThanFast (x:'T) (y:'T) = @@ -1208,7 +1208,7 @@ namespace Microsoft.FSharp.Core when 'T : float = (# "clt" x y : bool #) when 'T : float32= (# "clt" x y : bool #) when 'T : char = (# "clt" x y : bool #) - when 'T : decimal = System.Decimal.op_LessThan ((# "" x:decimal #), (# "" y:decimal #)) + when 'T : decimal = Decimal.op_LessThan ((# "" x:decimal #), (# "" y:decimal #)) /// Generic greater-than with static optimizations for some well-known cases. let inline GenericGreaterThanFast (x:'T) (y:'T) = @@ -1227,7 +1227,7 @@ namespace Microsoft.FSharp.Core when 'T : float = (# "cgt" x y : bool #) when 'T : float32 = (# "cgt" x y : bool #) when 'T : char = (# "cgt" x y : bool #) - when 'T : decimal = System.Decimal.op_GreaterThan ((# "" x:decimal #), (# "" y:decimal #)) + when 'T : decimal = Decimal.op_GreaterThan ((# "" x:decimal #), (# "" y:decimal #)) /// Generic less-than-or-equal with static optimizations for some well-known cases. let inline GenericLessOrEqualFast (x:'T) (y:'T) = @@ -1246,7 +1246,7 @@ namespace Microsoft.FSharp.Core when 'T : float = not (# "cgt.un" x y : bool #) when 'T : float32 = not (# "cgt.un" x y : bool #) when 'T : char = not(# "cgt" x y : bool #) - when 'T : decimal = System.Decimal.op_LessThanOrEqual ((# "" x:decimal #), (# "" y:decimal #)) + when 'T : decimal = Decimal.op_LessThanOrEqual ((# "" x:decimal #), (# "" y:decimal #)) /// Generic greater-than-or-equal with static optimizations for some well-known cases. let inline GenericGreaterOrEqualFast (x:'T) (y:'T) = @@ -1265,7 +1265,7 @@ namespace Microsoft.FSharp.Core when 'T : float = not (# "clt.un" x y : bool #) when 'T : float32 = not (# "clt.un" x y : bool #) when 'T : char = not (# "clt" x y : bool #) - when 'T : decimal = System.Decimal.op_GreaterThanOrEqual ((# "" x:decimal #), (# "" y:decimal #)) + when 'T : decimal = Decimal.op_GreaterThanOrEqual ((# "" x:decimal #), (# "" y:decimal #)) //------------------------------------------------------------------------- @@ -1381,7 +1381,7 @@ namespace Microsoft.FSharp.Core | null,null -> true | null,_ -> false | _,null -> false - | (:? string as xs),(:? string as ys) -> System.String.Equals(xs,ys) + | (:? string as xs),(:? string as ys) -> String.Equals(xs,ys) // Permit structural equality on arrays | (:? System.Array as arr1),_ -> match arr1,yobj with @@ -1606,8 +1606,8 @@ namespace Microsoft.FSharp.Core else not (# "ceq" x x : bool #) && not (# "ceq" y y : bool #) when 'T : char = (# "ceq" x y : bool #) - when 'T : string = System.String.Equals((# "" x : string #),(# "" y : string #)) - when 'T : decimal = System.Decimal.op_Equality((# "" x:decimal #), (# "" y:decimal #)) + when 'T : string = String.Equals((# "" x : string #),(# "" y : string #)) + when 'T : decimal = Decimal.op_Equality((# "" x:decimal #), (# "" y:decimal #)) /// Implements generic equality between two values, with PER semantics for NaN (so equality on two NaN values returns false) // @@ -1628,8 +1628,8 @@ namespace Microsoft.FSharp.Core when 'T : char = (# "ceq" x y : bool #) when 'T : nativeint = (# "ceq" x y : bool #) when 'T : unativeint = (# "ceq" x y : bool #) - when 'T : string = System.String.Equals((# "" x : string #),(# "" y : string #)) - when 'T : decimal = System.Decimal.op_Equality((# "" x:decimal #), (# "" y:decimal #)) + when 'T : string = String.Equals((# "" x : string #),(# "" y : string #)) + when 'T : decimal = Decimal.op_Equality((# "" x:decimal #), (# "" y:decimal #)) /// A compiler intrinsic generated during optimization of calls to GenericEqualityIntrinsic on tuple values. // @@ -1654,8 +1654,8 @@ namespace Microsoft.FSharp.Core when 'T : char = (# "ceq" x y : bool #) when 'T : nativeint = (# "ceq" x y : bool #) when 'T : unativeint = (# "ceq" x y : bool #) - when 'T : string = System.String.Equals((# "" x : string #),(# "" y : string #)) - when 'T : decimal = System.Decimal.op_Equality((# "" x:decimal #), (# "" y:decimal #)) + when 'T : string = String.Equals((# "" x : string #),(# "" y : string #)) + when 'T : decimal = Decimal.op_Equality((# "" x:decimal #), (# "" y:decimal #)) let inline GenericInequalityFast (x:'T) (y:'T) = (not(GenericEqualityFast x y) : bool) @@ -2319,13 +2319,13 @@ namespace Microsoft.FSharp.Core let inline EnumOfValue (value : 'T) : 'Enum when 'Enum : enum<'T> = unboxPrim<'Enum>(box value) // According to the somewhat subtle rules of static optimizations, - // this condition is used whenever 'Enum is resolved to a nominal type + // this condition is used whenever 'Enum is resolved to a nominal type or witnesses are available when 'Enum : 'Enum = (retype value : 'Enum) let inline EnumToValue (enum : 'Enum) : 'T when 'Enum : enum<'T> = unboxPrim<'T>(box enum) // According to the somewhat subtle rules of static optimizations, - // this condition is used whenever 'Enum is resolved to a nominal type + // this condition is used whenever 'Enum is resolved to a nominal type or witnesses are available when 'Enum : 'Enum = (retype enum : 'T) //------------------------------------------------------------------------- @@ -2454,7 +2454,23 @@ namespace Microsoft.FSharp.Core | 'o' -> parseOctalUInt64 s p l | _ -> UInt64.Parse(s.Substring(p), NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture) - type BuiltInPrimitives = + let inline ParseByte (s:string) = (# "conv.ovf.u1" (ParseUInt32 s) : byte #) + + let inline ParseSByte (s:string) = (# "conv.ovf.i1" (ParseInt32 s) : sbyte #) + + let inline ParseInt16 (s:string) = (# "conv.ovf.i2" (ParseInt32 s) : int16 #) + + let inline ParseUInt16 (s:string) = (# "conv.ovf.u2" (ParseUInt32 s) : uint16 #) + + let inline ParseIntPtr (s:string) = (# "conv.ovf.i" (ParseInt64 s) : nativeint #) + + let inline ParseUIntPtr (s:string) = (# "conv.ovf.u" (ParseInt64 s) : unativeint #) + + let inline ParseDouble (s:string) = Double.Parse(removeUnderscores s,NumberStyles.Float, CultureInfo.InvariantCulture) + + let inline ParseSingle (s:string) = Single.Parse(removeUnderscores s,NumberStyles.Float, CultureInfo.InvariantCulture) + + type BuiltInWitnesses = static member inline op_Addition(x: int32, y: int32) = (# "add" x y : int32 #) static member inline op_Addition(x: float, y: float) = (# "add" x y : float #) static member inline op_Addition(x: float32, y: float32) = (# "add" x y : float32 #) @@ -2471,6 +2487,21 @@ namespace Microsoft.FSharp.Core static member inline op_Addition(x: string, y: string) = String.Concat(x, y) static member inline op_Addition(x: decimal, y: decimal) = Decimal.op_Addition(x, y) + static member inline op_CheckedAddition(x: int32, y: int32) = (# "add.ovf" x y : int32 #) + static member inline op_CheckedAddition(x: float, y: float) = (# "add" x y : float #) + static member inline op_CheckedAddition(x: float32, y: float32) = (# "add" x y : float32 #) + static member inline op_CheckedAddition(x: int64, y: int64) = (# "add.ovf" x y : int64 #) + static member inline op_CheckedAddition(x: uint64, y: uint64) = (# "add.ovf.un" x y : uint64 #) + static member inline op_CheckedAddition(x: uint32, y: uint32) = (# "add.ovf.un" x y : uint32 #) + static member inline op_CheckedAddition(x: nativeint, y: nativeint) = (# "add.ovf" x y : nativeint #) + static member inline op_CheckedAddition(x: unativeint, y: unativeint) = (# "add.ovf.un" x y : unativeint #) + static member inline op_CheckedAddition(x: int16, y: int16) = (# "conv.ovf.i2" (# "add.ovf" x y : int32 #) : int16 #) + static member inline op_CheckedAddition(x: uint16, y: uint16) = (# "conv.ovf.u2.un" (# "add.ovf.un" x y : uint32 #) : uint16 #) + static member inline op_CheckedAddition(x: char, y: char) = (# "conv.ovf.u2.un" (# "add.ovf.un" x y : uint32 #) : char #) + static member inline op_CheckedAddition(x: sbyte, y: sbyte) = (# "conv.ovf.i1" (# "add.ovf" x y : int32 #) : sbyte #) + static member inline op_CheckedAddition(x: byte, y: byte) = (# "conv.ovf.u1.un" (# "add.ovf.un" x y : uint32 #) : byte #) + static member inline op_CheckedAddition(x: string, y: string) = String.Concat(x, y) + static member inline op_Multiply(x: int32, y: int32) = (# "mul" x y : int32 #) static member inline op_Multiply(x: float, y: float) = (# "mul" x y : float #) static member inline op_Multiply(x: float32, y: float32) = (# "mul" x y : float32 #) @@ -2483,7 +2514,19 @@ namespace Microsoft.FSharp.Core static member inline op_Multiply(x: uint16, y: uint16) = (# "conv.u2" (# "mul" x y : uint32 #) : uint16 #) static member inline op_Multiply(x: sbyte, y: sbyte) = (# "conv.i1" (# "mul" x y : int32 #) : sbyte #) static member inline op_Multiply(x: byte, y: byte) = (# "conv.u1" (# "mul" x y : uint32 #) : byte #) - static member inline op_Multiply(x: decimal, y: decimal) = Decimal.op_Multiply(x, y) + + static member inline op_CheckedMultiply(x: int32, y: int32) = (# "mul.ovf" x y : int32 #) + static member inline op_CheckedMultiply(x: float, y: float) = (# "mul" x y : float #) + static member inline op_CheckedMultiply(x: float32, y: float32) = (# "mul" x y : float32 #) + static member inline op_CheckedMultiply(x: int64, y: int64) = (# "mul.ovf" x y : int64 #) + static member inline op_CheckedMultiply(x: uint64, y: uint64) = (# "mul.ovf.un" x y : uint64 #) + static member inline op_CheckedMultiply(x: uint32, y: uint32) = (# "mul.ovf.un" x y : uint32 #) + static member inline op_CheckedMultiply(x: nativeint, y: nativeint) = (# "mul.ovf" x y : nativeint #) + static member inline op_CheckedMultiply(x: unativeint, y: unativeint) = (# "mul.ovf.un" x y : unativeint #) + static member inline op_CheckedMultiply(x: int16, y: int16) = (# "conv.ovf.i2" (# "mul.ovf" x y : int32 #) : int16 #) + static member inline op_CheckedMultiply(x: uint16, y: uint16) = (# "conv.ovf.u2.un" (# "mul.ovf.un" x y : uint16 #) : uint16 #) + static member inline op_CheckedMultiply(x: sbyte, y: sbyte) = (# "conv.ovf.i1" (# "mul.ovf" x y : int32 #) : sbyte #) + static member inline op_CheckedMultiply(x: byte, y: byte) = (# "conv.ovf.u1.un" (# "mul.ovf.un" x y : uint32 #) : byte #) static member inline op_UnaryNegation(x: int32) = (# "neg" x : int32 #) static member inline op_UnaryNegation(x: float) = (# "neg" x : float #) @@ -2492,7 +2535,6 @@ namespace Microsoft.FSharp.Core static member inline op_UnaryNegation(x: int16) = (# "neg" x : int16 #) static member inline op_UnaryNegation(x: nativeint) = (# "neg" x : nativeint #) static member inline op_UnaryNegation(x: sbyte) = (# "neg" x : sbyte #) - static member inline op_UnaryNegation(x: decimal) = Decimal.op_UnaryNegation(x) static member inline op_Subtraction(x: int32, y: int32) = (# "sub" x y : int32 #) static member inline op_Subtraction(x: float, y: float) = (# "sub" x y : float #) @@ -2547,15 +2589,15 @@ namespace Microsoft.FSharp.Core static member inline op_LeftShift(value: sbyte, shift: int32) = (# "conv.i1" (# "shl" value (mask shift 7) : int32 #) : sbyte #) static member inline op_LeftShift(value: byte, shift: int32) = (# "conv.u1" (# "shl" value (mask shift 7) : uint32 #) : byte #) - static member inline op_RightShift(value: byte, shift: int32) = (# "shr" value (mask shift 31) : int32 #) - static member inline op_RightShift(value: byte, shift: int32) = (# "shr.un" value (mask shift 31) : uint32 #) - static member inline op_RightShift(value: byte, shift: int32) = (# "shr" value (mask shift 63) : int64 #) - static member inline op_RightShift(value: byte, shift: int32) = (# "shr.un" value (mask shift 63) : uint64 #) - static member inline op_RightShift(value: byte, shift: int32) = (# "shr" value shift : nativeint #) - static member inline op_RightShift(value: byte, shift: int32) = (# "shr.un" value shift : unativeint #) - static member inline op_RightShift(value: byte, shift: int32) = (# "conv.i2" (# "shr" value (mask shift 15) : int32 #) : int16 #) - static member inline op_RightShift(value: byte, shift: int32) = (# "conv.u2" (# "shr.un" value (mask shift 15) : uint32 #) : uint16 #) - static member inline op_RightShift(value: byte, shift: int32) = (# "conv.i1" (# "shr" value (mask shift 7 ) : int32 #) : sbyte #) + static member inline op_RightShift(value: int32, shift: int32) = (# "shr" value (mask shift 31) : int32 #) + static member inline op_RightShift(value: uint32, shift: int32) = (# "shr.un" value (mask shift 31) : uint32 #) + static member inline op_RightShift(value: int64, shift: int32) = (# "shr" value (mask shift 63) : int64 #) + static member inline op_RightShift(value: uint64, shift: int32) = (# "shr.un" value (mask shift 63) : uint64 #) + static member inline op_RightShift(value: nativeint, shift: int32) = (# "shr" value shift : nativeint #) + static member inline op_RightShift(value: unativeint, shift: int32) = (# "shr.un" value shift : unativeint #) + static member inline op_RightShift(value: int16, shift: int32) = (# "conv.i2" (# "shr" value (mask shift 15) : int32 #) : int16 #) + static member inline op_RightShift(value: uint16, shift: int32) = (# "conv.u2" (# "shr.un" value (mask shift 15) : uint32 #) : uint16 #) + static member inline op_RightShift(value: sbyte, shift: int32) = (# "conv.i1" (# "shr" value (mask shift 7 ) : int32 #) : sbyte #) static member inline op_RightShift(value: byte, shift: int32) = (# "conv.u1" (# "shr.un" value (mask shift 7 ) : uint32 #) : byte #) static member inline op_BitwiseAnd(x: int32, y: int32) = (# "and" x y : int32 #) @@ -2569,488 +2611,352 @@ namespace Microsoft.FSharp.Core static member inline op_BitwiseAnd(x: sbyte, y: sbyte) = (# "and" x y : sbyte #) static member inline op_BitwiseAnd(x: byte, y: byte) = (# "and" x y : byte #) - (* -[] -let inline (|||) (x: ^T) (y: ^T) : ^T = - (^T: (static member (|||) : ^T * ^T -> ^T) (x,y)) - when ^T : int32 = (# "or" x y : int32 #) - when ^T : int64 = (# "or" x y : int64 #) - when ^T : uint64 = (# "or" x y : uint64 #) - when ^T : uint32 = (# "or" x y : uint32 #) - when ^T : int16 = (# "or" x y : int16 #) - when ^T : uint16 = (# "or" x y : uint16 #) - when ^T : nativeint = (# "or" x y : nativeint #) - when ^T : unativeint = (# "or" x y : unativeint #) - when ^T : sbyte = (# "or" x y : sbyte #) - when ^T : byte = (# "or" x y : byte #) - - -let inline (^^^) (x: ^T) (y: ^T) : ^T = - (^T: (static member (^^^) : ^T * ^T -> ^T) (x,y)) - when ^T : int32 = (# "xor" x y : int32 #) - when ^T : int64 = (# "xor" x y : int64 #) - when ^T : uint64 = (# "xor" x y : uint64 #) - when ^T : uint32 = (# "xor" x y : uint32 #) - when ^T : int16 = (# "xor" x y : int16 #) - when ^T : uint16 = (# "xor" x y : uint16 #) - when ^T : nativeint = (# "xor" x y : nativeint #) - when ^T : unativeint = (# "xor" x y : unativeint #) - when ^T : sbyte = (# "xor" x y : sbyte #) - when ^T : byte = (# "xor" x y : byte #) - - -let inline (~~~) (value: ^T) : ^T = - (^T: (static member (~~~) : ^T -> ^T) (value)) - when ^T : int32 = (# "not" value : int32 #) - when ^T : int64 = (# "not" value : int64 #) - when ^T : uint64 = (# "not" value : uint64 #) - when ^T : uint32 = (# "not" value : uint32 #) - when ^T : nativeint = (# "not" value : nativeint #) - when ^T : unativeint = (# "not" value : unativeint #) - when ^T : int16 = (# "conv.i2" (# "not" value : int32 #) : int16 #) - when ^T : uint16 = (# "conv.u2" (# "not" value : uint32 #) : uint16 #) - when ^T : sbyte = (# "conv.i1" (# "not" value : int32 #) : sbyte #) - when ^T : byte = (# "conv.u1" (# "not" value : uint32 #) : byte #) - - -let inline byte (value: ^T) = - (^T : (static member op_Explicit: ^T -> byte) (value)) - when ^T : string = parseByte (castToString value) - when ^T : float = (# "conv.u1" value : byte #) - when ^T : float32 = (# "conv.u1" value : byte #) - when ^T : int64 = (# "conv.u1" value : byte #) - when ^T : int32 = (# "conv.u1" value : byte #) - when ^T : int16 = (# "conv.u1" value : byte #) - when ^T : nativeint = (# "conv.u1" value : byte #) - when ^T : sbyte = (# "conv.u1" value : byte #) - when ^T : uint64 = (# "conv.u1" value : byte #) - when ^T : uint32 = (# "conv.u1" value : byte #) - when ^T : uint16 = (# "conv.u1" value : byte #) - when ^T : char = (# "conv.u1" value : byte #) - when ^T : unativeint = (# "conv.u1" value : byte #) - when ^T : byte = (# "conv.u1" value : byte #) - - -let inline sbyte (value: ^T) = - (^T : (static member op_Explicit: ^T -> sbyte) (value)) - when ^T : string = ParseSByte (castToString value) - when ^T : float = (# "conv.i1" value : sbyte #) - when ^T : float32 = (# "conv.i1" value : sbyte #) - when ^T : int64 = (# "conv.i1" value : sbyte #) - when ^T : int32 = (# "conv.i1" value : sbyte #) - when ^T : int16 = (# "conv.i1" value : sbyte #) - when ^T : nativeint = (# "conv.i1" value : sbyte #) - when ^T : sbyte = (# "conv.i1" value : sbyte #) - when ^T : uint64 = (# "conv.i1" value : sbyte #) - when ^T : uint32 = (# "conv.i1" value : sbyte #) - when ^T : uint16 = (# "conv.i1" value : sbyte #) - when ^T : char = (# "conv.i1" value : sbyte #) - when ^T : unativeint = (# "conv.i1" value : sbyte #) - when ^T : byte = (# "conv.i1" value : sbyte #) - - -let inline uint16 (value: ^T) = - (^T : (static member op_Explicit: ^T -> uint16) (value)) - when ^T : string = ParseUInt16 (castToString value) - when ^T : float = (# "conv.u2" value : uint16 #) - when ^T : float32 = (# "conv.u2" value : uint16 #) - when ^T : int64 = (# "conv.u2" value : uint16 #) - when ^T : int32 = (# "conv.u2" value : uint16 #) - when ^T : int16 = (# "conv.u2" value : uint16 #) - when ^T : nativeint = (# "conv.u2" value : uint16 #) - when ^T : sbyte = (# "conv.u2" value : uint16 #) - when ^T : uint64 = (# "conv.u2" value : uint16 #) - when ^T : uint32 = (# "conv.u2" value : uint16 #) - when ^T : uint16 = (# "conv.u2" value : uint16 #) - when ^T : char = (# "conv.u2" value : uint16 #) - when ^T : unativeint = (# "conv.u2" value : uint16 #) - when ^T : byte = (# "conv.u2" value : uint16 #) - - - (^T : (static member op_Explicit: ^T -> int16) (value)) - when ^T : string = ParseInt16 (castToString value) - when ^T : float = (# "conv.i2" value : int16 #) - when ^T : float32 = (# "conv.i2" value : int16 #) - when ^T : int64 = (# "conv.i2" value : int16 #) - when ^T : int32 = (# "conv.i2" value : int16 #) - when ^T : int16 = (# "conv.i2" value : int16 #) - when ^T : nativeint = (# "conv.i2" value : int16 #) - when ^T : sbyte = (# "conv.i2" value : int16 #) - when ^T : uint64 = (# "conv.i2" value : int16 #) - when ^T : uint32 = (# "conv.i2" value : int16 #) - when ^T : uint16 = (# "conv.i2" value : int16 #) - when ^T : char = (# "conv.i2" value : int16 #) - when ^T : unativeint = (# "conv.i2" value : int16 #) - when ^T : byte = (# "conv.i2" value : int16 #) - + static member inline op_BitwiseOr(x: int32, y: int32) = (# "or" x y : int32 #) + static member inline op_BitwiseOr(x: int64, y: int64) = (# "or" x y : int64 #) + static member inline op_BitwiseOr(x: uint64, y: uint64) = (# "or" x y : uint64 #) + static member inline op_BitwiseOr(x: uint32, y: uint32) = (# "or" x y : uint32 #) + static member inline op_BitwiseOr(x: int16, y: int16) = (# "or" x y : int16 #) + static member inline op_BitwiseOr(x: uint16, y: uint16) = (# "or" x y : uint16 #) + static member inline op_BitwiseOr(x: nativeint, y: nativeint) = (# "or" x y : nativeint #) + static member inline op_BitwiseOr(x: unativeint, y: unativeint) = (# "or" x y : unativeint #) + static member inline op_BitwiseOr(x: sbyte, y: sbyte) = (# "or" x y : sbyte #) + static member inline op_BitwiseOr(x: byte, y: byte) = (# "or" x y : byte #) + + static member inline op_BitwiseExclusiveOr(x: int32, y: int32) = (# "xor" x y : int32 #) + static member inline op_BitwiseExclusiveOr(x: int64, y: int64) = (# "xor" x y : int64 #) + static member inline op_BitwiseExclusiveOr(x: uint64, y: uint64) = (# "xor" x y : uint64 #) + static member inline op_BitwiseExclusiveOr(x: uint32, y: uint32) = (# "xor" x y : uint32 #) + static member inline op_BitwiseExclusiveOr(x: int16, y: int16) = (# "xor" x y : int16 #) + static member inline op_BitwiseExclusiveOr(x: uint16, y: uint16) = (# "xor" x y : uint16 #) + static member inline op_BitwiseExclusiveOr(x: nativeint, y: nativeint) = (# "xor" x y : nativeint #) + static member inline op_BitwiseExclusiveOr(x: unativeint, y: unativeint) = (# "xor" x y : unativeint #) + static member inline op_BitwiseExclusiveOr(x: sbyte, y: sbyte) = (# "xor" x y : sbyte #) + static member inline op_BitwiseExclusiveOr(x: byte, y: byte) = (# "xor" x y : byte #) + + static member inline op_LogicalNot(value: int32) = (# "not" value : int32 #) + static member inline op_LogicalNot(value: int64) = (# "not" value : int64 #) + static member inline op_LogicalNot(value: uint64) = (# "not" value : uint64 #) + static member inline op_LogicalNot(value: uint32) = (# "not" value : uint32 #) + static member inline op_LogicalNot(value: nativeint) = (# "not" value : nativeint #) + static member inline op_LogicalNot(value: unativeint) = (# "not" value : unativeint #) + static member inline op_LogicalNot(value: int16) = (# "conv.i2" (# "not" value : int32 #) : int16 #) + static member inline op_LogicalNot(value: uint16) = (# "conv.u2" (# "not" value : uint32 #) : uint16 #) + static member inline op_LogicalNot(value: sbyte) = (# "conv.i1" (# "not" value : int32 #) : sbyte #) + static member inline op_LogicalNot(value: byte) = (# "conv.u1" (# "not" value : uint32 #) : byte #) + + static member inline op_Explicit(value: string) : byte = ParseByte value + static member inline op_Explicit(value: float) : byte = (# "conv.u1" value : byte #) + static member inline op_Explicit(value: float32) : byte = (# "conv.u1" value : byte #) + static member inline op_Explicit(value: int64) : byte = (# "conv.u1" value : byte #) + static member inline op_Explicit(value: int32) : byte = (# "conv.u1" value : byte #) + static member inline op_Explicit(value: int16) : byte = (# "conv.u1" value : byte #) + static member inline op_Explicit(value: nativeint) : byte = (# "conv.u1" value : byte #) + static member inline op_Explicit(value: sbyte) : byte = (# "conv.u1" value : byte #) + static member inline op_Explicit(value: uint64) : byte = (# "conv.u1" value : byte #) + static member inline op_Explicit(value: uint32) : byte = (# "conv.u1" value : byte #) + static member inline op_Explicit(value: uint16) : byte = (# "conv.u1" value : byte #) + static member inline op_Explicit(value: char) : byte = (# "conv.u1" value : byte #) + static member inline op_Explicit(value: unativeint) : byte = (# "conv.u1" value : byte #) + static member inline op_Explicit(value: byte) : byte = (# "conv.u1" value : byte #) + + static member inline op_Explicit(value: byte) : sbyte = ParseSByte value + static member inline op_Explicit(value: float) : sbyte = (# "conv.i1" value : sbyte #) + static member inline op_Explicit(value: float32) : sbyte = (# "conv.i1" value : sbyte #) + static member inline op_Explicit(value: int64) : sbyte = (# "conv.i1" value : sbyte #) + static member inline op_Explicit(value: int32) : sbyte = (# "conv.i1" value : sbyte #) + static member inline op_Explicit(value: int16) : sbyte = (# "conv.i1" value : sbyte #) + static member inline op_Explicit(value: nativeint) : sbyte = (# "conv.i1" value : sbyte #) + static member inline op_Explicit(value: sbyte) : sbyte = (# "conv.i1" value : sbyte #) + static member inline op_Explicit(value: uint64) : sbyte = (# "conv.i1" value : sbyte #) + static member inline op_Explicit(value: uint32) : sbyte = (# "conv.i1" value : sbyte #) + static member inline op_Explicit(value: uint16) : sbyte = (# "conv.i1" value : sbyte #) + static member inline op_Explicit(value: char) : sbyte = (# "conv.i1" value : sbyte #) + static member inline op_Explicit(value: unativeint) : sbyte = (# "conv.i1" value : sbyte #) + static member inline op_Explicit(value: byte) : sbyte = (# "conv.i1" value : sbyte #) + + static member inline op_Explicit(value: string) : uint16 = ParseUInt16 value + static member inline op_Explicit(value: float) : uint16 = (# "conv.u2" value : uint16 #) + static member inline op_Explicit(value: float32) : uint16 = (# "conv.u2" value : uint16 #) + static member inline op_Explicit(value: int64) : uint16 = (# "conv.u2" value : uint16 #) + static member inline op_Explicit(value: int32) : uint16 = (# "conv.u2" value : uint16 #) + static member inline op_Explicit(value: int16) : uint16 = (# "conv.u2" value : uint16 #) + static member inline op_Explicit(value: nativeint) : uint16 = (# "conv.u2" value : uint16 #) + static member inline op_Explicit(value: sbyte) : uint16 = (# "conv.u2" value : uint16 #) + static member inline op_Explicit(value: uint64) : uint16 = (# "conv.u2" value : uint16 #) + static member inline op_Explicit(value: uint32) : uint16 = (# "conv.u2" value : uint16 #) + static member inline op_Explicit(value: uint16) : uint16 = (# "conv.u2" value : uint16 #) + static member inline op_Explicit(value: char) : uint16 = (# "conv.u2" value : uint16 #) + static member inline op_Explicit(value: unativeint) : uint16 = (# "conv.u2" value : uint16 #) + static member inline op_Explicit(value: byte) : uint16 = (# "conv.u2" value : uint16 #) + + static member inline op_Explicit(value: string) : int16 = ParseInt16 value + static member inline op_Explicit(value: float) : int16 = (# "conv.i2" value : int16 #) + static member inline op_Explicit(value: float32) : int16 = (# "conv.i2" value : int16 #) + static member inline op_Explicit(value: int64) : int16 = (# "conv.i2" value : int16 #) + static member inline op_Explicit(value: int32) : int16 = (# "conv.i2" value : int16 #) + static member inline op_Explicit(value: int16) : int16 = (# "conv.i2" value : int16 #) + static member inline op_Explicit(value: nativeint) : int16 = (# "conv.i2" value : int16 #) + static member inline op_Explicit(value: sbyte) : int16 = (# "conv.i2" value : int16 #) + static member inline op_Explicit(value: uint64) : int16 = (# "conv.i2" value : int16 #) + static member inline op_Explicit(value: uint32) : int16 = (# "conv.i2" value : int16 #) + static member inline op_Explicit(value: uint16) : int16 = (# "conv.i2" value : int16 #) + static member inline op_Explicit(value: char) : int16 = (# "conv.i2" value : int16 #) + static member inline op_Explicit(value: unativeint) : int16 = (# "conv.i2" value : int16 #) + static member inline op_Explicit(value: byte) : int16 = (# "conv.i2" value : int16 #) + + static member inline op_Explicit(value: string) : uint32 = ParseUInt32 value + static member inline op_Explicit(value: float) : uint32 = (# "conv.u4" value : uint32 #) + static member inline op_Explicit(value: float32) : uint32 = (# "conv.u4" value : uint32 #) + static member inline op_Explicit(value: int64) : uint32 = (# "conv.u4" value : uint32 #) + static member inline op_Explicit(value: nativeint) : uint32 = (# "conv.u4" value : uint32 #) + static member inline op_Explicit(value: int32) : uint32 = (# "" value : uint32 #) + static member inline op_Explicit(value: int16) : uint32 = (# "" value : uint32 #) + static member inline op_Explicit(value: sbyte) : uint32 = (# "" value : uint32 #) + static member inline op_Explicit(value: uint64) : uint32 = (# "conv.u4" value : uint32 #) + static member inline op_Explicit(value: uint32) : uint32 = (# "conv.u4" value : uint32 #) + static member inline op_Explicit(value: uint16) : uint32 = (# "conv.u4" value : uint32 #) + static member inline op_Explicit(value: char) : uint32 = (# "conv.u4" value : uint32 #) + static member inline op_Explicit(value: unativeint) : uint32 = (# "conv.u4" value : uint32 #) + static member inline op_Explicit(value: byte) : uint32 = (# "conv.u4" value : uint32 #) + + static member inline op_Explicit(value: string) : int32 = ParseInt32 value + static member inline op_Explicit(value: float) : int32 = (# "conv.i4" value : int32 #) + static member inline op_Explicit(value: float32) : int32 = (# "conv.i4" value : int32 #) + static member inline op_Explicit(value: int64) : int32 = (# "conv.i4" value : int32 #) + static member inline op_Explicit(value: nativeint) : int32 = (# "conv.i4" value : int32 #) + static member inline op_Explicit(value: int32) : int32 = (# "" value : int32 #) + static member inline op_Explicit(value: int16) : int32 = (# "" value : int32 #) + static member inline op_Explicit(value: sbyte) : int32 = (# "" value : int32 #) + static member inline op_Explicit(value: uint64) : int32 = (# "conv.i4" value : int32 #) + static member inline op_Explicit(value: uint32) : int32 = (# "" value : int32 #) + static member inline op_Explicit(value: uint16) : int32 = (# "conv.i4" value : int32 #) + static member inline op_Explicit(value: char) : int32 = (# "conv.i4" value : int32 #) + static member inline op_Explicit(value: unativeint) : int32 = (# "conv.i4" value : int32 #) + static member inline op_Explicit(value: byte) : int32 = (# "conv.i4" value : int32 #) + + static member inline op_Explicit(value: string) : uint64 = ParseUInt64 value + static member inline op_Explicit(value: float) : uint64 = (# "conv.u8" value : uint64 #) + static member inline op_Explicit(value: float32) : uint64 = (# "conv.u8" value : uint64 #) + static member inline op_Explicit(value: int64) : uint64 = (# "" value : uint64 #) + static member inline op_Explicit(value: int32) : uint64 = (# "conv.i8" value : uint64 #) + static member inline op_Explicit(value: int16) : uint64 = (# "conv.i8" value : uint64 #) + static member inline op_Explicit(value: nativeint) : uint64 = (# "conv.i8" value : uint64 #) + static member inline op_Explicit(value: sbyte) : uint64 = (# "conv.i8" value : uint64 #) + static member inline op_Explicit(value: uint64) : uint64 = (# "" value : uint64 #) + static member inline op_Explicit(value: uint32) : uint64 = (# "conv.u8" value : uint64 #) + static member inline op_Explicit(value: uint16) : uint64 = (# "conv.u8" value : uint64 #) + static member inline op_Explicit(value: char) : uint64 = (# "conv.u8" value : uint64 #) + static member inline op_Explicit(value: unativeint) : uint64 = (# "conv.u8" value : uint64 #) + static member inline op_Explicit(value: byte) : uint64 = (# "conv.u8" value : uint64 #) + + static member inline op_Explicit(value: string) : int64 = ParseInt64 value + static member inline op_Explicit(value: string) : int64 = (# "conv.i8" value : int64 #) + static member inline op_Explicit(value: float32) : int64 = (# "conv.i8" value : int64 #) + static member inline op_Explicit(value: int64) : int64 = (# "conv.i8" value : int64 #) + static member inline op_Explicit(value: int32) : int64 = (# "conv.i8" value : int64 #) + static member inline op_Explicit(value: int16) : int64 = (# "conv.i8" value : int64 #) + static member inline op_Explicit(value: nativeint) : int64 = (# "conv.i8" value : int64 #) + static member inline op_Explicit(value: sbyte) : int64 = (# "conv.i8" value : int64 #) + static member inline op_Explicit(value: uint64) : int64 = (# "" value : int64 #) + static member inline op_Explicit(value: uint32) : int64 = (# "conv.u8" value : int64 #) + static member inline op_Explicit(value: uint16) : int64 = (# "conv.u8" value : int64 #) + static member inline op_Explicit(value: char) : int64 = (# "conv.u8" value : int64 #) + static member inline op_Explicit(value: unativeint) : int64 = (# "conv.u8" value : int64 #) + static member inline op_Explicit(value: byte) : int64 = (# "conv.u8" value : int64 #) + + static member inline op_Explicit(value: string) : float32 = ParseSingle value + static member inline op_Explicit(value: float) : float32 = (# "conv.r4" value : float32 #) + static member inline op_Explicit(value: float32) : float32 = (# "conv.r4" value : float32 #) + static member inline op_Explicit(value: int64) : float32 = (# "conv.r4" value : float32 #) + static member inline op_Explicit(value: int32) : float32 = (# "conv.r4" value : float32 #) + static member inline op_Explicit(value: int16) : float32 = (# "conv.r4" value : float32 #) + static member inline op_Explicit(value: nativeint) : float32 = (# "conv.r4" value : float32 #) + static member inline op_Explicit(value: sbyte) : float32 = (# "conv.r4" value : float32 #) + static member inline op_Explicit(value: uint64) : float32 = (# "conv.r.un conv.r4" value : float32 #) + static member inline op_Explicit(value: uint32) : float32 = (# "conv.r.un conv.r4" value : float32 #) + static member inline op_Explicit(value: uint16) : float32 = (# "conv.r.un conv.r4" value : float32 #) + static member inline op_Explicit(value: char) : float32 = (# "conv.r.un conv.r4" value : float32 #) + static member inline op_Explicit(value: unativeint) : float32 = (# "conv.r.un conv.r4" value : float32 #) + static member inline op_Explicit(value: byte) : float32 = (# "conv.r.un conv.r4" value : float32 #) + + static member inline op_Explicit(value: string) : float = ParseDouble value + static member inline op_Explicit(value: float) : float = (# "conv.r8" value : float #) + static member inline op_Explicit(value: float32) : float = (# "conv.r8" value : float #) + static member inline op_Explicit(value: int64) : float = (# "conv.r8" value : float #) + static member inline op_Explicit(value: int32) : float = (# "conv.r8" value : float #) + static member inline op_Explicit(value: int16) : float = (# "conv.r8" value : float #) + static member inline op_Explicit(value: nativeint) : float = (# "conv.r8" value : float #) + static member inline op_Explicit(value: sbyte) : float = (# "conv.r8" value : float #) + static member inline op_Explicit(value: uint64) : float = (# "conv.r.un conv.r8" value : float #) + static member inline op_Explicit(value: uint32) : float = (# "conv.r.un conv.r8" value : float #) + static member inline op_Explicit(value: uint16) : float = (# "conv.r.un conv.r8" value : float #) + static member inline op_Explicit(value: char) : float = (# "conv.r.un conv.r8" value : float #) + static member inline op_Explicit(value: unativeint) : float = (# "conv.r.un conv.r8" value : float #) + static member inline op_Explicit(value: byte) : float = (# "conv.r.un conv.r8" value : float #) + static member inline op_Explicit(value: decimal) : float = Convert.ToDouble(value) + + static member inline op_Explicit(value: string) : decimal = Decimal.Parse(value,NumberStyles.Float,CultureInfo.InvariantCulture)) + static member inline op_Explicit(value: float) : decimal = Convert.ToDecimal(value) + static member inline op_Explicit(value: float32) : decimal = Convert.ToDecimal(value) + static member inline op_Explicit(value: int64) : decimal = Convert.ToDecimal(value) + static member inline op_Explicit(value: int32) : decimal = Convert.ToDecimal(value) + static member inline op_Explicit(value: int16) : decimal = Convert.ToDecimal(value) + static member inline op_Explicit(value: nativeint) : decimal = Convert.ToDecimal(int64 value) + static member inline op_Explicit(value: sbyte) : decimal = Convert.ToDecimal(value) + static member inline op_Explicit(value: uint64) : decimal = Convert.ToDecimal(value) + static member inline op_Explicit(value: uint32) : decimal = Convert.ToDecimal(value) + static member inline op_Explicit(value: uint16) : decimal = Convert.ToDecimal(value) + static member inline op_Explicit(value: unativeint) : decimal = Convert.ToDecimal(uint64 value) + static member inline op_Explicit(value: byte) : decimal = Convert.ToDecimal(value decimal #))) + static member inline op_Explicit(value: decimal) : decimal = value + + static member inline op_Explicit(value: string) : unativeint = ParseUIntPtr value + static member inline op_Explicit(value: float) : unativeint = (# "conv.u" value : unativeint #) + static member inline op_Explicit(value: float32) : unativeint = (# "conv.u" value : unativeint #) + static member inline op_Explicit(value: int64) : unativeint = (# "conv.i" value : unativeint #) + static member inline op_Explicit(value: int32) : unativeint = (# "conv.i" value : unativeint #) + static member inline op_Explicit(value: int16) : unativeint = (# "conv.i" value : unativeint #) + static member inline op_Explicit(value: nativeint) : unativeint = (# "" value : unativeint #) + static member inline op_Explicit(value: sbyte) : unativeint = (# "conv.i" value : unativeint #) + static member inline op_Explicit(value: uint64) : unativeint = (# "conv.u" value : unativeint #) + static member inline op_Explicit(value: uint32) : unativeint = (# "conv.u" value : unativeint #) + static member inline op_Explicit(value: uint16) : unativeint = (# "conv.u" value : unativeint #) + static member inline op_Explicit(value: char) : unativeint = (# "conv.u" value : unativeint #) + static member inline op_Explicit(value: unativeint) : unativeint = (# "" value : unativeint #) + static member inline op_Explicit(value: byte) : unativeint = (# "conv.u" value : unativeint #) + + static member inline op_Explicit(value: string) : nativeint = ParseIntPtr value + static member inline op_Explicit(value: float) : nativeint = (# "conv.i" value : nativeint #) + static member inline op_Explicit(value: float32) : nativeint = (# "conv.i" value : nativeint #) + static member inline op_Explicit(value: int64) : nativeint = (# "conv.i" value : nativeint #) + static member inline op_Explicit(value: int32) : nativeint = (# "conv.i" value : nativeint #) + static member inline op_Explicit(value: int16) : nativeint = (# "conv.i" value : nativeint #) + static member inline op_Explicit(value: nativeint) : nativeint = (# "conv.i" value : nativeint #) + static member inline op_Explicit(value: sbyte) : nativeint = (# "conv.i" value : nativeint #) + static member inline op_Explicit(value: uint64) : nativeint = (# "conv.u" value : nativeint #) + static member inline op_Explicit(value: uint32) : nativeint = (# "conv.u" value : nativeint #) + static member inline op_Explicit(value: uint16) : nativeint = (# "conv.u" value : nativeint #) + static member inline op_Explicit(value: char) : nativeint = (# "conv.u" value : nativeint #) + static member inline op_Explicit(value: unativeint) : nativeint = (# "" value : nativeint #) + static member inline op_Explicit(value: byte) : nativeint = (# "conv.i" value : nativeint #) + + static member inline op_Explicit(value: string) : char = (System.Char.Parse value) + static member inline op_Explicit(value: float) : char = (# "conv.u2" value : char #) + static member inline op_Explicit(value: float32) : char = (# "conv.u2" value : char #) + static member inline op_Explicit(value: int64) : char = (# "conv.u2" value : char #) + static member inline op_Explicit(value: int32) : char = (# "conv.u2" value : char #) + static member inline op_Explicit(value: int16) : char = (# "conv.u2" value : char #) + static member inline op_Explicit(value: nativeint) : char = (# "conv.u2" value : char #) + static member inline op_Explicit(value: sbyte) : char = (# "conv.u2" value : char #) + static member inline op_Explicit(value: uint64) : char = (# "conv.u2" value : char #) + static member inline op_Explicit(value: uint32) : char = (# "conv.u2" value : char #) + static member inline op_Explicit(value: uint16) : char = (# "conv.u2" value : char #) + static member inline op_Explicit(value: char) : char = (# "conv.u2" value : char #) + static member inline op_Explicit(value: unativeint) : char = (# "conv.u2" value : char #) + static member inline op_Explicit(value: byte) : char = (# "conv.u2" value : char #) + + static member inline op_LessThan(x: bool, y: bool) = (# "clt" x y : bool #) + static member inline op_LessThan(x: sbyte, y: sbyte) = (# "clt" x y : bool #) + static member inline op_LessThan(x: int16, y: int16) = (# "clt" x y : bool #) + static member inline op_LessThan(x: int32, y: int32) = (# "clt" x y : bool #) + static member inline op_LessThan(x: int64, y: int64) = (# "clt" x y : bool #) + static member inline op_LessThan(x: byte, y: byte) = (# "clt.un" x y : bool #) + static member inline op_LessThan(x: uint16, y: uint16) = (# "clt.un" x y : bool #) + static member inline op_LessThan(x: uint32, y: uint32) = (# "clt.un" x y : bool #) + static member inline op_LessThan(x: uint64, y: uint64) = (# "clt.un" x y : bool #) + static member inline op_LessThan(x: unativeint, y: unativeint) = (# "clt.un" x y : bool #) + static member inline op_LessThan(x: nativeint, y: nativeint) = (# "clt" x y : bool #) + static member inline op_LessThan(x: float, y: float) = (# "clt" x y : bool #) + static member inline op_LessThan(x: float32, y: float32) = (# "clt" x y : bool #) + static member inline op_LessThan(x: char, y: char) = (# "clt" x y : bool #) + static member inline op_LessThan(x: decimal, y: decimal) = Decimal.op_LessThan (x, y) + static member inline op_LessThan(x: string, y: string) = (# "clt" (String.CompareOrdinal(x,y)) 0 : bool #) + + static member inline op_GreaterThan(x: bool, y: bool) = (# "cgt" x y : bool #) + static member inline op_GreaterThan(x: sbyte, y: sbyte) = (# "cgt" x y : bool #) + static member inline op_GreaterThan(x: int16, y: int16) = (# "cgt" x y : bool #) + static member inline op_GreaterThan(x: int32, y: int32) = (# "cgt" x y : bool #) + static member inline op_GreaterThan(x: int64, y: int64) = (# "cgt" x y : bool #) + static member inline op_GreaterThan(x: nativeint, y: nativeint) = (# "cgt" x y : bool #) + static member inline op_GreaterThan(x: byte, y: byte) = (# "cgt.un" x y : bool #) + static member inline op_GreaterThan(x: uint16, y: uint16) = (# "cgt.un" x y : bool #) + static member inline op_GreaterThan(x: uint32, y: uint32) = (# "cgt.un" x y : bool #) + static member inline op_GreaterThan(x: uint64, y: uint64) = (# "cgt.un" x y : bool #) + static member inline op_GreaterThan(x: unativeint, y: unativeint) = (# "cgt.un" x y : bool #) + static member inline op_GreaterThan(x: float, y: float) = (# "cgt" x y : bool #) + static member inline op_GreaterThan(x: float32, y: float32) = (# "cgt" x y : bool #) + static member inline op_GreaterThan(x: char, y: char) = (# "cgt" x y : bool #) + static member inline op_GreaterThan(x: decimal, y: decimal) = Decimal.op_GreaterThan (x, y) + static member inline op_GreaterThan(x: string, y: string) = (# "cgt" (String.CompareOrdinal(x, y)) 0 : bool #) + + static member inline op_LessThanOrEqual(x: bool, y: bool) = not (# "cgt" x y : bool #) + static member inline op_LessThanOrEqual(x: sbyte, y: sbyte) = not (# "cgt" x y : bool #) + static member inline op_LessThanOrEqual(x: int16, y: int16) = not (# "cgt" x y : bool #) + static member inline op_LessThanOrEqual(x: int32, y: int32) = not (# "cgt" x y : bool #) + static member inline op_LessThanOrEqual(x: int64, y: int64) = not (# "cgt" x y : bool #) + static member inline op_LessThanOrEqual(x: nativeint, y: nativeint) = not (# "cgt" x y : bool #) + static member inline op_LessThanOrEqual(x: byte, y: byte) = not (# "cgt.un" x y : bool #) + static member inline op_LessThanOrEqual(x: uint16, y: uint16) = not (# "cgt.un" x y : bool #) + static member inline op_LessThanOrEqual(x: uint32, y: uint32) = not (# "cgt.un" x y : bool #) + static member inline op_LessThanOrEqual(x: uint64, y: uint64) = not (# "cgt.un" x y : bool #) + static member inline op_LessThanOrEqual(x: unativeint, y: unativeint) = not (# "cgt.un" x y : bool #) + static member inline op_LessThanOrEqual(x: float, y: unativeint) = not (# "cgt.un" x y : bool #) + static member inline op_LessThanOrEqual(x: float32, y: float32) = not (# "cgt.un" x y : bool #) + static member inline op_LessThanOrEqual(x: char, y: char) = not (# "cgt" x y : bool #) + static member inline op_LessThanOrEqual(x: decimal, y: decimal) = Decimal.op_LessThanOrEqual (x, y) + static member inline op_LessThanOrEqual(x: string, y: string) = not (# "cgt" (String.CompareOrdinal(x, y)) 0 : bool #) + + static member inline op_GreaterThanOrEqual(x: bool, y: bool) = not (# "clt" x y : bool #) + static member inline op_GreaterThanOrEqual(x: sbyte, y: sbyte) = not (# "clt" x y : bool #) + static member inline op_GreaterThanOrEqual(x: int16, y: int16) = not (# "clt" x y : bool #) + static member inline op_GreaterThanOrEqual(x: int32, y: int32) = not (# "clt" x y : bool #) + static member inline op_GreaterThanOrEqual(x: int64, y: int64) = not (# "clt" x y : bool #) + static member inline op_GreaterThanOrEqual(x: nativeint, y: nativeint) = not (# "clt" x y : bool #) + static member inline op_GreaterThanOrEqual(x: byte, y: byte) = not (# "clt.un" x y : bool #) + static member inline op_GreaterThanOrEqual(x: uint16, y: uint16) = not (# "clt.un" x y : bool #) + static member inline op_GreaterThanOrEqual(x: uint32, y: uint32) = not (# "clt.un" x y : bool #) + static member inline op_GreaterThanOrEqual(x: uint64, y: uint64) = not (# "clt.un" x y : bool #) + static member inline op_GreaterThanOrEqual(x: unativeint, y: unativeint) = not (# "clt.un" x y : bool #) + static member inline op_GreaterThanOrEqual(x: float, y: float) = not (# "clt.un" x y : bool #) + static member inline op_GreaterThanOrEqual(x: float32, y: float32) = not (# "clt.un" x y : bool #) + static member inline op_GreaterThanOrEqual(x: char, y: char) = not (# "clt" x y : bool #) + static member inline op_GreaterThanOrEqual(x: decimal, y: decimal) = Decimal.op_GreaterThanOrEqual (x, y) + static member inline op_GreaterThanOrEqual(x: string, y: string) = not (# "clt" (String.CompareOrdinal(x, y)) 0 : bool #) + + static member inline op_Equality(x: bool, y: bool) = (# "ceq" x y : bool #) + static member inline op_Equality(x: sbyte, y: sbyte) = (# "ceq" x y : bool #) + static member inline op_Equality(x: int16, y: int16) = (# "ceq" x y : bool #) + static member inline op_Equality(x: int32, y: int32) = (# "ceq" x y : bool #) + static member inline op_Equality(x: int64, y: int64) = (# "ceq" x y : bool #) + static member inline op_Equality(x: byte, y: byte) = (# "ceq" x y : bool #) + static member inline op_Equality(x: uint16, y: uint16) = (# "ceq" x y : bool #) + static member inline op_Equality(x: uint32, y: uint32) = (# "ceq" x y : bool #) + static member inline op_Equality(x: uint64, y: uint64) = (# "ceq" x y : bool #) + static member inline op_Equality(x: float, y: float) = (# "ceq" x y : bool #) + static member inline op_Equality(x: float32, y: float32) = (# "ceq" x y : bool #) + static member inline op_Equality(x: char, y: char) = (# "ceq" x y : bool #) + static member inline op_Equality(x: nativeint, y: nativeint) = (# "ceq" x y : bool #) + static member inline op_Equality(x: unativeint, y: unativeint) = (# "ceq" x y : bool #) + static member inline op_Equality(x: string, y: string) = String.Equals(x, y) + static member inline op_Equality(x: decimal, y: v) = Decimal.op_Equality(x, y) + + static member inline op_Inequality(x: bool, y: bool) = not (# "ceq" x y : bool #) + static member inline op_Inequality(x: sbyte, y: sbyte) = not (# "ceq" x y : bool #) + static member inline op_Inequality(x: int16, y: int16) = not (# "ceq" x y : bool #) + static member inline op_Inequality(x: int32, y: int32) = not (# "ceq" x y : bool #) + static member inline op_Inequality(x: int64, y: int64) = not (# "ceq" x y : bool #) + static member inline op_Inequality(x: byte, y: byte) = not (# "ceq" x y : bool #) + static member inline op_Inequality(x: uint16, y: uint16) = not (# "ceq" x y : bool #) + static member inline op_Inequality(x: uint32, y: uint32) = not (# "ceq" x y : bool #) + static member inline op_Inequality(x: uint64, y: uint64) = not (# "ceq" x y : bool #) + static member inline op_Inequality(x: float, y: float) = not (# "ceq" x y : bool #) + static member inline op_Inequality(x: float32, y: float32) = not (# "ceq" x y : bool #) + static member inline op_Inequality(x: char, y: char) = not (# "ceq" x y : bool #) + static member inline op_Inequality(x: nativeint, y: nativeint) = not (# "ceq" x y : bool #) + static member inline op_Inequality(x: unativeint, y: unativeint) = not (# "ceq" x y : bool #) + static member inline op_Inequality(x: string, y: string) = not (String.Equals(x, y)) + static member inline op_Inequality(x: decimal, y: decimal) = Decimal.op_Inequality(x, y) -let inline uint32 (value: ^T) = - (^T : (static member op_Explicit: ^T -> uint32) (value)) - when ^T : string = ParseUInt32 (castToString value) - when ^T : float = (# "conv.u4" value : uint32 #) - when ^T : float32 = (# "conv.u4" value : uint32 #) - - when ^T : int64 = (# "conv.u4" value : uint32 #) - when ^T : nativeint = (# "conv.u4" value : uint32 #) - - // For integers shorter that 32 bits, we must first - // sign-widen the signed integer to 32 bits, and then - // "convert" from signed int32 to unsigned int32 - // This is a no-op on IL stack (ECMA 335 Part III 1.5 Tables 8 & 9) - when ^T : int32 = (# "" value : uint32 #) - when ^T : int16 = (# "" value : uint32 #) - when ^T : sbyte = (# "" value : uint32 #) - - when ^T : uint64 = (# "conv.u4" value : uint32 #) - when ^T : uint32 = (# "conv.u4" value : uint32 #) - when ^T : uint16 = (# "conv.u4" value : uint32 #) - when ^T : char = (# "conv.u4" value : uint32 #) - when ^T : unativeint = (# "conv.u4" value : uint32 #) - when ^T : byte = (# "conv.u4" value : uint32 #) - - -let inline int32 (value: ^T) = - (^T : (static member op_Explicit: ^T -> int32) (value)) - when ^T : string = ParseInt32 (castToString value) - when ^T : float = (# "conv.i4" value : int32 #) - when ^T : float32 = (# "conv.i4" value : int32 #) - when ^T : int64 = (# "conv.i4" value : int32 #) - when ^T : nativeint = (# "conv.i4" value : int32 #) - - // For integers shorter that 32 bits, we sign-widen the signed integer to 32 bits - // This is a no-op on IL stack (ECMA 335 Part III 1.5 Tables 8 & 9) - when ^T : int32 = (# "" value : int32 #) - when ^T : int16 = (# "" value : int32 #) - when ^T : sbyte = (# "" value : int32 #) - - when ^T : uint64 = (# "conv.i4" value : int32 #) - when ^T : uint32 = (# "" value : int32 #) // Signed<->Unsigned conversion is a no-op on IL stack - when ^T : uint16 = (# "conv.i4" value : int32 #) - when ^T : char = (# "conv.i4" value : int32 #) - when ^T : unativeint = (# "conv.i4" value : int32 #) - when ^T : byte = (# "conv.i4" value : int32 #) - - -let inline uint64 (value: ^T) = - (^T : (static member op_Explicit: ^T -> uint64) (value)) - when ^T : string = ParseUInt64 (castToString value) - when ^T : float = (# "conv.u8" value : uint64 #) - when ^T : float32 = (# "conv.u8" value : uint64 #) - - // we must first sign-widen the signed integer to 64 bits, and then - // "convert" from signed int64 to unsigned int64 - // conv.i8 sign-widens the input, and on IL stack, - // conversion from signed to unsigned is a no-op (ECMA 335 Part III 1.5 Table 8) - when ^T : int64 = (# "" value : uint64 #) - when ^T : int32 = (# "conv.i8" value : uint64 #) - when ^T : int16 = (# "conv.i8" value : uint64 #) - when ^T : nativeint = (# "conv.i8" value : uint64 #) - when ^T : sbyte = (# "conv.i8" value : uint64 #) - - - when ^T : uint64 = (# "" value : uint64 #) - when ^T : uint32 = (# "conv.u8" value : uint64 #) - when ^T : uint16 = (# "conv.u8" value : uint64 #) - when ^T : char = (# "conv.u8" value : uint64 #) - when ^T : unativeint = (# "conv.u8" value : uint64 #) - when ^T : byte = (# "conv.u8" value : uint64 #) - - -[] -[] -let inline int64 (value: ^T) = - (^T : (static member op_Explicit: ^T -> int64) (value)) - when ^T : string = ParseInt64 (castToString value) - when ^T : float = (# "conv.i8" value : int64 #) - when ^T : float32 = (# "conv.i8" value : int64 #) - when ^T : int64 = (# "conv.i8" value : int64 #) - when ^T : int32 = (# "conv.i8" value : int64 #) - when ^T : int16 = (# "conv.i8" value : int64 #) - when ^T : nativeint = (# "conv.i8" value : int64 #) - when ^T : sbyte = (# "conv.i8" value : int64 #) - - // When converting unsigned integer, we should zero-widen them, NOT sign-widen - // No-op for uint64, conv.u8 for uint32, for smaller types conv.u8 and conv.i8 are identical. - // For nativeint, conv.u8 works correctly both in 32 bit and 64 bit case. - when ^T : uint64 = (# "" value : int64 #) - when ^T : uint32 = (# "conv.u8" value : int64 #) - when ^T : uint16 = (# "conv.u8" value : int64 #) - when ^T : char = (# "conv.u8" value : int64 #) - when ^T : unativeint = (# "conv.u8" value : int64 #) - when ^T : byte = (# "conv.u8" value : int64 #) - - -[] -[] -let inline float32 (value: ^T) = - (^T : (static member op_Explicit: ^T -> float32) (value)) - when ^T : string = ParseSingle (castToString value) - when ^T : float = (# "conv.r4" value : float32 #) - // NOTE: float32 should convert its argument to 32-bit float even when applied to a higher precision float stored in a register. See devdiv2#49888. - when ^T : float32 = (# "conv.r4" value : float32 #) - when ^T : int64 = (# "conv.r4" value : float32 #) - when ^T : int32 = (# "conv.r4" value : float32 #) - when ^T : int16 = (# "conv.r4" value : float32 #) - when ^T : nativeint = (# "conv.r4" value : float32 #) - when ^T : sbyte = (# "conv.r4" value : float32 #) - when ^T : uint64 = (# "conv.r.un conv.r4" value : float32 #) - when ^T : uint32 = (# "conv.r.un conv.r4" value : float32 #) - when ^T : uint16 = (# "conv.r.un conv.r4" value : float32 #) - when ^T : char = (# "conv.r.un conv.r4" value : float32 #) - when ^T : unativeint = (# "conv.r.un conv.r4" value : float32 #) - when ^T : byte = (# "conv.r.un conv.r4" value : float32 #) - - -let inline float (value: ^T) = - (^T : (static member op_Explicit: ^T -> float) (value)) - when ^T : string = ParseDouble (castToString value) - // NOTE: float should convert its argument to 64-bit float even when applied to a higher precision float stored in a register. See devdiv2#49888. - when ^T : float = (# "conv.r8" value : float #) - when ^T : float32 = (# "conv.r8" value : float #) - when ^T : int64 = (# "conv.r8" value : float #) - when ^T : int32 = (# "conv.r8" value : float #) - when ^T : int16 = (# "conv.r8" value : float #) - when ^T : nativeint = (# "conv.r8" value : float #) - when ^T : sbyte = (# "conv.r8" value : float #) - when ^T : uint64 = (# "conv.r.un conv.r8" value : float #) - when ^T : uint32 = (# "conv.r.un conv.r8" value : float #) - when ^T : uint16 = (# "conv.r.un conv.r8" value : float #) - when ^T : char = (# "conv.r.un conv.r8" value : float #) - when ^T : unativeint = (# "conv.r.un conv.r8" value : float #) - when ^T : byte = (# "conv.r.un conv.r8" value : float #) - when ^T : decimal = (System.Convert.ToDouble((# "" value : decimal #))) - - -let inline decimal (value: ^T) = - (^T : (static member op_Explicit: ^T -> decimal) (value)) - when ^T : string = (System.Decimal.Parse(castToString value,NumberStyles.Float,CultureInfo.InvariantCulture)) - when ^T : float = (System.Convert.ToDecimal((# "" value : float #))) - when ^T : float32 = (System.Convert.ToDecimal((# "" value : float32 #))) - when ^T : int64 = (System.Convert.ToDecimal((# "" value : int64 #))) - when ^T : int32 = (System.Convert.ToDecimal((# "" value : int32 #))) - when ^T : int16 = (System.Convert.ToDecimal((# "" value : int16 #))) - when ^T : nativeint = (System.Convert.ToDecimal(int64 (# "" value : nativeint #))) - when ^T : sbyte = (System.Convert.ToDecimal((# "" value : sbyte #))) - when ^T : uint64 = (System.Convert.ToDecimal((# "" value : uint64 #))) - when ^T : uint32 = (System.Convert.ToDecimal((# "" value : uint32 #))) - when ^T : uint16 = (System.Convert.ToDecimal((# "" value : uint16 #))) - when ^T : unativeint = (System.Convert.ToDecimal(uint64 (# "" value : unativeint #))) - when ^T : byte = (System.Convert.ToDecimal((# "" value : byte #))) - when ^T : decimal = (# "" value : decimal #) - - -let inline unativeint (value: ^T) = - (^T : (static member op_Explicit: ^T -> unativeint) (value)) - when ^T : string = ParseUIntPtr (castToString value) - when ^T : float = (# "conv.u" value : unativeint #) - when ^T : float32 = (# "conv.u" value : unativeint #) - - // Narrower signed types we sign-extend. - // Same length signed types we leave as such (so -1 gets reinterpreted as unsigned MaxValue). - // Wider signed types we truncate. - // conv.i does just that for both 32 and 64 bit case of nativeint, and conversion from nativeint is no-op. - when ^T : int64 = (# "conv.i" value : unativeint #) - when ^T : int32 = (# "conv.i" value : unativeint #) - when ^T : int16 = (# "conv.i" value : unativeint #) - when ^T : nativeint = (# "" value : unativeint #) - when ^T : sbyte = (# "conv.i" value : unativeint #) - - when ^T : uint64 = (# "conv.u" value : unativeint #) - when ^T : uint32 = (# "conv.u" value : unativeint #) - when ^T : uint16 = (# "conv.u" value : unativeint #) - when ^T : char = (# "conv.u" value : unativeint #) - when ^T : unativeint = (# "" value : unativeint #) - when ^T : byte = (# "conv.u" value : unativeint #) - - -let inline nativeint (value: ^T) = - (^T : (static member op_Explicit: ^T -> nativeint) (value)) - when ^T : string = ParseIntPtr (castToString value) - when ^T : float = (# "conv.i" value : nativeint #) - when ^T : float32 = (# "conv.i" value : nativeint #) - - when ^T : int64 = (# "conv.i" value : nativeint #) - when ^T : int32 = (# "conv.i" value : nativeint #) - when ^T : int16 = (# "conv.i" value : nativeint #) - when ^T : nativeint = (# "conv.i" value : nativeint #) - when ^T : sbyte = (# "conv.i" value : nativeint #) - - // Narrower unsigned types we zero-extend. - // Same length unsigned types we leave as such (so unsigned MaxValue (all-bits-set) gets reinterpreted as -1). - // Wider unsigned types we truncate. - // conv.u does just that for both 32- and 64-bit-wide nativeint, and conversion from unativeint is no-op. - when ^T : uint64 = (# "conv.u" value : nativeint #) - when ^T : uint32 = (# "conv.u" value : nativeint #) - when ^T : uint16 = (# "conv.u" value : nativeint #) - when ^T : char = (# "conv.u" value : nativeint #) - when ^T : unativeint = (# "" value : nativeint #) - when ^T : byte = (# "conv.i" value : nativeint #) - -let inline string (value: ^T) = - anyToString "" value - // since we have static optimization conditionals for ints below, we need to special-case Enums. - // This way we'll print their symbolic value, as opposed to their integral one (Eg., "A", rather than "1") - when ^T struct = anyToString "" value - when ^T : float = (# "" value : float #).ToString("g",CultureInfo.InvariantCulture) - when ^T : float32 = (# "" value : float32 #).ToString("g",CultureInfo.InvariantCulture) - when ^T : int64 = (# "" value : int64 #).ToString("g",CultureInfo.InvariantCulture) - when ^T : int32 = (# "" value : int32 #).ToString("g",CultureInfo.InvariantCulture) - when ^T : int16 = (# "" value : int16 #).ToString("g",CultureInfo.InvariantCulture) - when ^T : nativeint = (# "" value : nativeint #).ToString() - when ^T : sbyte = (# "" value : sbyte #).ToString("g",CultureInfo.InvariantCulture) - when ^T : uint64 = (# "" value : uint64 #).ToString("g",CultureInfo.InvariantCulture) - when ^T : uint32 = (# "" value : uint32 #).ToString("g",CultureInfo.InvariantCulture) - when ^T : int16 = (# "" value : int16 #).ToString("g",CultureInfo.InvariantCulture) - when ^T : unativeint = (# "" value : unativeint #).ToString() - when ^T : byte = (# "" value : byte #).ToString("g",CultureInfo.InvariantCulture) - -let inline char (value: ^T) = - (^T : (static member op_Explicit: ^T -> char) (value)) - when ^T : string = (System.Char.Parse(castToString value)) - when ^T : float = (# "conv.u2" value : char #) - when ^T : float32 = (# "conv.u2" value : char #) - when ^T : int64 = (# "conv.u2" value : char #) - when ^T : int32 = (# "conv.u2" value : char #) - when ^T : int16 = (# "conv.u2" value : char #) - when ^T : nativeint = (# "conv.u2" value : char #) - when ^T : sbyte = (# "conv.u2" value : char #) - when ^T : uint64 = (# "conv.u2" value : char #) - when ^T : uint32 = (# "conv.u2" value : char #) - when ^T : uint16 = (# "conv.u2" value : char #) - when ^T : char = (# "conv.u2" value : char #) - when ^T : unativeint = (# "conv.u2" value : char #) - when ^T : byte = (# "conv.u2" value : char #) - - -let inline (<) (x:^T) (y:^U) = - ((^T or ^U): (static member (<) : ^T * ^U -> bool) (x,y)) - when ^T : bool = (# "clt" x y : bool #) - when ^T : sbyte = (# "clt" x y : bool #) - when ^T : int16 = (# "clt" x y : bool #) - when ^T : int32 = (# "clt" x y : bool #) - when ^T : int64 = (# "clt" x y : bool #) - when ^T : byte = (# "clt.un" x y : bool #) - when ^T : uint16 = (# "clt.un" x y : bool #) - when ^T : uint32 = (# "clt.un" x y : bool #) - when ^T : uint64 = (# "clt.un" x y : bool #) - when ^T : unativeint = (# "clt.un" x y : bool #) - when ^T : nativeint = (# "clt" x y : bool #) - when ^T : float = (# "clt" x y : bool #) - when ^T : float32= (# "clt" x y : bool #) - when ^T : char = (# "clt" x y : bool #) - when ^T : decimal = System.Decimal.op_LessThan ((# "" x:decimal #), (# "" y:decimal #)) - when ^T : string = (# "clt" (System.String.CompareOrdinal((# "" x : string #),(# "" y : string #))) 0 : bool #) - - -let inline (>) (x:^T) (y:^U) = - ((^T or ^U): (static member (>) : ^T * ^U -> bool) (x,y)) - when 'T : bool = (# "cgt" x y : bool #) - when 'T : sbyte = (# "cgt" x y : bool #) - when 'T : int16 = (# "cgt" x y : bool #) - when 'T : int32 = (# "cgt" x y : bool #) - when 'T : int64 = (# "cgt" x y : bool #) - when 'T : nativeint = (# "cgt" x y : bool #) - when 'T : byte = (# "cgt.un" x y : bool #) - when 'T : uint16 = (# "cgt.un" x y : bool #) - when 'T : uint32 = (# "cgt.un" x y : bool #) - when 'T : uint64 = (# "cgt.un" x y : bool #) - when 'T : unativeint = (# "cgt.un" x y : bool #) - when 'T : float = (# "cgt" x y : bool #) - when 'T : float32 = (# "cgt" x y : bool #) - when 'T : char = (# "cgt" x y : bool #) - when 'T : decimal = System.Decimal.op_GreaterThan ((# "" x:decimal #), (# "" y:decimal #)) - when ^T : string = (# "cgt" (System.String.CompareOrdinal((# "" x : string #),(# "" y : string #))) 0 : bool #) - - -let inline (<=) (x:^T) (y:^U) = - ((^T or ^U): (static member (<=) : ^T * ^U -> bool) (x,y)) - when 'T : bool = not (# "cgt" x y : bool #) - when 'T : sbyte = not (# "cgt" x y : bool #) - when 'T : int16 = not (# "cgt" x y : bool #) - when 'T : int32 = not (# "cgt" x y : bool #) - when 'T : int64 = not (# "cgt" x y : bool #) - when 'T : nativeint = not (# "cgt" x y : bool #) - when 'T : byte = not (# "cgt.un" x y : bool #) - when 'T : uint16 = not (# "cgt.un" x y : bool #) - when 'T : uint32 = not (# "cgt.un" x y : bool #) - when 'T : uint64 = not (# "cgt.un" x y : bool #) - when 'T : unativeint = not (# "cgt.un" x y : bool #) - when 'T : float = not (# "cgt.un" x y : bool #) - when 'T : float32 = not (# "cgt.un" x y : bool #) - when 'T : char = not (# "cgt" x y : bool #) - when 'T : decimal = System.Decimal.op_LessThanOrEqual ((# "" x:decimal #), (# "" y:decimal #)) - when ^T : string = not (# "cgt" (System.String.CompareOrdinal((# "" x : string #),(# "" y : string #))) 0 : bool #) - - -let inline (>=) (x:^T) (y:^U) = - ((^T or ^U): (static member (>=) : ^T * ^U -> bool) (x,y)) - when 'T : bool = not (# "clt" x y : bool #) - when 'T : sbyte = not (# "clt" x y : bool #) - when 'T : int16 = not (# "clt" x y : bool #) - when 'T : int32 = not (# "clt" x y : bool #) - when 'T : int64 = not (# "clt" x y : bool #) - when 'T : nativeint = not (# "clt" x y : bool #) - when 'T : byte = not (# "clt.un" x y : bool #) - when 'T : uint16 = not (# "clt.un" x y : bool #) - when 'T : uint32 = not (# "clt.un" x y : bool #) - when 'T : uint64 = not (# "clt.un" x y : bool #) - when 'T : unativeint = not (# "clt.un" x y : bool #) - when 'T : float = not (# "clt.un" x y : bool #) - when 'T : float32 = not (# "clt.un" x y : bool #) - when 'T : char = not (# "clt" x y : bool #) - when 'T : decimal = System.Decimal.op_GreaterThanOrEqual ((# "" x:decimal #), (# "" y:decimal #)) - when ^T : string = not (# "clt" (System.String.CompareOrdinal((# "" x : string #),(# "" y : string #))) 0 : bool #) - - -let inline (=) (x:^T) (y:^T) = - (^T : (static member (=) : ^T * ^T -> bool) (x,y)) - when ^T : bool = (# "ceq" x y : bool #) - when ^T : sbyte = (# "ceq" x y : bool #) - when ^T : int16 = (# "ceq" x y : bool #) - when ^T : int32 = (# "ceq" x y : bool #) - when ^T : int64 = (# "ceq" x y : bool #) - when ^T : byte = (# "ceq" x y : bool #) - when ^T : uint16 = (# "ceq" x y : bool #) - when ^T : uint32 = (# "ceq" x y : bool #) - when ^T : uint64 = (# "ceq" x y : bool #) - when ^T : float = (# "ceq" x y : bool #) - when ^T : float32 = (# "ceq" x y : bool #) - when ^T : char = (# "ceq" x y : bool #) - when ^T : nativeint = (# "ceq" x y : bool #) - when ^T : unativeint = (# "ceq" x y : bool #) - when ^T : string = System.String.Equals((# "" x : string #),(# "" y : string #)) - when ^T : decimal = System.Decimal.op_Equality((# "" x:decimal #), (# "" y:decimal #)) - - -let inline (<>) (x:^T) (y:^T) = - (^T : (static member (<>) : ^T * ^T -> bool) (x,y)) - when ^T : bool = not (# "ceq" x y : bool #) - when ^T : sbyte = not (# "ceq" x y : bool #) - when ^T : int16 = not (# "ceq" x y : bool #) - when ^T : int32 = not (# "ceq" x y : bool #) - when ^T : int64 = not (# "ceq" x y : bool #) - when ^T : byte = not (# "ceq" x y : bool #) - when ^T : uint16 = not (# "ceq" x y : bool #) - when ^T : uint32 = not (# "ceq" x y : bool #) - when ^T : uint64 = not (# "ceq" x y : bool #) - when ^T : float = not (# "ceq" x y : bool #) - when ^T : float32 = not (# "ceq" x y : bool #) - when ^T : char = not (# "ceq" x y : bool #) - when ^T : nativeint = not (# "ceq" x y : bool #) - when ^T : unativeint = not (# "ceq" x y : bool #) - when ^T : string = not (System.String.Equals((# "" x : string #),(# "" y : string #))) - when ^T : decimal = System.Decimal.op_Inequality((# "" x:decimal #), (# "" y:decimal #)) - -let inline DivideByInt< ^T when ^T : (static member DivideByInt : ^T * int -> ^T) > (x:^T) (y:int) : ^T = - DivideByIntDynamic<'T> x y - when ^T : float = (# "div" x ((# "conv.r8" (y:int) : float #)) : float #) - when ^T : float32 = (# "div" x ((# "conv.r4" (y:int) : float32 #)) : float32 #) - when ^T : decimal = System.Decimal.Divide((retype x:decimal), System.Convert.ToDecimal(y)) - -*) - - - [] type GenericZeroDynamicImplTable<'T>() = static let result : 'T = // The dynamic implementation @@ -3073,7 +2979,6 @@ let inline DivideByInt< ^T when ^T : (static member DivideByInt : ^T * int -> ^T unboxPrim<'T> (pinfo.GetValue(null,null)) static member Result : 'T = result - [] type GenericOneDynamicImplTable<'T>() = static let result : 'T = // The dynamic implementation @@ -3117,10 +3022,9 @@ let inline DivideByInt< ^T when ^T : (static member DivideByInt : ^T * int -> ^T when ^T : byte = 0uy when ^T : decimal = 0M // According to the somewhat subtle rules of static optimizations, - // this condition is used whenever ^T is resolved to a nominal type + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available when ^T : ^T = (^T : (static member Zero : ^T) ()) - let inline GenericOne< ^T when ^T : (static member One : ^T) > : ^T = GenericOneDynamic<(^T)>() when ^T : int32 = 1 @@ -3138,18 +3042,17 @@ let inline DivideByInt< ^T when ^T : (static member DivideByInt : ^T * int -> ^T when ^T : byte = 1uy when ^T : decimal = 1M // According to the somewhat subtle rules of static optimizations, - // this condition is used whenever ^T is resolved to a nominal type + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available // That is, not in the generic implementation of '+' when ^T : ^T = (^T : (static member One : ^T) ()) - [] type GenericDivideByIntDynamicImplTable<'T>() = static let result : ('T -> int -> 'T) = // The dynamic implementation let aty = typeof<'T> - if aty.Equals(typeof) then unboxPrim<_> (box (fun (x:decimal) (n:int) -> System.Decimal.Divide(x, System.Convert.ToDecimal(n)))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float) (n:int) -> (# "div" x ((# "conv.r8" n : float #)) : float #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float32) (n:int) -> (# "div" x ((# "conv.r4" n : float32 #)) : float32 #))) + if aty.Equals(typeof) then unboxPrim<_> (box (fun (x:decimal) (n:int) -> Decimal.Divide(x, Convert.ToDecimal(n)))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float) (n:int) -> (# "div" x ((# "conv.r8" n : float #)) : float #))) + elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float32) (n:int) -> (# "div" x ((# "conv.r4" n : float32 #)) : float32 #))) else match aty.GetMethod("DivideByInt",[| aty; typeof |]) with | null -> raise (NotSupportedException (SR.GetString(SR.dyInvDivByIntCoerce))) @@ -3163,156 +3066,149 @@ let inline DivideByInt< ^T when ^T : (static member DivideByInt : ^T * int -> ^T DivideByIntDynamic<'T> x y when ^T : float = (# "div" x ((# "conv.r8" (y:int) : float #)) : float #) when ^T : float32 = (# "div" x ((# "conv.r4" (y:int) : float32 #)) : float32 #) - when ^T : decimal = System.Decimal.Divide((retype x:decimal), System.Convert.ToDecimal(y)) + when ^T : decimal = Decimal.Divide((retype x:decimal), Convert.ToDecimal(y)) when ^T : ^T = (^T : (static member DivideByInt : ^T * int -> ^T) (x, y)) - // Dynamic implementation of addition operator resolution - type AdditionDynamicImplTable<'T,'U,'V>() = - static let impl : ('T -> 'U -> 'V) = + // Dynamic implementation of operator resolution, using BuiltInWitnesses as backing data + type UnaryOpDynamicImplTable<'OpInfo,'T,'U>() = + static let impl : ('T -> 'U) = // The dynamic implementation let aty = typeof<'T> let bty = typeof<'U> - let cty = typeof<'V> - let dyn() = - let ameth = aty.GetMethod("op_Addition",[| aty; bty |]) - let bmeth = if aty.Equals(bty) then null else bty.GetMethod("op_Addition",[| aty; bty |]) - match ameth,bmeth with - | null, null -> raise (NotSupportedException (SR.GetString(SR.dyInvOpAddCoerce))) - | m,null | null,m -> (fun x y -> unboxPrim<_> (m.Invoke(null,[| box x; box y |]))) - | _ -> raise (NotSupportedException (SR.GetString(SR.dyInvOpAddOverload))) - - if aty.Equals(bty) && bty.Equals(cty) then - if aty.Equals(typeof) then unboxPrim<_> (box (fun (x:sbyte) (y:sbyte) -> BuiltInPrimitives.op_Addition(x,y))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int16) (y:int16) -> BuiltInPrimitives.op_Addition(x,y))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int32) (y:int32) -> BuiltInPrimitives.op_Addition(x,y))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int64) (y:int64) -> BuiltInPrimitives.op_Addition(x,y))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:nativeint) (y:nativeint) -> BuiltInPrimitives.op_Addition(x,y))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:byte) (y:byte) -> BuiltInPrimitives.op_Addition(x,y))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint16) (y:uint16) -> BuiltInPrimitives.op_Addition(x,y))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint32) (y:uint32) -> BuiltInPrimitives.op_Addition(x,y))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint64) (y:uint64) -> BuiltInPrimitives.op_Addition(x,y))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:unativeint) (y:unativeint) -> BuiltInPrimitives.op_Addition(x,y))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float) (y:float) -> BuiltInPrimitives.op_Addition(x,y))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float32) (y:float32) -> BuiltInPrimitives.op_Addition(x,y))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:string) (y:string) -> BuiltInPrimitives.op_Addition(x,y))) - else dyn() - else dyn() - static member Impl : ('T -> 'U -> 'V) = impl + // Find the operator name + let staticBindingFlags = (BindingFlags.Static ||| BindingFlags.Public ||| BindingFlags.NonPublic) + let opNameMeth = typeof<'OpInfo>.GetMethod("get_Name", staticBindingFlags, [| |], null) + let opName = opNameMeth.Invoke(null) :?> string + let builtinNameMeth = typeof<'OpInfo>.GetMethod("get_BuiltInName", staticBindingFlags, [| |], null) + let builtinName = match builtinNameMeth with null -> opName | _ -> builtinNameMeth.Invoke(null) :?> string + + let meth = + let witnessesTy = typeof + let cmeth = + if builtinName = "op_Explicit" then + let meths = witnessesTy.GetMethods(staticBindingFlags) + let mutable res = null + for meth in meths do + if meth.Name = builtinName + && meth.GetParameters().[0].ParameterType.Equals(aty) && + && meth.ReturnType.Equals(bty) then + res <- meth + res + else + witnessesTy.GetMethod(builtinName, staticBindingFlags, [| aty |], null) - let AdditionDynamic<'T,'U,'V> x y = AdditionDynamicImplTable<'T,'U,'V>.Impl x y + match cmeth with + | null -> + let ameth = aty.GetMethod(opName,[| aty |]) + match ameth with + | null -> raise (NotSupportedException (SR.GetString(SR.dyInvOpAddCoerce))) + | res -> res + | res -> res + (fun x -> unboxPrim<_> (meth.Invoke(null,[| box x |]))) - // Dynamic implementation of checked addition operator resolution - [] - type CheckedAdditionDynamicImplTable<'T,'U,'V>() = + static member Impl : ('T -> 'U) = impl + + // Dynamic implementation of operator resolution, using BuiltInWitnesses as backing data + type BinaryOpDynamicImplTable<'OpInfo,'T,'U,'V>() = static let impl : ('T -> 'U -> 'V) = // The dynamic implementation let aty = typeof<'T> let bty = typeof<'U> let cty = typeof<'V> - let dyn() = - let ameth = aty.GetMethod("op_Addition",[| aty; bty |]) - let bmeth = if aty.Equals(bty) then null else bty.GetMethod("op_Addition",[| aty; bty |]) - match ameth,bmeth with - | null, null -> raise (NotSupportedException (SR.GetString(SR.dyInvOpAddCoerce))) - | m,null | null,m -> (fun x y -> unboxPrim<_> (m.Invoke(null,[| box x; box y |]))) - | _ -> raise (NotSupportedException (SR.GetString(SR.dyInvOpAddOverload))) - - if aty.Equals(bty) && bty.Equals(cty) then - if aty.Equals(typeof) then unboxPrim<_> (box (fun (x:sbyte) (y:sbyte) -> (# "conv.ovf.i1" (# "add.ovf" x y : int32 #) : sbyte #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int16) (y:int16) -> (# "conv.ovf.i2" (# "add.ovf" x y : int32 #) : int16 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int32) (y:int32) -> (# "add.ovf" x y : int32 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int64) (y:int64) -> (# "add.ovf" x y : int64 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:nativeint) (y:nativeint) -> (# "add.ovf" x y : nativeint #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:byte) (y:byte) -> (# "conv.ovf.u1.un" (# "add.ovf.un" x y : uint32 #) : byte #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint16) (y:uint16) -> (# "conv.ovf.u2.un" (# "add.ovf.un" x y : uint32 #) : uint16 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:char) (y:char) -> (# "conv.ovf.u2.un" (# "add.ovf.un" x y : uint32 #) : char #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint32) (y:uint32) -> (# "add.ovf.un" x y : uint32 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint64) (y:uint64) -> (# "add.ovf.un" x y : uint64 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:unativeint) (y:unativeint) -> (# "add.ovf.un" x y : unativeint #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float) (y:float) -> (# "add" x y : float #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float32) (y:float32) -> (# "add" x y : float32 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:string) (y:string) -> System.String.Concat(x,y))) - else dyn() - else dyn() + // Find the operator name + let staticBindingFlags = (BindingFlags.Static ||| BindingFlags.Public ||| BindingFlags.NonPublic) + let opNameMeth = typeof<'OpInfo>.GetMethod("get_Name", staticBindingFlags, [| |], null) + let opName = opNameMeth.Invoke(null) :?> string + let builtinNameMeth = typeof<'OpInfo>.GetMethod("get_BuiltInName", staticBindingFlags, [| |], null) + let builtinName = match builtinNameMeth with null -> opName | _ -> builtinNameMeth.Invoke(null) :?> string + + let meth = + let witnessesTy = typeof + let cmeth = witnessesTy.GetMethod(builtinName, staticBindingFlags, [| aty; bty |], null) + match cmeth with + | res -> res + | null -> + let ameth = aty.GetMethod(opName,[| aty; bty |]) + let bmeth = if aty.Equals(bty) then null else bty.GetMethod(opName,[| aty; bty |]) + match ameth, bmeth with + | null, null -> raise (NotSupportedException (SR.GetString(SR.dyInvOpAddCoerce))) + | m, null | null, m -> m + | _ -> raise (NotSupportedException (SR.GetString(SR.dyInvOpAddOverload))) + (fun x y -> unboxPrim<_> (meth.Invoke(null,[| box x; box y |]))) static member Impl : ('T -> 'U -> 'V) = impl - let CheckedAdditionDynamic<'T,'U,'V> x y = CheckedAdditionDynamicImplTable<'T,'U,'V>.Impl x y + type OpAdditionLabel = static member Name = "op_Addition" + let AdditionDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + type OpCheckedAdditionLabel = + static member Name = "op_Addition" + static member BuiltInName = "op_CheckedAddition" + let CheckedAdditionDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - // Dynamic implementation of addition operator resolution - [] - type MultiplyDynamicImplTable<'T,'U,'V>() = - static let impl : ('T -> 'U -> 'V) = - // The dynamic implementation - let aty = typeof<'T> - let bty = typeof<'U> - let cty = typeof<'V> - let dyn() = - let ameth = aty.GetMethod("op_Multiply",[| aty; bty |]) - let bmeth = if aty.Equals(bty) then null else bty.GetMethod("op_Multiply",[| aty; bty |]) - match ameth,bmeth with - | null, null -> raise (NotSupportedException (SR.GetString(SR.dyInvOpMultCoerce))) - | m,null | null,m -> (fun x y -> unboxPrim<_> (m.Invoke(null,[| box x; box y |]))) - | _ -> raise (NotSupportedException (SR.GetString(SR.dyInvOpMultOverload))) - - if aty.Equals(bty) && bty.Equals(cty) then - if aty.Equals(typeof) then unboxPrim<_> (box (fun (x:sbyte) (y:sbyte) -> BuiltInPrimitives.op_Multiply(x,y))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int16) (y:int16) -> BuiltInPrimitives.op_Multiply(x,y))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int32) (y:int32) -> BuiltInPrimitives.op_Multiply(x,y))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int64) (y:int64) -> BuiltInPrimitives.op_Multiply(x,y))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:nativeint) (y:nativeint) -> BuiltInPrimitives.op_Multiply(x,y))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:byte) (y:byte) -> BuiltInPrimitives.op_Multiply(x,y))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint16) (y:uint16) -> BuiltInPrimitives.op_Multiply(x,y))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint32) (y:uint32) -> BuiltInPrimitives.op_Multiply(x,y))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint64) (y:uint64) -> BuiltInPrimitives.op_Multiply(x,y))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:unativeint) (y:unativeint) -> BuiltInPrimitives.op_Multiply(x,y))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float) (y:float) -> BuiltInPrimitives.op_Multiply(x,y))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float32) (y:float32) -> BuiltInPrimitives.op_Multiply(x,y))) - else dyn() - else dyn() + type OpSubtractionLabel = static member Name = "op_Subtraction" + let SubtractionDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - static member Impl : ('T -> 'U -> 'V) = impl + type OpMultiplyLabel = static member Name = "op_Multiply" + let MultiplyDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - let MultiplyDynamic<'T,'U,'V> x y = MultiplyDynamicImplTable<'T,'U,'V>.Impl x y + type OpCheckedMultiplyLabel = + static member Name = "op_Multiply" + static member BuiltInName = "op_CheckedMultiply" + let CheckedMultiplyDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - // Dynamic implementation of checked addition operator resolution - [] - type CheckedMultiplyDynamicImplTable<'T,'U,'V>() = - static let impl : ('T -> 'U -> 'V) = - // The dynamic implementation - let aty = typeof<'T> - let bty = typeof<'U> - let cty = typeof<'V> - let dyn() = - let ameth = aty.GetMethod("op_Multiply",[| aty; bty |]) - let bmeth = if aty.Equals(bty) then null else bty.GetMethod("op_Multiply",[| aty; bty |]) - match ameth,bmeth with - | null, null -> raise (NotSupportedException (SR.GetString(SR.dyInvOpMultCoerce))) - | m,null | null,m -> (fun x y -> unboxPrim<_> (m.Invoke(null,[| box x; box y |]))) - | _ -> raise (NotSupportedException (SR.GetString(SR.dyInvOpMultOverload))) - - if aty.Equals(bty) && bty.Equals(cty) then - if aty.Equals(typeof) then unboxPrim<_> (box (fun (x:sbyte) (y:sbyte) -> (# "conv.ovf.i1" (# "mul.ovf" x y : int32 #) : sbyte #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int16) (y:int16) -> (# "conv.ovf.i2" (# "mul.ovf" x y : int32 #) : int16 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int32) (y:int32) -> (# "mul.ovf" x y : int32 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:int64) (y:int64) -> (# "mul.ovf" x y : int64 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:nativeint) (y:nativeint) -> (# "mul.ovf" x y : nativeint #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:byte) (y:byte) -> (# "conv.ovf.u1.un" (# "mul.ovf.un" x y : uint32 #) : byte #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint16) (y:uint16) -> (# "conv.ovf.u2.un" (# "mul.ovf.un" x y : uint16 #) : uint16 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint32) (y:uint32) -> (# "mul.ovf.un" x y : uint32 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:uint64) (y:uint64) -> (# "mul.ovf.un" x y : uint64 #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:unativeint) (y:unativeint) -> (# "mul.ovf.un" x y : unativeint #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float) (y:float) -> (# "mul" x y : float #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float32) (y:float32) -> (# "mul" x y : float32 #))) - else dyn() - else dyn() + type OpDivisionLabel = static member Name = "op_Division" + let DivisionDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - static member Impl : ('T -> 'U -> 'V) = impl + type OpModulusLabel = static member Name = "op_Modulus" + let ModulusDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + + type OpLeftShiftLabel = static member Name = "op_LeftShift" + let LeftShiftDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + + type OpRightShiftLabel = static member Name = "op_RightShift" + let RightShiftDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + + type OpBitwiseAndLabel = static member Name = "op_BitwiseAnd" + let BitwiseAndDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - let CheckedMultiplyDynamic<'T,'U,'V> x y = CheckedMultiplyDynamicImplTable<'T,'U,'V>.Impl x y + type OpBitwiseOrLabel = static member Name = "op_BitwiseOr" + let BitwiseOrDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + + type OpBitwiseAndLabel = static member Name = "op_BitwiseAnd" + let BitwiseAndDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + + type OpBitwiseExclusiveOrLabel = static member Name = "op_BitwiseExclusiveOr" + let BitwiseExclusiveOrDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + + type OpLogicalNotLabel = static member Name = "op_LogicalNot" + let LogicalNotDynamic<'T,'U> x = UnaryOpDynamicImplTable.Impl x + + type OpExplicitLabel = static member Name = "op_Explicit" + let OpExplicitDynamic<'T,'U> x y = UnaryOpDynamicImplTable.Impl x y + + type OpLessThanLabel = static member Name = "op_LessThan" + let OpLessThanDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + + type OpGreaterThanLabel = static member Name = "op_GreaterThan" + let OpGreaterThanDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + + type OpLessThanOrEqualLabel = static member Name = "op_LessThanOrEqual" + let OpLessThanOrEqualDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + + type OpGreaterThanOrEqualLabel = static member Name = "op_GreaterThanOrEqual" + let OpGreaterThanOrEqualDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + + type OpEqualityLabel = static member Name = "op_Equality" + let OpEqualityDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + + type OpInequalityLabel = static member Name = "op_Inequality" + let InequalityDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + + type OpBitwiseAndLabel = static member Name = "op_BitwiseAnd" + let BitwiseAndDynamic<'T,'U,'V> x y = BitwiseAndDynamicImplTable.Impl x y namespace Microsoft.FSharp.Core @@ -3853,7 +3749,7 @@ namespace Microsoft.FSharp.Collections let n = l.Length let txt = if n > 1000 then "Length > 1000" - else System.String.Concat( [| "Length = "; n.ToString() |]) + else String.Concat( [| "Length = "; n.ToString() |]) txt member l.Head = match l with a :: _ -> a | [] -> raise (System.InvalidOperationException(SR.GetString(SR.inputListWasEmpty))) @@ -4037,7 +3933,7 @@ namespace Microsoft.FSharp.Core let inline (<<) func2 func1 x = func2 (func1 x) - let (^) (s1: string) (s2: string) = System.String.Concat(s1, s2) + let (^) (s1: string) (s2: string) = String.Concat(s1, s2) [] let defaultArg arg defaultValue = match arg with None -> defaultValue | Some v -> v @@ -4045,9 +3941,8 @@ namespace Microsoft.FSharp.Core [] let defaultValueArg arg defaultValue = match arg with ValueNone -> defaultValue | ValueSome v -> v - [] let inline (~-) (n: ^T) : ^T = - (^T : (static member (~-) : ^T -> ^T) (n)) + UnaryNegationDynamic<(^T), (^T)> n when ^T : int32 = (# "neg" n : int32 #) when ^T : float = (# "neg" n : float #) when ^T : float32 = (# "neg" n : float32 #) @@ -4055,8 +3950,11 @@ namespace Microsoft.FSharp.Core when ^T : int16 = (# "neg" n : int16 #) when ^T : nativeint = (# "neg" n : nativeint #) when ^T : sbyte = (# "neg" n : sbyte #) - when ^T : decimal = (# "" (System.Decimal.op_UnaryNegation((# "" n : decimal #))) : ^T #) - + when ^T : decimal = (# "" (Decimal.op_UnaryNegation((# "" n : decimal #))) : ^T #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + // That is, not in the generic implementation of '*' + when ^T : ^T = (^T : (static member (~-) : ^T -> ^T) (n)) let inline (+) (x: ^T) (y: ^U) : ^V = AdditionDynamic<(^T),(^U),(^V)> x y @@ -4073,17 +3971,14 @@ namespace Microsoft.FSharp.Core when ^T : char and ^U : char = (# "conv.u2" (# "add" x y : uint32 #) : char #) when ^T : sbyte and ^U : sbyte = (# "conv.i1" (# "add" x y : int32 #) : sbyte #) when ^T : byte and ^U : byte = (# "conv.u1" (# "add" x y : uint32 #) : byte #) - when ^T : string and ^U : string = (# "" (System.String.Concat((# "" x : string #),(# "" y : string #))) : ^T #) - when ^T : decimal and ^U : decimal = (# "" (System.Decimal.op_Addition((# "" x : decimal #),(# "" y : decimal #))) : ^V #) - + when ^T : string and ^U : string = (# "" (String.Concat((# "" x : string #),(# "" y : string #))) : ^T #) + when ^T : decimal and ^U : decimal = (# "" (Decimal.op_Addition((# "" x : decimal #),(# "" y : decimal #))) : ^V #) // According to the somewhat subtle rules of static optimizations, - // this condition is used whenever ^T is resolved to a nominal type - // That is, not in the generic implementation of '+' + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available when ^T : ^T = ((^T or ^U): (static member (+) : ^T * ^U -> ^V) (x,y)) - [] let inline (-) (x: ^T) (y: ^U) : ^V = - ((^T or ^U): (static member (-) : ^T * ^U -> ^V) (x,y)) + SubtractionDynamic<(^T),(^U),(^V)> x y when ^T : int32 and ^U : int32 = (# "sub" x y : int32 #) when ^T : float and ^U : float = (# "sub" x y : float #) when ^T : float32 and ^U : float32 = (# "sub" x y : float32 #) @@ -4096,8 +3991,10 @@ namespace Microsoft.FSharp.Core when ^T : uint16 and ^U : uint16 = (# "conv.u2" (# "sub" x y : uint32 #) : uint16 #) when ^T : sbyte and ^U : sbyte = (# "conv.i1" (# "sub" x y : int32 #) : sbyte #) when ^T : byte and ^U : byte = (# "conv.u1" (# "sub" x y : uint32 #) : byte #) - when ^T : decimal and ^U : decimal = (# "" (System.Decimal.op_Subtraction((# "" x : decimal #),(# "" y : decimal #))) : ^V #) - + when ^T : decimal and ^U : decimal = (# "" (Decimal.op_Subtraction((# "" x : decimal #),(# "" y : decimal #))) : ^V #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = ((^T or ^U): (static member (-) : ^T * ^U -> ^V) (x,y)) let inline ( * ) (x: ^T) (y: ^U) : ^V = MultiplyDynamic<(^T),(^U),(^V)> x y @@ -4113,15 +4010,13 @@ namespace Microsoft.FSharp.Core when ^T : uint16 and ^U : uint16 = (# "conv.u2" (# "mul" x y : uint32 #) : uint16 #) when ^T : sbyte and ^U : sbyte = (# "conv.i1" (# "mul" x y : int32 #) : sbyte #) when ^T : byte and ^U : byte = (# "conv.u1" (# "mul" x y : uint32 #) : byte #) - when ^T : decimal and ^U : decimal = (# "" (System.Decimal.op_Multiply((# "" x : decimal #),(# "" y : decimal #))) : ^V #) + when ^T : decimal and ^U : decimal = (# "" (Decimal.op_Multiply((# "" x : decimal #),(# "" y : decimal #))) : ^V #) // According to the somewhat subtle rules of static optimizations, - // this condition is used whenever ^T is resolved to a nominal type - // That is, not in the generic implementation of '*' + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available when ^T : ^T = ((^T or ^U): (static member (*) : ^T * ^U -> ^V) (x,y)) - [] let inline ( / ) (x: ^T) (y: ^U) : ^V = - ((^T or ^U): (static member (/) : ^T * ^U -> ^V) (x,y)) + DivisionDynamic<(^T),(^U),(^V)> x y when ^T : int32 and ^U : int32 = (# "div" x y : int32 #) when ^T : float and ^U : float = (# "div" x y : float #) when ^T : float32 and ^U : float32 = (# "div" x y : float32 #) @@ -4134,11 +4029,13 @@ namespace Microsoft.FSharp.Core when ^T : uint16 and ^U : uint16 = (# "conv.u2" (# "div.un" x y : uint32 #) : uint16 #) when ^T : sbyte and ^U : sbyte = (# "conv.i1" (# "div" x y : int32 #) : sbyte #) when ^T : byte and ^U : byte = (# "conv.u1" (# "div.un" x y : uint32 #) : byte #) - when ^T : decimal and ^U : decimal = (# "" (System.Decimal.op_Division((# "" x : decimal #),(# "" y : decimal #))) : ^V #) + when ^T : decimal and ^U : decimal = (# "" (Decimal.op_Division((# "" x : decimal #),(# "" y : decimal #))) : ^V #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = ((^T or ^U): (static member (/) : ^T * ^U -> ^V) (x,y)) - [] let inline ( % ) (x: ^T) (y: ^U) : ^V = - ((^T or ^U): (static member (%) : ^T * ^U -> ^V) (x,y)) + ModulusDynamic<(^T),(^U),(^V)> x y when ^T : int32 and ^U : int32 = (# "rem" x y : int32 #) when ^T : float and ^U : float = (# "rem" x y : float #) when ^T : float32 and ^U : float32 = (# "rem" x y : float32 #) @@ -4151,11 +4048,13 @@ namespace Microsoft.FSharp.Core when ^T : uint16 and ^U : uint16 = (# "conv.u2" (# "rem.un" x y : uint32 #) : uint16 #) when ^T : sbyte and ^U : sbyte = (# "conv.i1" (# "rem" x y : int32 #) : sbyte #) when ^T : byte and ^U : byte = (# "conv.u1" (# "rem.un" x y : uint32 #) : byte #) - when ^T : decimal and ^U : decimal = (# "" (System.Decimal.op_Modulus((# "" x : decimal #),(# "" y : decimal #))) : ^V #) + when ^T : decimal and ^U : decimal = (# "" (Decimal.op_Modulus((# "" x : decimal #),(# "" y : decimal #))) : ^V #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = ((^T or ^U): (static member (%) : ^T * ^U -> ^V) (x,y)) - [] let inline (~+) (value: ^T) : ^T = - (^T: (static member (~+) : ^T -> ^T) (value)) + value when ^T : int32 = value when ^T : float = value when ^T : float32 = value @@ -4169,10 +4068,10 @@ namespace Microsoft.FSharp.Core when ^T : sbyte = value when ^T : byte = value when ^T : decimal = value + when ^T : ^T = (^T: (static member (~+) : ^T -> ^T) (value)) - [] let inline (<<<) (value: ^T) (shift:int) : ^T = - (^T: (static member (<<<) : ^T * int -> ^T) (value,shift)) + LeftShiftDynamic<(^T),int,(^T)> value shift when ^T : int32 = (# "shl" value (mask shift 31) : int #) when ^T : uint32 = (# "shl" value (mask shift 31) : uint32 #) when ^T : int64 = (# "shl" value (mask shift 63) : int64 #) @@ -4183,10 +4082,12 @@ namespace Microsoft.FSharp.Core when ^T : uint16 = (# "conv.u2" (# "shl" value (mask shift 15) : uint32 #) : uint16 #) when ^T : sbyte = (# "conv.i1" (# "shl" value (mask shift 7 ) : int32 #) : sbyte #) when ^T : byte = (# "conv.u1" (# "shl" value (mask shift 7 ) : uint32 #) : byte #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = (^T: (static member (<<<) : ^T * int -> ^T) (value,shift)) - [] let inline (>>>) (value: ^T) (shift:int) : ^T = - (^T: (static member (>>>) : ^T * int -> ^T) (value,shift)) + RightShiftDynamic<(^T),int,(^T)> value shift when ^T : int32 = (# "shr" value (mask shift 31) : int32 #) when ^T : uint32 = (# "shr.un" value (mask shift 31) : uint32 #) when ^T : int64 = (# "shr" value (mask shift 63) : int64 #) @@ -4197,10 +4098,12 @@ namespace Microsoft.FSharp.Core when ^T : uint16 = (# "conv.u2" (# "shr.un" value (mask shift 15) : uint32 #) : uint16 #) when ^T : sbyte = (# "conv.i1" (# "shr" value (mask shift 7 ) : int32 #) : sbyte #) when ^T : byte = (# "conv.u1" (# "shr.un" value (mask shift 7 ) : uint32 #) : byte #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = (^T: (static member (>>>) : ^T * int -> ^T) (value, shift)) - [] let inline (&&&) (x: ^T) (y: ^T) : ^T = - (^T: (static member (&&&) : ^T * ^T -> ^T) (x,y)) + BitwiseAndDynamic<(^T),(^T),(^T)> x y when ^T : int32 = (# "and" x y : int32 #) when ^T : int64 = (# "and" x y : int64 #) when ^T : uint64 = (# "and" x y : uint64 #) @@ -4211,10 +4114,12 @@ namespace Microsoft.FSharp.Core when ^T : unativeint = (# "and" x y : unativeint #) when ^T : sbyte = (# "and" x y : sbyte #) when ^T : byte = (# "and" x y : byte #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = (^T: (static member (&&&) : ^T * ^T -> ^T) (x, y)) - [] let inline (|||) (x: ^T) (y: ^T) : ^T = - (^T: (static member (|||) : ^T * ^T -> ^T) (x,y)) + BitwiseOrDynamic<(^T),(^T),(^T)> x y when ^T : int32 = (# "or" x y : int32 #) when ^T : int64 = (# "or" x y : int64 #) when ^T : uint64 = (# "or" x y : uint64 #) @@ -4225,10 +4130,12 @@ namespace Microsoft.FSharp.Core when ^T : unativeint = (# "or" x y : unativeint #) when ^T : sbyte = (# "or" x y : sbyte #) when ^T : byte = (# "or" x y : byte #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = (^T: (static member (|||) : ^T * ^T -> ^T) (x, y)) - [] let inline (^^^) (x: ^T) (y: ^T) : ^T = - (^T: (static member (^^^) : ^T * ^T -> ^T) (x,y)) + BitwiseExclusiveOrDynamic<(^T),(^T),(^T)> x y when ^T : int32 = (# "xor" x y : int32 #) when ^T : int64 = (# "xor" x y : int64 #) when ^T : uint64 = (# "xor" x y : uint64 #) @@ -4239,10 +4146,12 @@ namespace Microsoft.FSharp.Core when ^T : unativeint = (# "xor" x y : unativeint #) when ^T : sbyte = (# "xor" x y : sbyte #) when ^T : byte = (# "xor" x y : byte #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = (^T: (static member (^^^) : ^T * ^T -> ^T) (x, y)) - [] let inline (~~~) (value: ^T) : ^T = - (^T: (static member (~~~) : ^T -> ^T) (value)) + LogicalNotDynamic<(^T),(^T)> x y when ^T : int32 = (# "not" value : int32 #) when ^T : int64 = (# "not" value : int64 #) when ^T : uint64 = (# "not" value : uint64 #) @@ -4253,6 +4162,9 @@ namespace Microsoft.FSharp.Core when ^T : uint16 = (# "conv.u2" (# "not" value : uint32 #) : uint16 #) when ^T : sbyte = (# "conv.i1" (# "not" value : int32 #) : sbyte #) when ^T : byte = (# "conv.u1" (# "not" value : uint32 #) : byte #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = (^T: (static member (~~~) : ^T -> ^T) (value)) let inline castToString (x:'T) = (# "" x : string #) // internal @@ -4281,21 +4193,10 @@ namespace Microsoft.FSharp.Core [] let exit (exitcode:int) = System.Environment.Exit(exitcode); failwith "System.Environment.Exit did not exit!" - let inline parseByte (s:string) = (# "conv.ovf.u1" (ParseUInt32 s) : byte #) - let inline ParseSByte (s:string) = (# "conv.ovf.i1" (ParseInt32 s) : sbyte #) - let inline ParseInt16 (s:string) = (# "conv.ovf.i2" (ParseInt32 s) : int16 #) - let inline ParseUInt16 (s:string) = (# "conv.ovf.u2" (ParseUInt32 s) : uint16 #) - let inline ParseIntPtr (s:string) = (# "conv.ovf.i" (ParseInt64 s) : nativeint #) - let inline ParseUIntPtr (s:string) = (# "conv.ovf.u" (ParseInt64 s) : unativeint #) - let inline ParseDouble (s:string) = Double.Parse(removeUnderscores s,NumberStyles.Float, CultureInfo.InvariantCulture) - let inline ParseSingle (s:string) = Single.Parse(removeUnderscores s,NumberStyles.Float, CultureInfo.InvariantCulture) - - - [] [] let inline byte (value: ^T) = - (^T : (static member op_Explicit: ^T -> byte) (value)) - when ^T : string = parseByte (castToString value) + OpExplicitDynamic<(^T), byte> value + when ^T : string = ParseByte (castToString value) when ^T : float = (# "conv.u1" value : byte #) when ^T : float32 = (# "conv.u1" value : byte #) when ^T : int64 = (# "conv.u1" value : byte #) @@ -4309,11 +4210,13 @@ namespace Microsoft.FSharp.Core when ^T : char = (# "conv.u1" value : byte #) when ^T : unativeint = (# "conv.u1" value : byte #) when ^T : byte = (# "conv.u1" value : byte #) - - [] + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = (^T : (static member op_Explicit: ^T -> byte) (value)) + [] let inline sbyte (value: ^T) = - (^T : (static member op_Explicit: ^T -> sbyte) (value)) + OpExplicitDynamic<(^T), sbyte> value when ^T : string = ParseSByte (castToString value) when ^T : float = (# "conv.i1" value : sbyte #) when ^T : float32 = (# "conv.i1" value : sbyte #) @@ -4328,11 +4231,13 @@ namespace Microsoft.FSharp.Core when ^T : char = (# "conv.i1" value : sbyte #) when ^T : unativeint = (# "conv.i1" value : sbyte #) when ^T : byte = (# "conv.i1" value : sbyte #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = (^T : (static member op_Explicit: ^T -> sbyte) (value)) - [] [] let inline uint16 (value: ^T) = - (^T : (static member op_Explicit: ^T -> uint16) (value)) + OpExplicitDynamic<(^T), uint16> value when ^T : string = ParseUInt16 (castToString value) when ^T : float = (# "conv.u2" value : uint16 #) when ^T : float32 = (# "conv.u2" value : uint16 #) @@ -4347,11 +4252,13 @@ namespace Microsoft.FSharp.Core when ^T : char = (# "conv.u2" value : uint16 #) when ^T : unativeint = (# "conv.u2" value : uint16 #) when ^T : byte = (# "conv.u2" value : uint16 #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = (^T : (static member op_Explicit: ^T -> uint16) (value)) - [] [] let inline int16 (value: ^T) = - (^T : (static member op_Explicit: ^T -> int16) (value)) + OpExplicitDynamic<(^T), int16> value when ^T : string = ParseInt16 (castToString value) when ^T : float = (# "conv.i2" value : int16 #) when ^T : float32 = (# "conv.i2" value : int16 #) @@ -4366,18 +4273,18 @@ namespace Microsoft.FSharp.Core when ^T : char = (# "conv.i2" value : int16 #) when ^T : unativeint = (# "conv.i2" value : int16 #) when ^T : byte = (# "conv.i2" value : int16 #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = (^T : (static member op_Explicit: ^T -> int16) (value)) - [] [] let inline uint32 (value: ^T) = - (^T : (static member op_Explicit: ^T -> uint32) (value)) + OpExplicitDynamic<(^T), uint32> value when ^T : string = ParseUInt32 (castToString value) when ^T : float = (# "conv.u4" value : uint32 #) when ^T : float32 = (# "conv.u4" value : uint32 #) - when ^T : int64 = (# "conv.u4" value : uint32 #) when ^T : nativeint = (# "conv.u4" value : uint32 #) - // For integers shorter that 32 bits, we must first // sign-widen the signed integer to 32 bits, and then // "convert" from signed int32 to unsigned int32 @@ -4385,36 +4292,38 @@ namespace Microsoft.FSharp.Core when ^T : int32 = (# "" value : uint32 #) when ^T : int16 = (# "" value : uint32 #) when ^T : sbyte = (# "" value : uint32 #) - when ^T : uint64 = (# "conv.u4" value : uint32 #) when ^T : uint32 = (# "conv.u4" value : uint32 #) when ^T : uint16 = (# "conv.u4" value : uint32 #) when ^T : char = (# "conv.u4" value : uint32 #) when ^T : unativeint = (# "conv.u4" value : uint32 #) when ^T : byte = (# "conv.u4" value : uint32 #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = (^T : (static member op_Explicit: ^T -> uint32) (value)) - [] [] let inline int32 (value: ^T) = - (^T : (static member op_Explicit: ^T -> int32) (value)) + OpExplicitDynamic<(^T), int32> value when ^T : string = ParseInt32 (castToString value) when ^T : float = (# "conv.i4" value : int32 #) when ^T : float32 = (# "conv.i4" value : int32 #) when ^T : int64 = (# "conv.i4" value : int32 #) when ^T : nativeint = (# "conv.i4" value : int32 #) - // For integers shorter that 32 bits, we sign-widen the signed integer to 32 bits // This is a no-op on IL stack (ECMA 335 Part III 1.5 Tables 8 & 9) when ^T : int32 = (# "" value : int32 #) when ^T : int16 = (# "" value : int32 #) when ^T : sbyte = (# "" value : int32 #) - when ^T : uint64 = (# "conv.i4" value : int32 #) when ^T : uint32 = (# "" value : int32 #) // Signed<->Unsigned conversion is a no-op on IL stack when ^T : uint16 = (# "conv.i4" value : int32 #) when ^T : char = (# "conv.i4" value : int32 #) when ^T : unativeint = (# "conv.i4" value : int32 #) when ^T : byte = (# "conv.i4" value : int32 #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = (^T : (static member op_Explicit: ^T -> int32) (value)) [] let inline int value = int32 value @@ -4437,14 +4346,12 @@ namespace Microsoft.FSharp.Core [] let nanf = System.Single.NaN - [] [] let inline uint64 (value: ^T) = - (^T : (static member op_Explicit: ^T -> uint64) (value)) + OpExplicitDynamic<(^T), uint64> value when ^T : string = ParseUInt64 (castToString value) when ^T : float = (# "conv.u8" value : uint64 #) when ^T : float32 = (# "conv.u8" value : uint64 #) - // we must first sign-widen the signed integer to 64 bits, and then // "convert" from signed int64 to unsigned int64 // conv.i8 sign-widens the input, and on IL stack, @@ -4454,19 +4361,19 @@ namespace Microsoft.FSharp.Core when ^T : int16 = (# "conv.i8" value : uint64 #) when ^T : nativeint = (# "conv.i8" value : uint64 #) when ^T : sbyte = (# "conv.i8" value : uint64 #) - - when ^T : uint64 = (# "" value : uint64 #) when ^T : uint32 = (# "conv.u8" value : uint64 #) when ^T : uint16 = (# "conv.u8" value : uint64 #) when ^T : char = (# "conv.u8" value : uint64 #) when ^T : unativeint = (# "conv.u8" value : uint64 #) when ^T : byte = (# "conv.u8" value : uint64 #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = (^T : (static member op_Explicit: ^T -> uint64) (value)) - [] [] let inline int64 (value: ^T) = - (^T : (static member op_Explicit: ^T -> int64) (value)) + OpExplicitDynamic<(^T), int64> value when ^T : string = ParseInt64 (castToString value) when ^T : float = (# "conv.i8" value : int64 #) when ^T : float32 = (# "conv.i8" value : int64 #) @@ -4475,7 +4382,6 @@ namespace Microsoft.FSharp.Core when ^T : int16 = (# "conv.i8" value : int64 #) when ^T : nativeint = (# "conv.i8" value : int64 #) when ^T : sbyte = (# "conv.i8" value : int64 #) - // When converting unsigned integer, we should zero-widen them, NOT sign-widen // No-op for uint64, conv.u8 for uint32, for smaller types conv.u8 and conv.i8 are identical. // For nativeint, conv.u8 works correctly both in 32 bit and 64 bit case. @@ -4485,11 +4391,13 @@ namespace Microsoft.FSharp.Core when ^T : char = (# "conv.u8" value : int64 #) when ^T : unativeint = (# "conv.u8" value : int64 #) when ^T : byte = (# "conv.u8" value : int64 #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = (^T : (static member op_Explicit: ^T -> int64) (value)) - [] [] let inline float32 (value: ^T) = - (^T : (static member op_Explicit: ^T -> float32) (value)) + OpExplicitDynamic<(^T), float32> value when ^T : string = ParseSingle (castToString value) when ^T : float = (# "conv.r4" value : float32 #) // NOTE: float32 should convert its argument to 32-bit float even when applied to a higher precision float stored in a register. See devdiv2#49888. @@ -4505,11 +4413,13 @@ namespace Microsoft.FSharp.Core when ^T : char = (# "conv.r.un conv.r4" value : float32 #) when ^T : unativeint = (# "conv.r.un conv.r4" value : float32 #) when ^T : byte = (# "conv.r.un conv.r4" value : float32 #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = (^T : (static member op_Explicit: ^T -> float32) (value)) - [] [] let inline float (value: ^T) = - (^T : (static member op_Explicit: ^T -> float) (value)) + OpExplicitDynamic<(^T), float> value when ^T : string = ParseDouble (castToString value) // NOTE: float should convert its argument to 64-bit float even when applied to a higher precision float stored in a register. See devdiv2#49888. when ^T : float = (# "conv.r8" value : float #) @@ -4525,35 +4435,38 @@ namespace Microsoft.FSharp.Core when ^T : char = (# "conv.r.un conv.r8" value : float #) when ^T : unativeint = (# "conv.r.un conv.r8" value : float #) when ^T : byte = (# "conv.r.un conv.r8" value : float #) - when ^T : decimal = (System.Convert.ToDouble((# "" value : decimal #))) + when ^T : decimal = (Convert.ToDouble((# "" value : decimal #))) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = (^T : (static member op_Explicit: ^T -> float) (value)) - [] [] let inline decimal (value: ^T) = - (^T : (static member op_Explicit: ^T -> decimal) (value)) - when ^T : string = (System.Decimal.Parse(castToString value,NumberStyles.Float,CultureInfo.InvariantCulture)) - when ^T : float = (System.Convert.ToDecimal((# "" value : float #))) - when ^T : float32 = (System.Convert.ToDecimal((# "" value : float32 #))) - when ^T : int64 = (System.Convert.ToDecimal((# "" value : int64 #))) - when ^T : int32 = (System.Convert.ToDecimal((# "" value : int32 #))) - when ^T : int16 = (System.Convert.ToDecimal((# "" value : int16 #))) - when ^T : nativeint = (System.Convert.ToDecimal(int64 (# "" value : nativeint #))) - when ^T : sbyte = (System.Convert.ToDecimal((# "" value : sbyte #))) - when ^T : uint64 = (System.Convert.ToDecimal((# "" value : uint64 #))) - when ^T : uint32 = (System.Convert.ToDecimal((# "" value : uint32 #))) - when ^T : uint16 = (System.Convert.ToDecimal((# "" value : uint16 #))) - when ^T : unativeint = (System.Convert.ToDecimal(uint64 (# "" value : unativeint #))) - when ^T : byte = (System.Convert.ToDecimal((# "" value : byte #))) + OpExplicitDynamic<(^T), decimal> value + when ^T : string = (Decimal.Parse(castToString value,NumberStyles.Float,CultureInfo.InvariantCulture)) + when ^T : float = (Convert.ToDecimal((# "" value : float #))) + when ^T : float32 = (Convert.ToDecimal((# "" value : float32 #))) + when ^T : int64 = (Convert.ToDecimal((# "" value : int64 #))) + when ^T : int32 = (Convert.ToDecimal((# "" value : int32 #))) + when ^T : int16 = (Convert.ToDecimal((# "" value : int16 #))) + when ^T : nativeint = (Convert.ToDecimal(int64 (# "" value : nativeint #))) + when ^T : sbyte = (Convert.ToDecimal((# "" value : sbyte #))) + when ^T : uint64 = (Convert.ToDecimal((# "" value : uint64 #))) + when ^T : uint32 = (Convert.ToDecimal((# "" value : uint32 #))) + when ^T : uint16 = (Convert.ToDecimal((# "" value : uint16 #))) + when ^T : unativeint = (Convert.ToDecimal(uint64 (# "" value : unativeint #))) + when ^T : byte = (Convert.ToDecimal((# "" value : byte #))) when ^T : decimal = (# "" value : decimal #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = (^T : (static member op_Explicit: ^T -> decimal) (value)) - [] [] let inline unativeint (value: ^T) = - (^T : (static member op_Explicit: ^T -> unativeint) (value)) + OpExplicitDynamic<(^T), unativeint> value when ^T : string = ParseUIntPtr (castToString value) when ^T : float = (# "conv.u" value : unativeint #) when ^T : float32 = (# "conv.u" value : unativeint #) - // Narrower signed types we sign-extend. // Same length signed types we leave as such (so -1 gets reinterpreted as unsigned MaxValue). // Wider signed types we truncate. @@ -4563,28 +4476,27 @@ namespace Microsoft.FSharp.Core when ^T : int16 = (# "conv.i" value : unativeint #) when ^T : nativeint = (# "" value : unativeint #) when ^T : sbyte = (# "conv.i" value : unativeint #) - when ^T : uint64 = (# "conv.u" value : unativeint #) when ^T : uint32 = (# "conv.u" value : unativeint #) when ^T : uint16 = (# "conv.u" value : unativeint #) when ^T : char = (# "conv.u" value : unativeint #) when ^T : unativeint = (# "" value : unativeint #) when ^T : byte = (# "conv.u" value : unativeint #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = (^T : (static member op_Explicit: ^T -> unativeint) (value)) - [] [] let inline nativeint (value: ^T) = - (^T : (static member op_Explicit: ^T -> nativeint) (value)) + OpExplicitDynamic<(^T), nativeint> value when ^T : string = ParseIntPtr (castToString value) when ^T : float = (# "conv.i" value : nativeint #) when ^T : float32 = (# "conv.i" value : nativeint #) - when ^T : int64 = (# "conv.i" value : nativeint #) when ^T : int32 = (# "conv.i" value : nativeint #) when ^T : int16 = (# "conv.i" value : nativeint #) when ^T : nativeint = (# "conv.i" value : nativeint #) when ^T : sbyte = (# "conv.i" value : nativeint #) - // Narrower unsigned types we zero-extend. // Same length unsigned types we leave as such (so unsigned MaxValue (all-bits-set) gets reinterpreted as -1). // Wider unsigned types we truncate. @@ -4595,6 +4507,9 @@ namespace Microsoft.FSharp.Core when ^T : char = (# "conv.u" value : nativeint #) when ^T : unativeint = (# "" value : nativeint #) when ^T : byte = (# "conv.i" value : nativeint #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = (^T : (static member op_Explicit: ^T -> nativeint) (value)) [] let inline string (value: ^T) = @@ -4615,10 +4530,9 @@ namespace Microsoft.FSharp.Core when ^T : unativeint = (# "" value : unativeint #).ToString() when ^T : byte = (# "" value : byte #).ToString("g",CultureInfo.InvariantCulture) - [] [] let inline char (value: ^T) = - (^T : (static member op_Explicit: ^T -> char) (value)) + OpExplicitDynamic<(^T), char> value when ^T : string = (System.Char.Parse(castToString value)) when ^T : float = (# "conv.u2" value : char #) when ^T : float32 = (# "conv.u2" value : char #) @@ -4633,12 +4547,14 @@ namespace Microsoft.FSharp.Core when ^T : char = (# "conv.u2" value : char #) when ^T : unativeint = (# "conv.u2" value : char #) when ^T : byte = (# "conv.u2" value : char #) - + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = (^T : (static member op_Explicit: ^T -> char) (value)) module NonStructuralComparison = /// Static less-than with static optimizations for some well-known cases. let inline (<) (x:^T) (y:^U) = - ((^T or ^U): (static member (<) : ^T * ^U -> bool) (x,y)) + OpLessThanDynamic<(^T), (^U), bool> value when ^T : bool = (# "clt" x y : bool #) when ^T : sbyte = (# "clt" x y : bool #) when ^T : int16 = (# "clt" x y : bool #) @@ -4653,12 +4569,15 @@ namespace Microsoft.FSharp.Core when ^T : float = (# "clt" x y : bool #) when ^T : float32= (# "clt" x y : bool #) when ^T : char = (# "clt" x y : bool #) - when ^T : decimal = System.Decimal.op_LessThan ((# "" x:decimal #), (# "" y:decimal #)) - when ^T : string = (# "clt" (System.String.CompareOrdinal((# "" x : string #),(# "" y : string #))) 0 : bool #) + when ^T : decimal = Decimal.op_LessThan ((# "" x:decimal #), (# "" y:decimal #)) + when ^T : string = (# "clt" (String.CompareOrdinal((# "" x : string #),(# "" y : string #))) 0 : bool #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = ((^T or ^U): (static member (<) : ^T * ^U -> bool) (x,y)) /// Static greater-than with static optimizations for some well-known cases. let inline (>) (x:^T) (y:^U) = - ((^T or ^U): (static member (>) : ^T * ^U -> bool) (x,y)) + OpGreaterThanDynamic<(^T), (^U), bool> value when 'T : bool = (# "cgt" x y : bool #) when 'T : sbyte = (# "cgt" x y : bool #) when 'T : int16 = (# "cgt" x y : bool #) @@ -4673,12 +4592,15 @@ namespace Microsoft.FSharp.Core when 'T : float = (# "cgt" x y : bool #) when 'T : float32 = (# "cgt" x y : bool #) when 'T : char = (# "cgt" x y : bool #) - when 'T : decimal = System.Decimal.op_GreaterThan ((# "" x:decimal #), (# "" y:decimal #)) - when ^T : string = (# "cgt" (System.String.CompareOrdinal((# "" x : string #),(# "" y : string #))) 0 : bool #) + when 'T : decimal = Decimal.op_GreaterThan ((# "" x:decimal #), (# "" y:decimal #)) + when ^T : string = (# "cgt" (String.CompareOrdinal((# "" x : string #),(# "" y : string #))) 0 : bool #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = ((^T or ^U): (static member (>) : ^T * ^U -> bool) (x,y)) /// Static less-than-or-equal with static optimizations for some well-known cases. let inline (<=) (x:^T) (y:^U) = - ((^T or ^U): (static member (<=) : ^T * ^U -> bool) (x,y)) + OpLessThanOrEqualDynamic<(^T), (^U), bool> value when 'T : bool = not (# "cgt" x y : bool #) when 'T : sbyte = not (# "cgt" x y : bool #) when 'T : int16 = not (# "cgt" x y : bool #) @@ -4693,12 +4615,15 @@ namespace Microsoft.FSharp.Core when 'T : float = not (# "cgt.un" x y : bool #) when 'T : float32 = not (# "cgt.un" x y : bool #) when 'T : char = not (# "cgt" x y : bool #) - when 'T : decimal = System.Decimal.op_LessThanOrEqual ((# "" x:decimal #), (# "" y:decimal #)) - when ^T : string = not (# "cgt" (System.String.CompareOrdinal((# "" x : string #),(# "" y : string #))) 0 : bool #) + when 'T : decimal = Decimal.op_LessThanOrEqual ((# "" x:decimal #), (# "" y:decimal #)) + when ^T : string = not (# "cgt" (String.CompareOrdinal((# "" x : string #),(# "" y : string #))) 0 : bool #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = ((^T or ^U): (static member (<=) : ^T * ^U -> bool) (x,y)) /// Static greater-than-or-equal with static optimizations for some well-known cases. let inline (>=) (x:^T) (y:^U) = - ((^T or ^U): (static member (>=) : ^T * ^U -> bool) (x,y)) + OpGreaterThanOrEqualDynamic<(^T), (^U), bool> value when 'T : bool = not (# "clt" x y : bool #) when 'T : sbyte = not (# "clt" x y : bool #) when 'T : int16 = not (# "clt" x y : bool #) @@ -4713,13 +4638,15 @@ namespace Microsoft.FSharp.Core when 'T : float = not (# "clt.un" x y : bool #) when 'T : float32 = not (# "clt.un" x y : bool #) when 'T : char = not (# "clt" x y : bool #) - when 'T : decimal = System.Decimal.op_GreaterThanOrEqual ((# "" x:decimal #), (# "" y:decimal #)) - when ^T : string = not (# "clt" (System.String.CompareOrdinal((# "" x : string #),(# "" y : string #))) 0 : bool #) - + when 'T : decimal = Decimal.op_GreaterThanOrEqual ((# "" x:decimal #), (# "" y:decimal #)) + when ^T : string = not (# "clt" (String.CompareOrdinal((# "" x : string #),(# "" y : string #))) 0 : bool #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = ((^T or ^U): (static member (>=) : ^T * ^U -> bool) (x,y)) /// Static greater-than-or-equal with static optimizations for some well-known cases. let inline (=) (x:^T) (y:^T) = - (^T : (static member (=) : ^T * ^T -> bool) (x,y)) + OpEqualityDynamic<(^T), (^T), bool> value when ^T : bool = (# "ceq" x y : bool #) when ^T : sbyte = (# "ceq" x y : bool #) when ^T : int16 = (# "ceq" x y : bool #) @@ -4734,11 +4661,12 @@ namespace Microsoft.FSharp.Core when ^T : char = (# "ceq" x y : bool #) when ^T : nativeint = (# "ceq" x y : bool #) when ^T : unativeint = (# "ceq" x y : bool #) - when ^T : string = System.String.Equals((# "" x : string #),(# "" y : string #)) - when ^T : decimal = System.Decimal.op_Equality((# "" x:decimal #), (# "" y:decimal #)) + when ^T : string = String.Equals((# "" x : string #),(# "" y : string #)) + when ^T : decimal = Decimal.op_Equality((# "" x:decimal #), (# "" y:decimal #)) + when ^T : ^T = (^T : (static member (=) : ^T * ^T -> bool) (x,y)) let inline (<>) (x:^T) (y:^T) = - (^T : (static member (<>) : ^T * ^T -> bool) (x,y)) + InequalityDynamic<(^T), (^T), bool> value when ^T : bool = not (# "ceq" x y : bool #) when ^T : sbyte = not (# "ceq" x y : bool #) when ^T : int16 = not (# "ceq" x y : bool #) @@ -4753,9 +4681,9 @@ namespace Microsoft.FSharp.Core when ^T : char = not (# "ceq" x y : bool #) when ^T : nativeint = not (# "ceq" x y : bool #) when ^T : unativeint = not (# "ceq" x y : bool #) - when ^T : string = not (System.String.Equals((# "" x : string #),(# "" y : string #))) - when ^T : decimal = System.Decimal.op_Inequality((# "" x:decimal #), (# "" y:decimal #)) - + when ^T : string = not (String.Equals((# "" x : string #),(# "" y : string #))) + when ^T : decimal = Decimal.op_Inequality((# "" x:decimal #), (# "" y:decimal #)) + when ^T : ^T = (^T : (static member (<>) : ^T * ^T -> bool) (x,y)) // static comparison (ER mode) with static optimizations for some well-known cases [] @@ -4784,10 +4712,10 @@ namespace Microsoft.FSharp.Core else (# "ceq" e1 e1 : int #) when ^T : char = if (# "clt.un" e1 e2 : bool #) then (-1) else (# "cgt.un" e1 e2 : int #) when ^T : string = - // NOTE: we don't have to null check here because System.String.CompareOrdinal + // NOTE: we don't have to null check here because String.CompareOrdinal // gives reliable results on null values. - System.String.CompareOrdinal((# "" e1 : string #),(# "" e2 : string #)) - when ^T : decimal = System.Decimal.Compare((# "" e1:decimal #), (# "" e2:decimal #)) + String.CompareOrdinal((# "" e1 : string #),(# "" e2 : string #)) + when ^T : decimal = Decimal.Compare((# "" e1:decimal #), (# "" e2:decimal #)) [] let inline max (e1: ^T) (e2: ^T) = @@ -4938,16 +4866,14 @@ namespace Microsoft.FSharp.Core when ^T : char and ^U : char = (# "conv.ovf.u2.un" (# "add.ovf.un" x y : uint32 #) : char #) when ^T : sbyte and ^U : sbyte = (# "conv.ovf.i1" (# "add.ovf" x y : int32 #) : sbyte #) when ^T : byte and ^U : byte = (# "conv.ovf.u1.un" (# "add.ovf.un" x y : uint32 #) : byte #) - when ^T : string and ^U : string = (# "" (System.String.Concat((# "" x : string #),(# "" y : string #))) : ^T #) - when ^T : decimal and ^U : decimal = (# "" (System.Decimal.op_Addition((# "" x : decimal #),(# "" y : decimal #))) : ^V #) + when ^T : string and ^U : string = (# "" (String.Concat((# "" x : string #),(# "" y : string #))) : ^T #) + when ^T : decimal and ^U : decimal = (# "" (Decimal.op_Addition((# "" x : decimal #),(# "" y : decimal #))) : ^V #) // According to the somewhat subtle rules of static optimizations, - // this condition is used whenever ^T is resolved to a nominal type - // That is, not in the generic implementation of '+' + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available when ^T : ^T = ((^T or ^U): (static member (+) : ^T * ^U -> ^V) (x,y)) - [] let inline (-) (x: ^T) (y: ^U) : ^V = - ((^T or ^U): (static member (-) : ^T * ^U -> ^V) (x,y)) + CheckedSubtractionDynamic<(^T),(^U),(^V)> x y when ^T : int32 and ^U : int32 = (# "sub.ovf" x y : int32 #) when ^T : float and ^U : float = (# "sub" x y : float #) when ^T : float32 and ^U : float32 = (# "sub" x y : float32 #) @@ -4960,11 +4886,13 @@ namespace Microsoft.FSharp.Core when ^T : uint16 and ^U : uint16 = (# "conv.ovf.u2.un" (# "sub.ovf.un" x y : uint32 #) : uint16 #) when ^T : sbyte and ^U : sbyte = (# "conv.ovf.i1" (# "sub.ovf" x y : int32 #) : sbyte #) when ^T : byte and ^U : byte = (# "conv.ovf.u1.un" (# "sub.ovf.un" x y : uint32 #) : byte #) - when ^T : decimal and ^U : decimal = (# "" (System.Decimal.op_Subtraction((# "" x : decimal #),(# "" y : decimal #))) : ^V #) + when ^T : decimal and ^U : decimal = (# "" (Decimal.op_Subtraction((# "" x : decimal #),(# "" y : decimal #))) : ^V #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = ((^T or ^U): (static member (-) : ^T * ^U -> ^V) (x,y)) - [] let inline (~-) (value: ^T) : ^T = - (^T : (static member (~-) : ^T -> ^T) (value)) + CheckedUnaryNegationDynamic<(^T),(^T)> value when ^T : int32 = (# "sub.ovf" 0 value : int32 #) when ^T : float = (# "neg" value : float #) when ^T : float32 = (# "neg" value : float32 #) @@ -4972,7 +4900,10 @@ namespace Microsoft.FSharp.Core when ^T : int16 = (# "sub.ovf" 0s value : int16 #) when ^T : nativeint = (# "sub.ovf" 0n value : nativeint #) when ^T : sbyte = (# "sub.ovf" 0y value : sbyte #) - when ^T : decimal = (# "" (System.Decimal.op_UnaryNegation((# "" value : decimal #))) : ^T #) + when ^T : decimal = (# "" (Decimal.op_UnaryNegation((# "" value : decimal #))) : ^T #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + when ^T : ^T = (^T : (static member (~-) : ^T -> ^T) (value)) let inline ( * ) (x: ^T) (y: ^U) : ^V = CheckedMultiplyDynamic<(^T),(^U),(^V)> x y @@ -4988,17 +4919,16 @@ namespace Microsoft.FSharp.Core when ^T : unativeint and ^U : unativeint = (# "mul.ovf.un" x y : unativeint #) when ^T : float and ^U : float = (# "mul" x y : float #) when ^T : float32 and ^U : float32 = (# "mul" x y : float32 #) - when ^T : decimal and ^U : decimal = (# "" (System.Decimal.op_Multiply((# "" x : decimal #),(# "" y : decimal #))) : ^V #) + when ^T : decimal and ^U : decimal = (# "" (Decimal.op_Multiply((# "" x : decimal #),(# "" y : decimal #))) : ^V #) // According to the somewhat subtle rules of static optimizations, - // this condition is used whenever ^T is resolved to a nominal type + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available // That is, not in the generic implementation of '*' when ^T : ^T = ((^T or ^U): (static member (*) : ^T * ^U -> ^V) (x,y)) - [] [] let inline byte (value: ^T) = - (^T : (static member op_Explicit: ^T -> byte) (value)) - when ^T : string = parseByte (castToString value) + OpExplicitDynamic<(^T),byte> value + when ^T : string = ParseByte (castToString value) when ^T : float = (# "conv.ovf.u1" value : byte #) when ^T : float32 = (# "conv.ovf.u1" value : byte #) when ^T : int64 = (# "conv.ovf.u1" value : byte #) @@ -5012,11 +4942,14 @@ namespace Microsoft.FSharp.Core when ^T : char = (# "conv.ovf.u1.un" value : byte #) when ^T : unativeint = (# "conv.ovf.u1.un" value : byte #) when ^T : byte = (# "conv.ovf.u1.un" value : byte #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + // That is, not in the generic implementation of '*' + when ^T : ^T = (^T : (static member op_Explicit: ^T -> byte) (value)) - [] [] let inline sbyte (value: ^T) = - (^T : (static member op_Explicit: ^T -> sbyte) (value)) + OpExplicitDynamic<(^T),sbyte> value when ^T : string = ParseSByte (castToString value) when ^T : float = (# "conv.ovf.i1" value : sbyte #) when ^T : float32 = (# "conv.ovf.i1" value : sbyte #) @@ -5031,11 +4964,14 @@ namespace Microsoft.FSharp.Core when ^T : char = (# "conv.ovf.i1.un" value : sbyte #) when ^T : unativeint = (# "conv.ovf.i1.un" value : sbyte #) when ^T : byte = (# "conv.ovf.i1.un" value : sbyte #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + // That is, not in the generic implementation of '*' + when ^T : ^T = (^T : (static member op_Explicit: ^T -> sbyte) (value)) - [] [] let inline uint16 (value: ^T) = - (^T : (static member op_Explicit: ^T -> uint16) (value)) + OpExplicitDynamic<(^T),uint16> value when ^T : string = ParseUInt16 (castToString value) when ^T : float = (# "conv.ovf.u2" value : uint16 #) when ^T : float32 = (# "conv.ovf.u2" value : uint16 #) @@ -5050,11 +4986,14 @@ namespace Microsoft.FSharp.Core when ^T : char = (# "conv.ovf.u2.un" value : uint16 #) when ^T : unativeint = (# "conv.ovf.u2.un" value : uint16 #) when ^T : byte = (# "conv.ovf.u2.un" value : uint16 #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + // That is, not in the generic implementation of '*' + when ^T : ^T = (^T : (static member op_Explicit: ^T -> byte) (value)) - [] [] let inline char (value: ^T) = - (^T : (static member op_Explicit: ^T -> char) (value)) + OpExplicitDynamic<(^T), char> value when ^T : string = (System.Char.Parse(castToString value)) when ^T : float = (# "conv.ovf.u2" value : char #) when ^T : float32 = (# "conv.ovf.u2" value : char #) @@ -5069,11 +5008,14 @@ namespace Microsoft.FSharp.Core when ^T : char = (# "conv.ovf.u2.un" value : char #) when ^T : unativeint = (# "conv.ovf.u2.un" value : char #) when ^T : byte = (# "conv.ovf.u2.un" value : char #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + // That is, not in the generic implementation of '*' + when ^T : ^T = (^T : (static member op_Explicit: ^T -> char) (value)) - [] [] let inline int16 (value: ^T) = - (^T : (static member op_Explicit: ^T -> int16) (value)) + OpExplicitDynamic<(^T), int16> value when ^T : string = ParseInt16 (castToString value) when ^T : float = (# "conv.ovf.i2" value : int16 #) when ^T : float32 = (# "conv.ovf.i2" value : int16 #) @@ -5088,11 +5030,14 @@ namespace Microsoft.FSharp.Core when ^T : char = (# "conv.ovf.i2.un" value : int16 #) when ^T : unativeint = (# "conv.ovf.i2.un" value : int16 #) when ^T : byte = (# "conv.ovf.i2.un" value : int16 #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + // That is, not in the generic implementation of '*' + when ^T : ^T = (^T : (static member op_Explicit: ^T -> int16) (value)) - [] [] let inline uint32 (value: ^T) = - (^T : (static member op_Explicit: ^T -> uint32) (value)) + OpExplicitDynamic<(^T), uint32> value when ^T : string = ParseUInt32 (castToString value) when ^T : float = (# "conv.ovf.u4" value : uint32 #) when ^T : float32 = (# "conv.ovf.u4" value : uint32 #) @@ -5107,11 +5052,14 @@ namespace Microsoft.FSharp.Core when ^T : char = (# "conv.ovf.u4.un" value : uint32 #) when ^T : unativeint = (# "conv.ovf.u4.un" value : uint32 #) when ^T : byte = (# "conv.ovf.u4.un" value : uint32 #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + // That is, not in the generic implementation of '*' + when ^T : ^T = (^T : (static member op_Explicit: ^T -> uint32) (value)) - [] [] let inline int32 (value: ^T) = - (^T : (static member op_Explicit: ^T -> int32) (value)) + OpExplicitDynamic<(^T), int32> value when ^T : string = ParseInt32 (castToString value) when ^T : float = (# "conv.ovf.i4" value : int32 #) when ^T : float32 = (# "conv.ovf.i4" value : int32 #) @@ -5126,15 +5074,17 @@ namespace Microsoft.FSharp.Core when ^T : char = (# "conv.ovf.i4.un" value : int32 #) when ^T : unativeint = (# "conv.ovf.i4.un" value : int32 #) when ^T : byte = (# "conv.ovf.i4.un" value : int32 #) - + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + // That is, not in the generic implementation of '*' + when ^T : ^T = (^T : (static member op_Explicit: ^T -> int32) (value)) [] let inline int value = int32 value - [] [] let inline uint64 (value: ^T) = - (^T : (static member op_Explicit: ^T -> uint64) (value)) + OpExplicitDynamic<(^T), uint64> value when ^T : string = ParseUInt64 (castToString value) when ^T : float = (# "conv.ovf.u8" value : uint64 #) when ^T : float32 = (# "conv.ovf.u8" value : uint64 #) @@ -5149,11 +5099,14 @@ namespace Microsoft.FSharp.Core when ^T : char = (# "conv.ovf.u8.un" value : uint64 #) when ^T : unativeint = (# "conv.ovf.u8.un" value : uint64 #) when ^T : byte = (# "conv.ovf.u8.un" value : uint64 #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + // That is, not in the generic implementation of '*' + when ^T : ^T = (^T : (static member op_Explicit: ^T -> uint64) (value)) - [] [] let inline int64 (value: ^T) = - (^T : (static member op_Explicit: ^T -> int64) (value)) + OpExplicitDynamic<(^T), int64> value when ^T : string = ParseInt64 (castToString value) when ^T : float = (# "conv.ovf.i8" value : int64 #) when ^T : float32 = (# "conv.ovf.i8" value : int64 #) @@ -5168,11 +5121,14 @@ namespace Microsoft.FSharp.Core when ^T : char = (# "conv.ovf.i8.un" value : int64 #) when ^T : unativeint = (# "conv.ovf.i8.un" value : int64 #) when ^T : byte = (# "conv.ovf.i8.un" value : int64 #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + // That is, not in the generic implementation of '*' + when ^T : ^T = (^T : (static member op_Explicit: ^T -> int64) (value)) - [] [] let inline unativeint (value: ^T) = - (^T : (static member op_Explicit: ^T -> unativeint) (value)) + OpExplicitDynamic<(^T), unativeint> value when ^T : string = ParseUIntPtr (castToString value) when ^T : float = (# "conv.ovf.u" value : unativeint #) when ^T : float32 = (# "conv.ovf.u" value : unativeint #) @@ -5187,11 +5143,14 @@ namespace Microsoft.FSharp.Core when ^T : char = (# "conv.ovf.u.un" value : unativeint #) when ^T : unativeint = (# "conv.ovf.u.un" value : unativeint #) when ^T : byte = (# "conv.ovf.u.un" value : unativeint #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + // That is, not in the generic implementation of '*' + when ^T : ^T = (^T : (static member op_Explicit: ^T -> unativeint) (value)) - [] [] let inline nativeint (value: ^T) = - (^T : (static member op_Explicit: ^T -> nativeint) (value)) + OpExplicitDynamic<(^T), nativeint> value when ^T : string = ParseIntPtr (castToString value) when ^T : float = (# "conv.ovf.i" value : nativeint #) when ^T : float32 = (# "conv.ovf.i" value : nativeint #) @@ -5206,6 +5165,10 @@ namespace Microsoft.FSharp.Core when ^T : char = (# "conv.ovf.i.un" value : nativeint #) when ^T : unativeint = (# "conv.ovf.i.un" value : nativeint #) when ^T : byte = (# "conv.ovf.i.un" value : nativeint #) + // According to the somewhat subtle rules of static optimizations, + // this condition is used whenever ^T is resolved to a nominal type or witnesses are available + // That is, not in the generic implementation of '*' + when ^T : ^T = (^T : (static member op_Explicit: ^T -> nativeint) (value)) module OperatorIntrinsics = @@ -5732,7 +5695,6 @@ namespace Microsoft.FSharp.Core if len <= 0 then String.Empty else source.Substring(start, len) - [] let inline absImpl (x: ^T) : ^T = (^T: (static member Abs : ^T -> ^T) (x)) when ^T : int32 = let x : int32 = retype x in System.Math.Abs(x) @@ -5749,61 +5711,51 @@ namespace Microsoft.FSharp.Core when ^T : sbyte = let x : sbyte = retype x in System.Math.Abs(x) when ^T : decimal = System.Math.Abs(retype x : decimal) - [] let inline acosImpl(x: ^T) : ^T = (^T: (static member Acos : ^T -> ^T) (x)) when ^T : float = System.Math.Acos(retype x) when ^T : float32 = System.Math.Acos(toFloat (retype x)) |> toFloat32 - [] let inline asinImpl(x: ^T) : ^T = (^T: (static member Asin : ^T -> ^T) (x)) when ^T : float = System.Math.Asin(retype x) when ^T : float32 = System.Math.Asin(toFloat (retype x)) |> toFloat32 - [] let inline atanImpl(x: ^T) : ^T = (^T: (static member Atan : ^T -> ^T) (x)) when ^T : float = System.Math.Atan(retype x) when ^T : float32 = System.Math.Atan(toFloat (retype x)) |> toFloat32 - [] let inline atan2Impl(x: ^T) (y: ^T) : 'U = (^T: (static member Atan2 : ^T * ^T -> 'U) (x,y)) when ^T : float = System.Math.Atan2(retype x, retype y) when ^T : float32 = System.Math.Atan2(toFloat (retype x), toFloat(retype y)) |> toFloat32 - [] let inline ceilImpl(x: ^T) : ^T = (^T: (static member Ceiling : ^T -> ^T) (x)) when ^T : float = System.Math.Ceiling(retype x : float) when ^T : float32 = System.Math.Ceiling(toFloat (retype x)) |> toFloat32 - [] let inline expImpl(x: ^T) : ^T = (^T: (static member Exp : ^T -> ^T) (x)) when ^T : float = System.Math.Exp(retype x) when ^T : float32 = System.Math.Exp(toFloat (retype x)) |> toFloat32 - [] let inline floorImpl (x: ^T) : ^T = (^T: (static member Floor : ^T -> ^T) (x)) when ^T : float = System.Math.Floor(retype x : float) when ^T : float32 = System.Math.Floor(toFloat (retype x)) |> toFloat32 - [] let inline truncateImpl (x: ^T) : ^T = (^T: (static member Truncate : ^T -> ^T) (x)) when ^T : float = System.Math.Truncate(retype x : float) when ^T : float32 = System.Math.Truncate(toFloat (retype x)) |> toFloat32 - [] let inline roundImpl (x: ^T) : ^T = (^T: (static member Round : ^T -> ^T) (x)) when ^T : float = System.Math.Round(retype x : float) when ^T : float32 = System.Math.Round(toFloat (retype x)) |> toFloat32 - [] let inline signImpl (x: ^T) : int = (^T: (member Sign : int) (x)) when ^T : int32 = System.Math.Sign(retype x : int32) @@ -5815,67 +5767,56 @@ namespace Microsoft.FSharp.Core when ^T : float32 = System.Math.Sign(toFloat (retype x)) when ^T : decimal = System.Math.Sign(retype x : decimal) - [] let inline logImpl(x: ^T) : ^T = (^T: (static member Log : ^T -> ^T) (x)) when ^T : float = System.Math.Log(retype x) when ^T : float32 = System.Math.Log(toFloat (retype x)) |> toFloat32 - [] let inline log10Impl(x: ^T) : ^T = (^T: (static member Log10 : ^T -> ^T) (x)) when ^T : float = System.Math.Log10(retype x) when ^T : float32 = System.Math.Log10(toFloat (retype x)) |> toFloat32 - [] let inline sqrtImpl(x: ^T) : ^U = (^T: (static member Sqrt : ^T -> ^U) (x)) when ^T : float = System.Math.Sqrt(retype x : float) when ^T : float32 = System.Math.Sqrt(toFloat (retype x)) |> toFloat32 - [] let inline cosImpl(x: ^T) : ^T = (^T: (static member Cos : ^T -> ^T) (x)) when ^T : float = System.Math.Cos(retype x) when ^T : float32 = System.Math.Cos(toFloat (retype x)) |> toFloat32 - [] let inline coshImpl(x: ^T) : ^T = (^T: (static member Cosh : ^T -> ^T) (x)) when ^T : float = System.Math.Cosh(retype x) when ^T : float32 = System.Math.Cosh(toFloat (retype x)) |> toFloat32 - [] let inline sinImpl(x: ^T) : ^T = (^T: (static member Sin : ^T -> ^T) (x)) when ^T : float = System.Math.Sin(retype x) when ^T : float32 = System.Math.Sin(toFloat (retype x)) |> toFloat32 - [] let inline sinhImpl(x: ^T) : ^T = (^T: (static member Sinh : ^T -> ^T) (x)) when ^T : float = System.Math.Sinh(retype x) when ^T : float32 = System.Math.Sinh(toFloat (retype x)) |> toFloat32 - [] let inline tanImpl(x: ^T) : ^T = (^T: (static member Tan : ^T -> ^T) (x)) when ^T : float = System.Math.Tan(retype x) when ^T : float32 = System.Math.Tan(toFloat (retype x)) |> toFloat32 - [] let inline tanhImpl(x: ^T) : ^T = (^T: (static member Tanh : ^T -> ^T) (x)) when ^T : float = System.Math.Tanh(retype x) when ^T : float32 = System.Math.Tanh(toFloat (retype x)) |> toFloat32 - [] let inline powImpl (x: ^T) (y: ^U) : ^T = (^T: (static member Pow : ^T * ^U -> ^T) (x,y)) when ^T : float = System.Math.Pow((retype x : float), (retype y: float)) when ^T : float32 = System.Math.Pow(toFloat (retype x), toFloat(retype y)) |> toFloat32 - [] let UnaryDynamicImpl nm : ('T -> 'U) = let aty = typeof<'T> let minfo = aty.GetMethod(nm, [| aty |]) @@ -5887,7 +5828,6 @@ namespace Microsoft.FSharp.Core let minfo = aty.GetMethod(nm,[| aty;bty |]) (fun x y -> unboxPrim<_>(minfo.Invoke(null,[| box x; box y|]))) - [] type AbsDynamicImplTable<'T>() = static let result : ('T -> 'T) = let aty = typeof<'T> @@ -5902,7 +5842,6 @@ namespace Microsoft.FSharp.Core else UnaryDynamicImpl "Abs" static member Result : ('T -> 'T) = result - [] type AcosDynamicImplTable<'T>() = static let result : ('T -> 'T) = let aty = typeof<'T> @@ -5911,7 +5850,6 @@ namespace Microsoft.FSharp.Core else UnaryDynamicImpl "Acos" static member Result : ('T -> 'T) = result - [] type AsinDynamicImplTable<'T>() = static let result : ('T -> 'T) = let aty = typeof<'T> @@ -5920,7 +5858,6 @@ namespace Microsoft.FSharp.Core else UnaryDynamicImpl "Asin" static member Result : ('T -> 'T) = result - [] type AtanDynamicImplTable<'T>() = static let result : ('T -> 'T) = let aty = typeof<'T> @@ -5929,7 +5866,6 @@ namespace Microsoft.FSharp.Core else UnaryDynamicImpl "Atan" static member Result : ('T -> 'T) = result - [] type Atan2DynamicImplTable<'T,'U>() = static let result : ('T -> 'T -> 'U) = let aty = typeof<'T> @@ -5938,7 +5874,6 @@ namespace Microsoft.FSharp.Core else BinaryDynamicImpl "Atan2" static member Result : ('T -> 'T -> 'U) = result - [] type CeilingDynamicImplTable<'T>() = static let result : ('T -> 'T) = let aty = typeof<'T> @@ -5947,7 +5882,6 @@ namespace Microsoft.FSharp.Core else UnaryDynamicImpl "Ceiling" static member Result : ('T -> 'T) = result - [] type ExpDynamicImplTable<'T>() = static let result : ('T -> 'T) = let aty = typeof<'T> @@ -5956,7 +5890,6 @@ namespace Microsoft.FSharp.Core else UnaryDynamicImpl "Exp" static member Result : ('T -> 'T) = result - [] type FloorDynamicImplTable<'T>() = static let result : ('T -> 'T) = let aty = typeof<'T> @@ -5965,7 +5898,6 @@ namespace Microsoft.FSharp.Core else UnaryDynamicImpl "Floor" static member Result : ('T -> 'T) = result - [] type TruncateDynamicImplTable<'T>() = static let result : ('T -> 'T) = let aty = typeof<'T> @@ -5974,7 +5906,6 @@ namespace Microsoft.FSharp.Core else UnaryDynamicImpl "Truncate" static member Result : ('T -> 'T) = result - [] type RoundDynamicImplTable<'T>() = static let result : ('T -> 'T) = let aty = typeof<'T> @@ -5983,7 +5914,6 @@ namespace Microsoft.FSharp.Core else UnaryDynamicImpl "Round" static member Result : ('T -> 'T) = result - [] type SignDynamicImplTable<'T>() = static let result : ('T -> int) = let aty = typeof<'T> @@ -5998,7 +5928,6 @@ namespace Microsoft.FSharp.Core else UnaryDynamicImpl "Sign" static member Result : ('T -> int) = result - [] type LogDynamicImplTable<'T>() = static let result : ('T -> 'T) = let aty = typeof<'T> @@ -6007,7 +5936,6 @@ namespace Microsoft.FSharp.Core else UnaryDynamicImpl "Log" static member Result : ('T -> 'T) = result - [] type Log10DynamicImplTable<'T>() = static let result : ('T -> 'T) = let aty = typeof<'T> @@ -6016,7 +5944,6 @@ namespace Microsoft.FSharp.Core else UnaryDynamicImpl "Log10" static member Result : ('T -> 'T) = result - [] type SqrtDynamicImplTable<'T,'U>() = static let result : ('T -> 'U) = let aty = typeof<'T> @@ -6025,7 +5952,6 @@ namespace Microsoft.FSharp.Core else UnaryDynamicImpl "Sqrt" static member Result : ('T -> 'U) = result - [] type CosDynamicImplTable<'T>() = static let result : ('T -> 'T) = let aty = typeof<'T> @@ -6034,7 +5960,6 @@ namespace Microsoft.FSharp.Core else UnaryDynamicImpl "Cos" static member Result : ('T -> 'T) = result - [] type CoshDynamicImplTable<'T>() = static let result : ('T -> 'T) = let aty = typeof<'T> @@ -6043,7 +5968,6 @@ namespace Microsoft.FSharp.Core else UnaryDynamicImpl "Cosh" static member Result : ('T -> 'T) = result - [] type SinDynamicImplTable<'T>() = static let result : ('T -> 'T) = let aty = typeof<'T> @@ -6052,7 +5976,6 @@ namespace Microsoft.FSharp.Core else UnaryDynamicImpl "Sin" static member Result : ('T -> 'T) = result - [] type SinhDynamicImplTable<'T>() = static let result : ('T -> 'T) = let aty = typeof<'T> @@ -6061,7 +5984,6 @@ namespace Microsoft.FSharp.Core else UnaryDynamicImpl "Sinh" static member Result : ('T -> 'T) = result - [] type TanDynamicImplTable<'T>() = static let result : ('T -> 'T) = let aty = typeof<'T> @@ -6070,7 +5992,6 @@ namespace Microsoft.FSharp.Core else UnaryDynamicImpl "Tan" static member Result : ('T -> 'T) = result - [] type TanhDynamicImplTable<'T>() = static let result : ('T -> 'T) = let aty = typeof<'T> @@ -6079,7 +6000,6 @@ namespace Microsoft.FSharp.Core else UnaryDynamicImpl "Tanh" static member Result : ('T -> 'T) = result - [] type PowDynamicImplTable<'T,'U>() = static let result : ('T -> 'U -> 'T) = let aty = typeof<'T> diff --git a/src/fsharp/FSharp.Core/prim-types.fsi b/src/fsharp/FSharp.Core/prim-types.fsi index f57d2ab0228..e0aa07db283 100644 --- a/src/fsharp/FSharp.Core/prim-types.fsi +++ b/src/fsharp/FSharp.Core/prim-types.fsi @@ -1099,6 +1099,471 @@ namespace Microsoft.FSharp.Core /// The division result. val inline DivideByInt< ^T > : x:^T -> y:int -> ^T when ^T : (static member DivideByInt : ^T * int -> ^T) + type BuiltInWitnesses = + static member inline op_Addition: x: int32 * y: int32 -> int32 + static member inline op_Addition: x: float * y: float -> float + static member inline op_Addition: x: float32 * y: float32 -> float32 + static member inline op_Addition: x: int64 * y: int64 -> int64 + static member inline op_Addition: x: uint64 * y: uint64 -> uint64 + static member inline op_Addition: x: uint32 * y: uint32 -> uint32 + static member inline op_Addition: x: nativeint * y: nativeint -> nativeint + static member inline op_Addition: x: unativeint * y: unativeint -> unativeint + static member inline op_Addition: x: int16 * y: int16 -> int16 + static member inline op_Addition: x: uint16 * y: uint16 -> uint16 + static member inline op_Addition: x: char * y: char -> char + static member inline op_Addition: x: sbyte * y: sbyte -> sbyte + static member inline op_Addition: x: byte * y: byte -> byte + static member inline op_Addition: x: string * y: string -> string + static member inline op_Addition: x: decimal * y: decimal -> decimal + + static member inline op_Multiply: x: int32 * y: int32 -> int32 + static member inline op_Multiply: x: float * y: float -> float + static member inline op_Multiply: x: float32 * y: float32 -> float32 + static member inline op_Multiply: x: int64 * y: int64 -> int64 + static member inline op_Multiply: x: uint64 * y: uint64 -> uint64 + static member inline op_Multiply: x: uint32 * y: uint32 -> uint32 + static member inline op_Multiply: x: nativeint * y: nativeint -> nativeint + static member inline op_Multiply: x: unativeint * y: unativeint -> unativeint + static member inline op_Multiply: x: int16 * y: int16 -> int16 + static member inline op_Multiply: x: uint16 * y: uint16 -> uint16 + static member inline op_Multiply: x: sbyte * y: sbyte -> sbyte + static member inline op_Multiply: x: byte * y: byte -> byte + static member inline op_Multiply: x: decimal * y: decimal -> decimal + + static member inline op_UnaryNegation: x: int32 -> int32 + static member inline op_UnaryNegation: x: float -> float + static member inline op_UnaryNegation: x: float32 -> float32 + static member inline op_UnaryNegation: x: int64 -> int64 + static member inline op_UnaryNegation: x: int16 -> int16 + static member inline op_UnaryNegation: x: nativeint -> nativeint + static member inline op_UnaryNegation: x: sbyte -> sbyte + static member inline op_UnaryNegation: x: decimal -> decimal + + static member inline op_Subtraction: x: int32 * y: int32 -> int32 + static member inline op_Subtraction: x: float * y: float -> float + static member inline op_Subtraction: x: float32 * y: float32 -> float32 + static member inline op_Subtraction: x: int64 * y: int64 -> int64 + static member inline op_Subtraction: x: uint64 * y: uint64 -> uint64 + static member inline op_Subtraction: x: uint32 * y: uint32 -> uint32 + static member inline op_Subtraction: x: nativeint * y: nativeint -> nativeint + static member inline op_Subtraction: x: unativeint * y: unativeint -> unativeint + static member inline op_Subtraction: x: int16 * y: int16 -> int16 + static member inline op_Subtraction: x: uint16 * y: uint16 -> uint16 + static member inline op_Subtraction: x: sbyte * y: sbyte -> sbyte + static member inline op_Subtraction: x: byte * y: byte -> byte + static member inline op_Subtraction: x: decimal * y: decimal -> decimal + + static member inline op_Division: x: int32 * y: int32 -> int32 + static member inline op_Division: x: float * y: float -> float + static member inline op_Division: x: float32 * y: float32 -> float32 + static member inline op_Division: x: int64 * y: int64 -> int64 + static member inline op_Division: x: uint64 * y: uint64 -> uint64 + static member inline op_Division: x: uint32 * y: uint32 -> uint32 + static member inline op_Division: x: nativeint * y: nativeint -> nativeint + static member inline op_Division: x: unativeint * y: unativeint -> unativeint + static member inline op_Division: x: int16 * y: int16 -> int16 + static member inline op_Division: x: uint16 * y: uint16 -> uint16 + static member inline op_Division: x: sbyte * y: sbyte -> sbyte + static member inline op_Division: x: byte * y: byte -> byte + static member inline op_Division: x: decimal * y: decimal -> decimal + + static member inline op_Modulus: x: int32 * y: int32 -> int32 + static member inline op_Modulus: x: float * y: float -> float + static member inline op_Modulus: x: float32 * y: float32 -> float32 + static member inline op_Modulus: x: int64 * y: int64 -> int64 + static member inline op_Modulus: x: uint64 * y: uint64 -> uint64 + static member inline op_Modulus: x: uint32 * y: uint32 -> uint32 + static member inline op_Modulus: x: nativeint * y: nativeint -> nativeint + static member inline op_Modulus: x: unativeint * y: unativeint -> unativeint + static member inline op_Modulus: x: int16 * y: int16 -> int16 + static member inline op_Modulus: x: uint16 * y: uint16 -> uint16 + static member inline op_Modulus: x: sbyte * y: sbyte -> sbyte + static member inline op_Modulus: x: byte * y: byte -> byte + static member inline op_Modulus: x: decimal * y: decimal -> decimal + + static member inline op_LeftShift: value: int32 * shift: int32 -> int32 + static member inline op_LeftShift: value: uint32 * shift: int32 -> uint32 + static member inline op_LeftShift: value: int64 * shift: int32 -> int64 + static member inline op_LeftShift: value: uint64 * shift: int32 -> uint64 + static member inline op_LeftShift: value: nativeint * shift: int32 -> nativeint + static member inline op_LeftShift: value: unativeint * shift: int32 -> unativeint + static member inline op_LeftShift: value: int16 * shift: int32 -> int16 + static member inline op_LeftShift: value: uint16 * shift: int32 -> uint16 + static member inline op_LeftShift: value: sbyte * shift: int32 -> sbyte + static member inline op_LeftShift: value: byte * shift: int32 -> byte + + static member inline op_RightShift: value: byte * shift: int32 -> byte + static member inline op_RightShift: value: uint32 * shift: int32 -> uint32 + static member inline op_RightShift: value: int64 * shift: int32 -> int64 + static member inline op_RightShift: value: uint64 * shift: int32 -> uint64 + static member inline op_RightShift: value: nativeint * shift: int32 -> nativeint + static member inline op_RightShift: value: unativeint * shift: int32 -> unativeint + static member inline op_RightShift: value: int16 * shift: int32 -> int16 + static member inline op_RightShift: value: uint16 * shift: int32 -> uint16 + static member inline op_RightShift: value: sbyte * shift: int32 -> sbyte + static member inline op_RightShift: value: byte * shift: int32 -> byte + + static member inline op_BitwiseAnd: x: int32 * y: int32 -> int32 + static member inline op_BitwiseAnd: x: int64 * y: int64 -> int64 + static member inline op_BitwiseAnd: x: uint64 * y: uint64 -> uint64 + static member inline op_BitwiseAnd: x: uint32 * y: uint32 -> uint32 + static member inline op_BitwiseAnd: x: int16 * y: int16 -> int16 + static member inline op_BitwiseAnd: x: uint16 * y: uint16 -> uint16 + static member inline op_BitwiseAnd: x: nativeint * y: nativeint -> nativeint + static member inline op_BitwiseAnd: x: unativeint * y: unativeint -> unativeint + static member inline op_BitwiseAnd: x: sbyte * y: sbyte -> sbyte + static member inline op_BitwiseAnd: x: byte * y: byte -> byte + + static member inline op_BitwiseOr: x: int32 * y: int32 -> int32 + static member inline op_BitwiseOr: x: int64 * y: int64 -> int64 + static member inline op_BitwiseOr: x: uint64 * y: uint64 -> uint64 + static member inline op_BitwiseOr: x: uint32 * y: uint32 -> uint32 + static member inline op_BitwiseOr: x: int16 * y: int16 -> int16 + static member inline op_BitwiseOr: x: uint16 * y: uint16 -> uint16 + static member inline op_BitwiseOr: x: nativeint * y: nativeint -> nativeint + static member inline op_BitwiseOr: x: unativeint * y: unativeint -> unativeint + static member inline op_BitwiseOr: x: sbyte * y: sbyte -> sbyte + static member inline op_BitwiseOr: x: byte * y: byte -> byte + + static member inline op_BitwiseExclusiveOr: x: int32 * y: int32 -> int32 + static member inline op_BitwiseExclusiveOr: x: int64 * y: int64 -> int64 + static member inline op_BitwiseExclusiveOr: x: uint64 * y: uint64 -> uint64 + static member inline op_BitwiseExclusiveOr: x: uint32 * y: uint32 -> uint32 + static member inline op_BitwiseExclusiveOr: x: int16 * y: int16 -> int16 + static member inline op_BitwiseExclusiveOr: x: uint16 * y: uint16 -> uint16 + static member inline op_BitwiseExclusiveOr: x: nativeint * y: nativeint -> nativeint + static member inline op_BitwiseExclusiveOr: x: unativeint * y: unativeint -> unativeint + static member inline op_BitwiseExclusiveOr: x: sbyte * y: sbyte -> sbyte + static member inline op_BitwiseExclusiveOr: x: byte * y: byte -> byte + + static member inline op_LogicalNot: value: int32 -> int32 + static member inline op_LogicalNot: value: int64 -> int64 + static member inline op_LogicalNot: value: uint64 -> uint64 + static member inline op_LogicalNot: value: uint32 -> uint32 + static member inline op_LogicalNot: value: nativeint -> nativeint + static member inline op_LogicalNot: value: unativeint -> unativeint + static member inline op_LogicalNot: value: int16 -> int16 + static member inline op_LogicalNot: value: uint16 -> uint16 + static member inline op_LogicalNot: value: sbyte -> sbyte + static member inline op_LogicalNot: value: byte -> byte + + static member inline op_Explicit: value: string -> byte + static member inline op_Explicit: value: float -> byte + static member inline op_Explicit: value: float32 -> byte + static member inline op_Explicit: value: int64 -> byte + static member inline op_Explicit: value: int32 -> byte + static member inline op_Explicit: value: int16 -> byte + static member inline op_Explicit: value: nativeint -> byte + static member inline op_Explicit: value: sbyte -> byte + static member inline op_Explicit: value: uint64 -> byte + static member inline op_Explicit: value: uint32 -> byte + static member inline op_Explicit: value: uint16 -> byte + static member inline op_Explicit: value: char -> byte + static member inline op_Explicit: value: unativeint -> byte + static member inline op_Explicit: value: byte -> byte + + static member inline op_Explicit: value: byte -> sbyte + static member inline op_Explicit: value: float -> sbyte + static member inline op_Explicit: value: float32 -> sbyte + static member inline op_Explicit: value: int64 -> sbyte + static member inline op_Explicit: value: int32 -> sbyte + static member inline op_Explicit: value: int16 -> sbyte + static member inline op_Explicit: value: nativeint -> sbyte + static member inline op_Explicit: value: sbyte -> sbyte + static member inline op_Explicit: value: uint64 -> sbyte + static member inline op_Explicit: value: uint32 -> sbyte + static member inline op_Explicit: value: uint16 -> sbyte + static member inline op_Explicit: value: char -> sbyte + static member inline op_Explicit: value: unativeint -> sbyte + static member inline op_Explicit: value: byte -> sbyte + + static member inline op_Explicit: value: string -> uint16 + static member inline op_Explicit: value: float -> uint16 + static member inline op_Explicit: value: float32 -> uint16 + static member inline op_Explicit: value: int64 -> uint16 + static member inline op_Explicit: value: int32 -> uint16 + static member inline op_Explicit: value: int16 -> uint16 + static member inline op_Explicit: value: nativeint -> uint16 + static member inline op_Explicit: value: sbyte -> uint16 + static member inline op_Explicit: value: uint64 -> uint16 + static member inline op_Explicit: value: uint32 -> uint16 + static member inline op_Explicit: value: uint16 -> uint16 + static member inline op_Explicit: value: char -> uint16 + static member inline op_Explicit: value: unativeint -> uint16 + static member inline op_Explicit: value: byte -> uint16 + + static member inline op_Explicit: value: string -> int16 + static member inline op_Explicit: value: float -> int16 + static member inline op_Explicit: value: float32 -> int16 + static member inline op_Explicit: value: int64 -> int16 + static member inline op_Explicit: value: int32 -> int16 + static member inline op_Explicit: value: int16 -> int16 + static member inline op_Explicit: value: nativeint -> int16 + static member inline op_Explicit: value: sbyte -> int16 + static member inline op_Explicit: value: uint64 -> int16 + static member inline op_Explicit: value: uint32 -> int16 + static member inline op_Explicit: value: uint16 -> int16 + static member inline op_Explicit: value: char -> int16 + static member inline op_Explicit: value: unativeint -> int16 + static member inline op_Explicit: value: byte -> int16 + + static member inline op_Explicit: value: string -> uint32 + static member inline op_Explicit: value: float -> uint32 + static member inline op_Explicit: value: float32 -> uint32 + static member inline op_Explicit: value: int64 -> uint32 + static member inline op_Explicit: value: nativeint -> uint32 + static member inline op_Explicit: value: int32 -> uint32 + static member inline op_Explicit: value: int16 -> uint32 + static member inline op_Explicit: value: sbyte -> uint32 + static member inline op_Explicit: value: uint64 -> uint32 + static member inline op_Explicit: value: uint32 -> uint32 + static member inline op_Explicit: value: uint16 -> uint32 + static member inline op_Explicit: value: char -> uint32 + static member inline op_Explicit: value: unativeint -> uint32 + static member inline op_Explicit: value: byte -> uint32 + + static member inline op_Explicit: value: string -> int32 + static member inline op_Explicit: value: float -> int32 + static member inline op_Explicit: value: float32 -> int32 + static member inline op_Explicit: value: int64 -> int32 + static member inline op_Explicit: value: nativeint -> int32 + static member inline op_Explicit: value: int32 -> int32 + static member inline op_Explicit: value: int16 -> int32 + static member inline op_Explicit: value: sbyte -> int32 + static member inline op_Explicit: value: uint64 -> int32 + static member inline op_Explicit: value: uint32 -> int32 + static member inline op_Explicit: value: uint16 -> int32 + static member inline op_Explicit: value: char -> int32 + static member inline op_Explicit: value: unativeint -> int32 + static member inline op_Explicit: value: byte -> int32 + + static member inline op_Explicit: value: string -> uint64 + static member inline op_Explicit: value: float -> uint64 + static member inline op_Explicit: value: float32 -> uint64 + static member inline op_Explicit: value: int64 -> uint64 + static member inline op_Explicit: value: int32 -> uint64 + static member inline op_Explicit: value: int16 -> uint64 + static member inline op_Explicit: value: nativeint -> uint64 + static member inline op_Explicit: value: sbyte -> uint64 + static member inline op_Explicit: value: uint64 -> uint64 + static member inline op_Explicit: value: uint32 -> uint64 + static member inline op_Explicit: value: uint16 -> uint64 + static member inline op_Explicit: value: char -> uint64 + static member inline op_Explicit: value: unativeint -> uint64 + static member inline op_Explicit: value: byte -> uint64 + + static member inline op_Explicit: value: string -> int64 + static member inline op_Explicit: value: string -> int64 + static member inline op_Explicit: value: float32 -> int64 + static member inline op_Explicit: value: int64 -> int64 + static member inline op_Explicit: value: int32 -> int64 + static member inline op_Explicit: value: int16 -> int64 + static member inline op_Explicit: value: nativeint -> int64 + static member inline op_Explicit: value: sbyte -> int64 + static member inline op_Explicit: value: uint64 -> int64 + static member inline op_Explicit: value: uint32 -> int64 + static member inline op_Explicit: value: uint16 -> int64 + static member inline op_Explicit: value: char -> int64 + static member inline op_Explicit: value: unativeint -> int64 + static member inline op_Explicit: value: byte -> int64 + + static member inline op_Explicit: value: string -> float32 + static member inline op_Explicit: value: float -> float32 + static member inline op_Explicit: value: float32 -> float32 + static member inline op_Explicit: value: int64 -> float32 + static member inline op_Explicit: value: int32 -> float32 + static member inline op_Explicit: value: int16 -> float32 + static member inline op_Explicit: value: nativeint -> float32 + static member inline op_Explicit: value: sbyte -> float32 + static member inline op_Explicit: value: uint64 -> float32 + static member inline op_Explicit: value: uint32 -> float32 + static member inline op_Explicit: value: uint16 -> float32 + static member inline op_Explicit: value: char -> float32 + static member inline op_Explicit: value: unativeint -> float32 + static member inline op_Explicit: value: byte -> float32 + + static member inline op_Explicit: value: string -> float + static member inline op_Explicit: value: float -> float + static member inline op_Explicit: value: float32 -> float + static member inline op_Explicit: value: int64 -> float + static member inline op_Explicit: value: int32 -> float + static member inline op_Explicit: value: int16 -> float + static member inline op_Explicit: value: nativeint -> float + static member inline op_Explicit: value: sbyte -> float + static member inline op_Explicit: value: uint64 -> float + static member inline op_Explicit: value: uint32 -> float + static member inline op_Explicit: value: uint16 -> float + static member inline op_Explicit: value: char -> float + static member inline op_Explicit: value: unativeint -> float + static member inline op_Explicit: value: byte -> float + static member inline op_Explicit: value: decimal -> float + + static member inline op_Explicit: value: string -> decimal + static member inline op_Explicit: value: float -> decimal + static member inline op_Explicit: value: float32 -> decimal + static member inline op_Explicit: value: int64 -> decimal + static member inline op_Explicit: value: int32 -> decimal + static member inline op_Explicit: value: int16 -> decimal + static member inline op_Explicit: value: nativeint -> decimal + static member inline op_Explicit: value: sbyte -> decimal + static member inline op_Explicit: value: uint64 -> decimal + static member inline op_Explicit: value: uint32 -> decimal + static member inline op_Explicit: value: uint16 -> decimal + static member inline op_Explicit: value: unativeint -> decimal + static member inline op_Explicit: value: byte -> decimal + static member inline op_Explicit: value: decimal -> decimal + + static member inline op_Explicit: value: string -> unativeint + static member inline op_Explicit: value: float -> unativeint + static member inline op_Explicit: value: float32 -> unativeint + static member inline op_Explicit: value: int64 -> unativeint + static member inline op_Explicit: value: int32 -> unativeint + static member inline op_Explicit: value: int16 -> unativeint + static member inline op_Explicit: value: nativeint -> unativeint + static member inline op_Explicit: value: sbyte -> unativeint + static member inline op_Explicit: value: uint64 -> unativeint + static member inline op_Explicit: value: uint32 -> unativeint + static member inline op_Explicit: value: uint16 -> unativeint + static member inline op_Explicit: value: char -> unativeint + static member inline op_Explicit: value: unativeint -> unativeint + static member inline op_Explicit: value: byte -> unativeint + + static member inline op_Explicit: value: string -> nativeint + static member inline op_Explicit: value: float -> nativeint + static member inline op_Explicit: value: float32 -> nativeint + static member inline op_Explicit: value: int64 -> nativeint + static member inline op_Explicit: value: int32 -> nativeint + static member inline op_Explicit: value: int16 -> nativeint + static member inline op_Explicit: value: nativeint -> nativeint + static member inline op_Explicit: value: sbyte -> nativeint + static member inline op_Explicit: value: uint64 -> nativeint + static member inline op_Explicit: value: uint32 -> nativeint + static member inline op_Explicit: value: uint16 -> nativeint + static member inline op_Explicit: value: char -> nativeint + static member inline op_Explicit: value: unativeint -> nativeint + static member inline op_Explicit: value: byte -> nativeint + + static member inline op_Explicit: value: string -> char + static member inline op_Explicit: value: float -> char + static member inline op_Explicit: value: float32 -> char + static member inline op_Explicit: value: int64 -> char + static member inline op_Explicit: value: int32 -> char + static member inline op_Explicit: value: int16 -> char + static member inline op_Explicit: value: nativeint -> char + static member inline op_Explicit: value: sbyte -> char + static member inline op_Explicit: value: uint64 -> char + static member inline op_Explicit: value: uint32 -> char + static member inline op_Explicit: value: uint16 -> char + static member inline op_Explicit: value: char -> char + static member inline op_Explicit: value: unativeint -> char + static member inline op_Explicit: value: byte -> char + + static member inline op_LessThan: x: bool * y: bool -> bool + static member inline op_LessThan: x: sbyte * y: sbyte -> bool + static member inline op_LessThan: x: int16 * y: int16 -> bool + static member inline op_LessThan: x: int32 * y: int32 -> bool + static member inline op_LessThan: x: int64 * y: int64 -> bool + static member inline op_LessThan: x: byte * y: byte -> bool + static member inline op_LessThan: x: uint16 * y: uint16 -> bool + static member inline op_LessThan: x: uint32 * y: uint32 -> bool + static member inline op_LessThan: x: uint64 * y: uint64 -> bool + static member inline op_LessThan: x: unativeint * y: unativeint -> bool + static member inline op_LessThan: x: nativeint * y: nativeint -> bool + static member inline op_LessThan: x: float * y: float -> bool + static member inline op_LessThan: x: float32 * y: float32 -> bool + static member inline op_LessThan: x: char * y: char -> bool + static member inline op_LessThan: x: decimal * y: decimal -> bool + static member inline op_LessThan: x: string * y: string -> bool + + static member inline op_GreaterThan: x: bool * y: bool -> bool + static member inline op_GreaterThan: x: sbyte * y: sbyte -> bool + static member inline op_GreaterThan: x: int16 * y: int16 -> bool + static member inline op_GreaterThan: x: int32 * y: int32 -> bool + static member inline op_GreaterThan: x: int64 * y: int64 -> bool + static member inline op_GreaterThan: x: nativeint * y: nativeint -> bool + static member inline op_GreaterThan: x: byte * y: byte -> bool + static member inline op_GreaterThan: x: uint16 * y: uint16 -> bool + static member inline op_GreaterThan: x: uint32 * y: uint32 -> bool + static member inline op_GreaterThan: x: uint64 * y: uint64 -> bool + static member inline op_GreaterThan: x: unativeint * y: unativeint -> bool + static member inline op_GreaterThan: x: float * y: float -> bool + static member inline op_GreaterThan: x: float32 * y: float32 -> bool + static member inline op_GreaterThan: x: char * y: char -> bool + static member inline op_GreaterThan: x: decimal * y: decimal -> bool + static member inline op_GreaterThan: x: string * y: string -> bool + + static member inline op_LessThanOrEqual: x: bool * y: bool -> bool + static member inline op_LessThanOrEqual: x: sbyte * y: sbyte -> bool + static member inline op_LessThanOrEqual: x: int16 * y: int16 -> bool + static member inline op_LessThanOrEqual: x: int32 * y: int32 -> bool + static member inline op_LessThanOrEqual: x: int64 * y: int64 -> bool + static member inline op_LessThanOrEqual: x: nativeint * y: nativeint -> bool + static member inline op_LessThanOrEqual: x: byte * y: byte -> bool + static member inline op_LessThanOrEqual: x: uint16 * y: uint16 -> bool + static member inline op_LessThanOrEqual: x: uint32 * y: uint32 -> bool + static member inline op_LessThanOrEqual: x: uint64 * y: uint64 -> bool + static member inline op_LessThanOrEqual: x: unativeint * y: unativeint -> bool + static member inline op_LessThanOrEqual: x: float * y: unativeint -> bool + static member inline op_LessThanOrEqual: x: float32 * y: float32 -> bool + static member inline op_LessThanOrEqual: x: char * y: char -> bool + static member inline op_LessThanOrEqual: x: decimal * y: decimal -> bool + static member inline op_LessThanOrEqual: x: string * y: string -> bool + + static member inline op_GreaterThanOrEqual: x: bool * y: bool -> bool + static member inline op_GreaterThanOrEqual: x: sbyte * y: sbyte -> bool + static member inline op_GreaterThanOrEqual: x: int16 * y: int16 -> bool + static member inline op_GreaterThanOrEqual: x: int32 * y: int32 -> bool + static member inline op_GreaterThanOrEqual: x: int64 * y: int64 -> bool + static member inline op_GreaterThanOrEqual: x: nativeint * y: nativeint -> bool + static member inline op_GreaterThanOrEqual: x: byte * y: byte -> bool + static member inline op_GreaterThanOrEqual: x: uint16 * y: uint16 -> bool + static member inline op_GreaterThanOrEqual: x: uint32 * y: uint32 -> bool + static member inline op_GreaterThanOrEqual: x: uint64 * y: uint64 -> bool + static member inline op_GreaterThanOrEqual: x: unativeint * y: unativeint -> bool + static member inline op_GreaterThanOrEqual: x: float * y: float -> bool + static member inline op_GreaterThanOrEqual: x: float32 * y: float32 -> bool + static member inline op_GreaterThanOrEqual: x: char * y: char -> bool + static member inline op_GreaterThanOrEqual: x: decimal * y: decimal -> bool + static member inline op_GreaterThanOrEqual: x: string * y: string -> bool + + static member inline op_Equality: x: bool * y: bool -> bool + static member inline op_Equality: x: sbyte * y: sbyte -> bool + static member inline op_Equality: x: int16 * y: int16 -> bool + static member inline op_Equality: x: int32 * y: int32 -> bool + static member inline op_Equality: x: int64 * y: int64 -> bool + static member inline op_Equality: x: byte * y: byte -> bool + static member inline op_Equality: x: uint16 * y: uint16 -> bool + static member inline op_Equality: x: uint32 * y: uint32 -> bool + static member inline op_Equality: x: uint64 * y: uint64 -> bool + static member inline op_Equality: x: float * y: float -> bool + static member inline op_Equality: x: float32 * y: float32 -> bool + static member inline op_Equality: x: char * y: char -> bool + static member inline op_Equality: x: nativeint * y: nativeint -> bool + static member inline op_Equality: x: unativeint * y: unativeint -> bool + static member inline op_Equality: x: string * y: string -> bool + static member inline op_Equality: x: decimal * y: v -> bool + + static member inline op_Inequality: x: bool * y: bool -> bool + static member inline op_Inequality: x: sbyte * y: sbyte -> bool + static member inline op_Inequality: x: int16 * y: int16 -> bool + static member inline op_Inequality: x: int32 * y: int32 -> bool + static member inline op_Inequality: x: int64 * y: int64 -> bool + static member inline op_Inequality: x: byte * y: byte -> bool + static member inline op_Inequality: x: uint16 * y: uint16 -> bool + static member inline op_Inequality: x: uint32 * y: uint32 -> bool + static member inline op_Inequality: x: uint64 * y: uint64 -> bool + static member inline op_Inequality: x: float * y: float -> bool + static member inline op_Inequality: x: float32 * y: float32 -> bool + static member inline op_Inequality: x: char * y: char -> bool + static member inline op_Inequality: x: nativeint * y: nativeint -> bool + static member inline op_Inequality: x: unativeint * y: unativeint -> bool + static member inline op_Inequality: x: string * y: string -> bool + static member inline op_Inequality: x: decimal * y: decimal -> bool + + static member inline DivideByInt: x: float * y: int -> float + static member inline DivideByInt: x: float32 * y: int -> float32 + static member inline DivideByInt: x: decimal * y: int -> decimal + /// For compiler use only module (* internal *) ErrorStrings = @@ -2745,7 +3210,7 @@ namespace Microsoft.FSharp.Core /// input types the operation requires an appropriate static conversion method on the input type. /// The input value. /// The converted char. - [] + [] [] val inline char : value:^T -> char when ^T : (static member op_Explicit : ^T -> char) and default ^T : int @@ -3184,14 +3649,14 @@ namespace Microsoft.FSharp.Core /// Overloaded unary negation (checks for overflow) /// The input value. /// The negated value. - [] + [] val inline ( ~- ) : value:^T -> ^T when ^T : (static member ( ~- ) : ^T -> ^T) and default ^T : int /// Overloaded subtraction operator (checks for overflow) /// The first value. /// The second value. /// The first value minus the second value. - [] + [] val inline ( - ) : x:^T1 -> y:^T2 -> ^T3 when (^T1 or ^T2) : (static member ( - ) : ^T1 * ^T2 -> ^T3) and default ^T2 : ^T3 and default ^T3 : ^T1 and default ^T3 : ^T2 and default ^T1 : ^T3 and default ^T1 : ^T2 and default ^T1 : int /// Overloaded addition operator (checks for overflow) @@ -3204,7 +3669,7 @@ namespace Microsoft.FSharp.Core /// The first value. /// The second value. /// The product of the two input values. - [] + [] val inline ( * ) : x:^T1 -> y:^T2 -> ^T3 when (^T1 or ^T2) : (static member ( * ) : ^T1 * ^T2 -> ^T3) and default ^T2 : ^T3 and default ^T3 : ^T1 and default ^T3 : ^T2 and default ^T1 : ^T3 and default ^T1 : ^T2 and default ^T1 : int /// Converts the argument to byte. This is a direct, checked conversion for all @@ -3213,7 +3678,7 @@ namespace Microsoft.FSharp.Core /// static conversion method on the input type. /// The input value. /// The converted byte - [] + [] [] val inline byte : value:^T -> byte when ^T : (static member op_Explicit : ^T -> byte) and default ^T : int @@ -3223,7 +3688,7 @@ namespace Microsoft.FSharp.Core /// static conversion method on the input type. /// The input value. /// The converted sbyte - [] + [] [] val inline sbyte : value:^T -> sbyte when ^T : (static member op_Explicit : ^T -> sbyte) and default ^T : int @@ -3233,7 +3698,7 @@ namespace Microsoft.FSharp.Core /// static conversion method on the input type. /// The input value. /// The converted int16 - [] + [] [] val inline int16 : value:^T -> int16 when ^T : (static member op_Explicit : ^T -> int16) and default ^T : int @@ -3243,7 +3708,7 @@ namespace Microsoft.FSharp.Core /// static conversion method on the input type. /// The input value. /// The converted uint16 - [] + [] [] val inline uint16 : value:^T -> uint16 when ^T : (static member op_Explicit : ^T -> uint16) and default ^T : int @@ -3253,7 +3718,7 @@ namespace Microsoft.FSharp.Core /// static conversion method on the input type. /// The input value. /// The converted int - [] + [] [] val inline int : value:^T -> int when ^T : (static member op_Explicit : ^T -> int) and default ^T : int @@ -3263,7 +3728,7 @@ namespace Microsoft.FSharp.Core /// static conversion method on the input type. /// The input value. /// The converted int32 - [] + [] [] val inline int32 : value:^T -> int32 when ^T : (static member op_Explicit : ^T -> int32) and default ^T : int @@ -3273,7 +3738,7 @@ namespace Microsoft.FSharp.Core /// static conversion method on the input type. /// The input value. /// The converted uint32 - [] + [] [] val inline uint32 : value:^T -> uint32 when ^T : (static member op_Explicit : ^T -> uint32) and default ^T : int @@ -3283,7 +3748,7 @@ namespace Microsoft.FSharp.Core /// static conversion method on the input type. /// The input value. /// The converted int64 - [] + [] [] val inline int64 : value:^T -> int64 when ^T : (static member op_Explicit : ^T -> int64) and default ^T : int @@ -3293,7 +3758,7 @@ namespace Microsoft.FSharp.Core /// static conversion method on the input type. /// The input value. /// The converted uint64 - [] + [] [] val inline uint64 : value:^T -> uint64 when ^T : (static member op_Explicit : ^T -> uint64) and default ^T : int @@ -3302,7 +3767,7 @@ namespace Microsoft.FSharp.Core /// static conversion method on the input type. /// The input value. /// The converted nativeint - [] + [] [] val inline nativeint : value:^T -> nativeint when ^T : (static member op_Explicit : ^T -> nativeint) and default ^T : int @@ -3311,7 +3776,7 @@ namespace Microsoft.FSharp.Core /// static conversion method on the input type. /// The input value. /// The converted unativeint - [] + [] [] val inline unativeint : value:^T -> unativeint when ^T : (static member op_Explicit : ^T -> unativeint) and default ^T : int @@ -3321,7 +3786,7 @@ namespace Microsoft.FSharp.Core /// appropriate static conversion method on the input type. /// The input value. /// The converted char - [] + [] [] val inline char : value:^T -> char when ^T : (static member op_Explicit : ^T -> char) and default ^T : int From 71e51f6c04a8c56e19bd7d587657d92f89625108 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 29 Mar 2019 18:34:30 +0000 Subject: [PATCH 38/77] more witnesses --- src/fsharp/FSharp.Core/prim-types.fs | 321 ++++++++++++++------------ src/fsharp/FSharp.Core/prim-types.fsi | 92 +++++++- 2 files changed, 260 insertions(+), 153 deletions(-) diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 1dd157f671c..c444959d005 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -2487,21 +2487,6 @@ namespace Microsoft.FSharp.Core static member inline op_Addition(x: string, y: string) = String.Concat(x, y) static member inline op_Addition(x: decimal, y: decimal) = Decimal.op_Addition(x, y) - static member inline op_CheckedAddition(x: int32, y: int32) = (# "add.ovf" x y : int32 #) - static member inline op_CheckedAddition(x: float, y: float) = (# "add" x y : float #) - static member inline op_CheckedAddition(x: float32, y: float32) = (# "add" x y : float32 #) - static member inline op_CheckedAddition(x: int64, y: int64) = (# "add.ovf" x y : int64 #) - static member inline op_CheckedAddition(x: uint64, y: uint64) = (# "add.ovf.un" x y : uint64 #) - static member inline op_CheckedAddition(x: uint32, y: uint32) = (# "add.ovf.un" x y : uint32 #) - static member inline op_CheckedAddition(x: nativeint, y: nativeint) = (# "add.ovf" x y : nativeint #) - static member inline op_CheckedAddition(x: unativeint, y: unativeint) = (# "add.ovf.un" x y : unativeint #) - static member inline op_CheckedAddition(x: int16, y: int16) = (# "conv.ovf.i2" (# "add.ovf" x y : int32 #) : int16 #) - static member inline op_CheckedAddition(x: uint16, y: uint16) = (# "conv.ovf.u2.un" (# "add.ovf.un" x y : uint32 #) : uint16 #) - static member inline op_CheckedAddition(x: char, y: char) = (# "conv.ovf.u2.un" (# "add.ovf.un" x y : uint32 #) : char #) - static member inline op_CheckedAddition(x: sbyte, y: sbyte) = (# "conv.ovf.i1" (# "add.ovf" x y : int32 #) : sbyte #) - static member inline op_CheckedAddition(x: byte, y: byte) = (# "conv.ovf.u1.un" (# "add.ovf.un" x y : uint32 #) : byte #) - static member inline op_CheckedAddition(x: string, y: string) = String.Concat(x, y) - static member inline op_Multiply(x: int32, y: int32) = (# "mul" x y : int32 #) static member inline op_Multiply(x: float, y: float) = (# "mul" x y : float #) static member inline op_Multiply(x: float32, y: float32) = (# "mul" x y : float32 #) @@ -2515,26 +2500,13 @@ namespace Microsoft.FSharp.Core static member inline op_Multiply(x: sbyte, y: sbyte) = (# "conv.i1" (# "mul" x y : int32 #) : sbyte #) static member inline op_Multiply(x: byte, y: byte) = (# "conv.u1" (# "mul" x y : uint32 #) : byte #) - static member inline op_CheckedMultiply(x: int32, y: int32) = (# "mul.ovf" x y : int32 #) - static member inline op_CheckedMultiply(x: float, y: float) = (# "mul" x y : float #) - static member inline op_CheckedMultiply(x: float32, y: float32) = (# "mul" x y : float32 #) - static member inline op_CheckedMultiply(x: int64, y: int64) = (# "mul.ovf" x y : int64 #) - static member inline op_CheckedMultiply(x: uint64, y: uint64) = (# "mul.ovf.un" x y : uint64 #) - static member inline op_CheckedMultiply(x: uint32, y: uint32) = (# "mul.ovf.un" x y : uint32 #) - static member inline op_CheckedMultiply(x: nativeint, y: nativeint) = (# "mul.ovf" x y : nativeint #) - static member inline op_CheckedMultiply(x: unativeint, y: unativeint) = (# "mul.ovf.un" x y : unativeint #) - static member inline op_CheckedMultiply(x: int16, y: int16) = (# "conv.ovf.i2" (# "mul.ovf" x y : int32 #) : int16 #) - static member inline op_CheckedMultiply(x: uint16, y: uint16) = (# "conv.ovf.u2.un" (# "mul.ovf.un" x y : uint16 #) : uint16 #) - static member inline op_CheckedMultiply(x: sbyte, y: sbyte) = (# "conv.ovf.i1" (# "mul.ovf" x y : int32 #) : sbyte #) - static member inline op_CheckedMultiply(x: byte, y: byte) = (# "conv.ovf.u1.un" (# "mul.ovf.un" x y : uint32 #) : byte #) - - static member inline op_UnaryNegation(x: int32) = (# "neg" x : int32 #) - static member inline op_UnaryNegation(x: float) = (# "neg" x : float #) - static member inline op_UnaryNegation(x: float32) = (# "neg" x : float32 #) - static member inline op_UnaryNegation(x: int64) = (# "neg" x : int64 #) - static member inline op_UnaryNegation(x: int16) = (# "neg" x : int16 #) - static member inline op_UnaryNegation(x: nativeint) = (# "neg" x : nativeint #) - static member inline op_UnaryNegation(x: sbyte) = (# "neg" x : sbyte #) + static member inline op_UnaryNegation(value: int32) = (# "neg" value : int32 #) + static member inline op_UnaryNegation(value: float) = (# "neg" value : float #) + static member inline op_UnaryNegation(value: float32) = (# "neg" value : float32 #) + static member inline op_UnaryNegation(value: int64) = (# "neg" value : int64 #) + static member inline op_UnaryNegation(value: int16) = (# "neg" value : int16 #) + static member inline op_UnaryNegation(value: nativeint) = (# "neg" value : nativeint #) + static member inline op_UnaryNegation(value: sbyte) = (# "neg" value : sbyte #) static member inline op_Subtraction(x: int32, y: int32) = (# "sub" x y : int32 #) static member inline op_Subtraction(x: float, y: float) = (# "sub" x y : float #) @@ -2578,6 +2550,55 @@ namespace Microsoft.FSharp.Core static member inline op_Modulus(x: byte, y: byte) = (# "conv.u1" (# "rem.un" x y : uint32 #) : byte #) static member inline op_Modulus(x: decimal, y: decimal) = Decimal.op_Modulus(x, y) + static member inline op_CheckedAddition(x: int32, y: int32) = (# "add.ovf" x y : int32 #) + static member inline op_CheckedAddition(x: float, y: float) = (# "add" x y : float #) + static member inline op_CheckedAddition(x: float32, y: float32) = (# "add" x y : float32 #) + static member inline op_CheckedAddition(x: int64, y: int64) = (# "add.ovf" x y : int64 #) + static member inline op_CheckedAddition(x: uint64, y: uint64) = (# "add.ovf.un" x y : uint64 #) + static member inline op_CheckedAddition(x: uint32, y: uint32) = (# "add.ovf.un" x y : uint32 #) + static member inline op_CheckedAddition(x: nativeint, y: nativeint) = (# "add.ovf" x y : nativeint #) + static member inline op_CheckedAddition(x: unativeint, y: unativeint) = (# "add.ovf.un" x y : unativeint #) + static member inline op_CheckedAddition(x: int16, y: int16) = (# "conv.ovf.i2" (# "add.ovf" x y : int32 #) : int16 #) + static member inline op_CheckedAddition(x: uint16, y: uint16) = (# "conv.ovf.u2.un" (# "add.ovf.un" x y : uint32 #) : uint16 #) + static member inline op_CheckedAddition(x: char, y: char) = (# "conv.ovf.u2.un" (# "add.ovf.un" x y : uint32 #) : char #) + static member inline op_CheckedAddition(x: sbyte, y: sbyte) = (# "conv.ovf.i1" (# "add.ovf" x y : int32 #) : sbyte #) + static member inline op_CheckedAddition(x: byte, y: byte) = (# "conv.ovf.u1.un" (# "add.ovf.un" x y : uint32 #) : byte #) + static member inline op_CheckedAddition(x: string, y: string) = String.Concat(x, y) + + static member inline op_CheckedSubtraction(x: int32, y: int32) = (# "sub.ovf" x y : int32 #) + static member inline op_CheckedSubtraction(x: float, y: float) = (# "sub" x y : float #) + static member inline op_CheckedSubtraction(x: float32, y: float32) = (# "sub" x y : float32 #) + static member inline op_CheckedSubtraction(x: int64, y: int64) = (# "sub.ovf" x y : int64 #) + static member inline op_CheckedSubtraction(x: uint64, y: uint64) = (# "sub.ovf.un" x y : uint64 #) + static member inline op_CheckedSubtraction(x: uint32, y: uint32) = (# "sub.ovf.un" x y : uint32 #) + static member inline op_CheckedSubtraction(x: nativeint, y: nativeint) = (# "sub.ovf" x y : nativeint #) + static member inline op_CheckedSubtraction(x: unativeint, y: unativeint) = (# "sub.ovf.un" x y : unativeint #) + static member inline op_CheckedSubtraction(x: int16, y: int16) = (# "conv.ovf.i2" (# "sub.ovf" x y : int32 #) : int16 #) + static member inline op_CheckedSubtraction(x: uint16, y: uint16) = (# "conv.ovf.u2.un" (# "sub.ovf.un" x y : uint32 #) : uint16 #) + static member inline op_CheckedSubtraction(x: sbyte, y: sbyte) = (# "conv.ovf.i1" (# "sub.ovf" x y : int32 #) : sbyte #) + static member inline op_CheckedSubtraction(x: byte, y: byte) = (# "conv.ovf.u1.un" (# "sub.ovf.un" x y : uint32 #) : byte #) + + static member inline op_CheckedMultiply(x: int32, y: int32) = (# "mul.ovf" x y : int32 #) + static member inline op_CheckedMultiply(x: float, y: float) = (# "mul" x y : float #) + static member inline op_CheckedMultiply(x: float32, y: float32) = (# "mul" x y : float32 #) + static member inline op_CheckedMultiply(x: int64, y: int64) = (# "mul.ovf" x y : int64 #) + static member inline op_CheckedMultiply(x: uint64, y: uint64) = (# "mul.ovf.un" x y : uint64 #) + static member inline op_CheckedMultiply(x: uint32, y: uint32) = (# "mul.ovf.un" x y : uint32 #) + static member inline op_CheckedMultiply(x: nativeint, y: nativeint) = (# "mul.ovf" x y : nativeint #) + static member inline op_CheckedMultiply(x: unativeint, y: unativeint) = (# "mul.ovf.un" x y : unativeint #) + static member inline op_CheckedMultiply(x: int16, y: int16) = (# "conv.ovf.i2" (# "mul.ovf" x y : int32 #) : int16 #) + static member inline op_CheckedMultiply(x: uint16, y: uint16) = (# "conv.ovf.u2.un" (# "mul.ovf.un" x y : uint16 #) : uint16 #) + static member inline op_CheckedMultiply(x: sbyte, y: sbyte) = (# "conv.ovf.i1" (# "mul.ovf" x y : int32 #) : sbyte #) + static member inline op_CheckedMultiply(x: byte, y: byte) = (# "conv.ovf.u1.un" (# "mul.ovf.un" x y : uint32 #) : byte #) + + static member inline op_CheckedUnaryNegation(value: int32) = (# "sub.ovf" 0 value : int32 #) + static member inline op_CheckedUnaryNegation(value: float) = (# "neg" value : float #) + static member inline op_CheckedUnaryNegation(value: float32) = (# "neg" value : float32 #) + static member inline op_CheckedUnaryNegation(value: int64) = (# "sub.ovf" 0L value : int64 #) + static member inline op_CheckedUnaryNegation(value: int16) = (# "sub.ovf" 0s value : int16 #) + static member inline op_CheckedUnaryNegation(value: nativeint) = (# "sub.ovf" 0n value : nativeint #) + static member inline op_CheckedUnaryNegation(value: sbyte) = (# "sub.ovf" 0y value : sbyte #) + static member inline op_LeftShift(value: int32, shift: int32) = (# "shl" value (mask shift 31) : int #) static member inline op_LeftShift(value: uint32, shift: int32) = (# "shl" value (mask shift 31) : uint32 #) static member inline op_LeftShift(value: int64, shift: int32) = (# "shl" value (mask shift 63) : int64 #) @@ -2659,7 +2680,7 @@ namespace Microsoft.FSharp.Core static member inline op_Explicit(value: unativeint) : byte = (# "conv.u1" value : byte #) static member inline op_Explicit(value: byte) : byte = (# "conv.u1" value : byte #) - static member inline op_Explicit(value: byte) : sbyte = ParseSByte value + static member inline op_Explicit(value: string) : sbyte = ParseSByte value static member inline op_Explicit(value: float) : sbyte = (# "conv.i1" value : sbyte #) static member inline op_Explicit(value: float32) : sbyte = (# "conv.i1" value : sbyte #) static member inline op_Explicit(value: int64) : sbyte = (# "conv.i1" value : sbyte #) @@ -2750,7 +2771,7 @@ namespace Microsoft.FSharp.Core static member inline op_Explicit(value: byte) : uint64 = (# "conv.u8" value : uint64 #) static member inline op_Explicit(value: string) : int64 = ParseInt64 value - static member inline op_Explicit(value: string) : int64 = (# "conv.i8" value : int64 #) + static member inline op_Explicit(value: float) : int64 = (# "conv.i8" value : int64 #) static member inline op_Explicit(value: float32) : int64 = (# "conv.i8" value : int64 #) static member inline op_Explicit(value: int64) : int64 = (# "conv.i8" value : int64 #) static member inline op_Explicit(value: int32) : int64 = (# "conv.i8" value : int64 #) @@ -2795,19 +2816,19 @@ namespace Microsoft.FSharp.Core static member inline op_Explicit(value: byte) : float = (# "conv.r.un conv.r8" value : float #) static member inline op_Explicit(value: decimal) : float = Convert.ToDouble(value) - static member inline op_Explicit(value: string) : decimal = Decimal.Parse(value,NumberStyles.Float,CultureInfo.InvariantCulture)) + static member inline op_Explicit(value: string) : decimal = Decimal.Parse(value,NumberStyles.Float,CultureInfo.InvariantCulture) static member inline op_Explicit(value: float) : decimal = Convert.ToDecimal(value) static member inline op_Explicit(value: float32) : decimal = Convert.ToDecimal(value) static member inline op_Explicit(value: int64) : decimal = Convert.ToDecimal(value) static member inline op_Explicit(value: int32) : decimal = Convert.ToDecimal(value) static member inline op_Explicit(value: int16) : decimal = Convert.ToDecimal(value) - static member inline op_Explicit(value: nativeint) : decimal = Convert.ToDecimal(int64 value) + static member inline op_Explicit(value: nativeint) : decimal = Convert.ToDecimal(BuiltInWitnesses.op_Explicit value : int64) static member inline op_Explicit(value: sbyte) : decimal = Convert.ToDecimal(value) static member inline op_Explicit(value: uint64) : decimal = Convert.ToDecimal(value) static member inline op_Explicit(value: uint32) : decimal = Convert.ToDecimal(value) static member inline op_Explicit(value: uint16) : decimal = Convert.ToDecimal(value) - static member inline op_Explicit(value: unativeint) : decimal = Convert.ToDecimal(uint64 value) - static member inline op_Explicit(value: byte) : decimal = Convert.ToDecimal(value decimal #))) + static member inline op_Explicit(value: unativeint) : decimal = Convert.ToDecimal(BuiltInWitnesses.op_Explicit value : uint64) + static member inline op_Explicit(value: byte) : decimal = Convert.ToDecimal(value) static member inline op_Explicit(value: decimal) : decimal = value static member inline op_Explicit(value: string) : unativeint = ParseUIntPtr value @@ -2938,7 +2959,7 @@ namespace Microsoft.FSharp.Core static member inline op_Equality(x: nativeint, y: nativeint) = (# "ceq" x y : bool #) static member inline op_Equality(x: unativeint, y: unativeint) = (# "ceq" x y : bool #) static member inline op_Equality(x: string, y: string) = String.Equals(x, y) - static member inline op_Equality(x: decimal, y: v) = Decimal.op_Equality(x, y) + static member inline op_Equality(x: decimal, y: decimal) = Decimal.op_Equality(x, y) static member inline op_Inequality(x: bool, y: bool) = not (# "ceq" x y : bool #) static member inline op_Inequality(x: sbyte, y: sbyte) = not (# "ceq" x y : bool #) @@ -2957,6 +2978,7 @@ namespace Microsoft.FSharp.Core static member inline op_Inequality(x: string, y: string) = not (String.Equals(x, y)) static member inline op_Inequality(x: decimal, y: decimal) = Decimal.op_Inequality(x, y) + // TODO: rationalise these type GenericZeroDynamicImplTable<'T>() = static let result : 'T = // The dynamic implementation @@ -2979,6 +3001,7 @@ namespace Microsoft.FSharp.Core unboxPrim<'T> (pinfo.GetValue(null,null)) static member Result : 'T = result + // TODO: rationalise these type GenericOneDynamicImplTable<'T>() = static let result : 'T = // The dynamic implementation @@ -3006,6 +3029,7 @@ namespace Microsoft.FSharp.Core let GenericZeroDynamic<'T>() : 'T = GenericZeroDynamicImplTable<'T>.Result let GenericOneDynamic<'T>() : 'T = GenericOneDynamicImplTable<'T>.Result + // TODO: rationalise these let inline GenericZero< ^T when ^T : (static member Zero : ^T) > : ^T = GenericZeroDynamic<(^T)>() when ^T : int32 = 0 @@ -3025,6 +3049,7 @@ namespace Microsoft.FSharp.Core // this condition is used whenever ^T is resolved to a nominal type or witnesses are available when ^T : ^T = (^T : (static member Zero : ^T) ()) + // TODO: rationalise these let inline GenericOne< ^T when ^T : (static member One : ^T) > : ^T = GenericOneDynamic<(^T)>() when ^T : int32 = 1 @@ -3046,6 +3071,7 @@ namespace Microsoft.FSharp.Core // That is, not in the generic implementation of '+' when ^T : ^T = (^T : (static member One : ^T) ()) + // TODO: rationalise these type GenericDivideByIntDynamicImplTable<'T>() = static let result : ('T -> int -> 'T) = // The dynamic implementation @@ -3054,14 +3080,16 @@ namespace Microsoft.FSharp.Core elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float) (n:int) -> (# "div" x ((# "conv.r8" n : float #)) : float #))) elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float32) (n:int) -> (# "div" x ((# "conv.r4" n : float32 #)) : float32 #))) else - match aty.GetMethod("DivideByInt",[| aty; typeof |]) with + match aty.GetRuntimeMethod("DivideByInt",[| aty; typeof |]) with | null -> raise (NotSupportedException (SR.GetString(SR.dyInvDivByIntCoerce))) | m -> (fun x n -> unboxPrim<_> (m.Invoke(null,[| box x; box n |]))) static member Result : ('T -> int -> 'T) = result + // TODO: rationalise these let DivideByIntDynamic<'T> x y = GenericDivideByIntDynamicImplTable<('T)>.Result x y + // TODO: rationalise these let inline DivideByInt< ^T when ^T : (static member DivideByInt : ^T * int -> ^T) > (x:^T) (y:int) : ^T = DivideByIntDynamic<'T> x y when ^T : float = (# "div" x ((# "conv.r8" (y:int) : float #)) : float #) @@ -3069,6 +3097,19 @@ namespace Microsoft.FSharp.Core when ^T : decimal = Decimal.Divide((retype x:decimal), Convert.ToDecimal(y)) when ^T : ^T = (^T : (static member DivideByInt : ^T * int -> ^T) (x, y)) + // TODO: rationalise these + let UnaryDynamicImpl nm : ('T -> 'U) = + let aty = typeof<'T> + let minfo = aty.GetRuntimeMethod(nm, [| aty |]) + (fun x -> unboxPrim<_>(minfo.Invoke(null,[| box x|]))) + + // TODO: rationalise these + let BinaryDynamicImpl nm : ('T -> 'U -> 'V) = + let aty = typeof<'T> + let bty = typeof<'U> + let minfo = aty.GetRuntimeMethod(nm,[| aty;bty |]) + (fun x y -> unboxPrim<_>(minfo.Invoke(null,[| box x; box y|]))) + // Dynamic implementation of operator resolution, using BuiltInWitnesses as backing data type UnaryOpDynamicImplTable<'OpInfo,'T,'U>() = static let impl : ('T -> 'U) = @@ -3077,30 +3118,30 @@ namespace Microsoft.FSharp.Core let bty = typeof<'U> // Find the operator name - let staticBindingFlags = (BindingFlags.Static ||| BindingFlags.Public ||| BindingFlags.NonPublic) - let opNameMeth = typeof<'OpInfo>.GetMethod("get_Name", staticBindingFlags, [| |], null) - let opName = opNameMeth.Invoke(null) :?> string - let builtinNameMeth = typeof<'OpInfo>.GetMethod("get_BuiltInName", staticBindingFlags, [| |], null) - let builtinName = match builtinNameMeth with null -> opName | _ -> builtinNameMeth.Invoke(null) :?> string + //let staticBindingFlags = (BindingFlags.Static ||| BindingFlags.Public ||| BindingFlags.NonPublic) + let opNameMeth = typeof<'OpInfo>.GetRuntimeMethod("get_Name", [| |] (*, staticBindingFlags, [| |], null*) ) + let opName = opNameMeth.Invoke(null, [| |]) :?> string + let builtinNameMeth = typeof<'OpInfo>.GetRuntimeMethod("get_BuiltInName", (* staticBindingFlags, *) [| |] (*, null *) ) + let builtinName = match builtinNameMeth with null -> opName | _ -> builtinNameMeth.Invoke(null, [| |]) :?> string let meth = let witnessesTy = typeof let cmeth = - if builtinName = "op_Explicit" then - let meths = witnessesTy.GetMethods(staticBindingFlags) + if builtinName.Equals("op_Explicit") then + let meths = witnessesTy.GetRuntimeMethods( (* staticBindingFlags *) ) let mutable res = null for meth in meths do - if meth.Name = builtinName - && meth.GetParameters().[0].ParameterType.Equals(aty) && - && meth.ReturnType.Equals(bty) then - res <- meth + if meth.Name.Equals(builtinName) then + if (IntrinsicFunctions.GetArray (meth.GetParameters()) 0).ParameterType.Equals(aty) then + if meth.ReturnType.Equals(bty) then + res <- meth res else - witnessesTy.GetMethod(builtinName, staticBindingFlags, [| aty |], null) + witnessesTy.GetRuntimeMethod(builtinName, (* , staticBindingFlags *) [| aty |] (* , null *) ) match cmeth with | null -> - let ameth = aty.GetMethod(opName,[| aty |]) + let ameth = aty.GetRuntimeMethod(opName, [| aty |]) match ameth with | null -> raise (NotSupportedException (SR.GetString(SR.dyInvOpAddCoerce))) | res -> res @@ -3115,100 +3156,106 @@ namespace Microsoft.FSharp.Core // The dynamic implementation let aty = typeof<'T> let bty = typeof<'U> - let cty = typeof<'V> // Find the operator name - let staticBindingFlags = (BindingFlags.Static ||| BindingFlags.Public ||| BindingFlags.NonPublic) - let opNameMeth = typeof<'OpInfo>.GetMethod("get_Name", staticBindingFlags, [| |], null) - let opName = opNameMeth.Invoke(null) :?> string - let builtinNameMeth = typeof<'OpInfo>.GetMethod("get_BuiltInName", staticBindingFlags, [| |], null) - let builtinName = match builtinNameMeth with null -> opName | _ -> builtinNameMeth.Invoke(null) :?> string + //let staticBindingFlags = (BindingFlags.Static ||| BindingFlags.Public ||| BindingFlags.NonPublic) + let opNameMeth = typeof<'OpInfo>.GetRuntimeMethod("get_Name" (* , staticBindingFlags *) , [| |] (*, null *) ) + let opName = opNameMeth.Invoke(null, [| |]) :?> string + let builtinNameMeth = typeof<'OpInfo>.GetRuntimeMethod("get_BuiltInName" (*, staticBindingFlags *) , [| |] (*, null *) ) + let builtinName = match builtinNameMeth with null -> opName | _ -> builtinNameMeth.Invoke(null, [| |]) :?> string let meth = let witnessesTy = typeof - let cmeth = witnessesTy.GetMethod(builtinName, staticBindingFlags, [| aty; bty |], null) + let cmeth = witnessesTy.GetRuntimeMethod(builtinName (*, staticBindingFlags *) , [| aty; bty |] (*, null *) ) match cmeth with - | res -> res | null -> - let ameth = aty.GetMethod(opName,[| aty; bty |]) - let bmeth = if aty.Equals(bty) then null else bty.GetMethod(opName,[| aty; bty |]) + let ameth = aty.GetRuntimeMethod(opName, [| aty; bty |]) + let bmeth = if aty.Equals(bty) then null else bty.GetRuntimeMethod(opName, [| aty; bty |]) match ameth, bmeth with | null, null -> raise (NotSupportedException (SR.GetString(SR.dyInvOpAddCoerce))) | m, null | null, m -> m | _ -> raise (NotSupportedException (SR.GetString(SR.dyInvOpAddOverload))) + | res -> res (fun x y -> unboxPrim<_> (meth.Invoke(null,[| box x; box y |]))) static member Impl : ('T -> 'U -> 'V) = impl - type OpAdditionLabel = static member Name = "op_Addition" - let AdditionDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + type OpAdditionInfo = static member Name = "op_Addition" + let AdditionDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - type OpCheckedAdditionLabel = - static member Name = "op_Addition" - static member BuiltInName = "op_CheckedAddition" - let CheckedAdditionDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + type OpSubtractionInfo = static member Name = "op_Subtraction" + let SubtractionDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - type OpSubtractionLabel = static member Name = "op_Subtraction" - let SubtractionDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + type OpMultiplyInfo = static member Name = "op_Multiply" + let MultiplyDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - type OpMultiplyLabel = static member Name = "op_Multiply" - let MultiplyDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + type OpDivisionInfo = static member Name = "op_Division" + let DivisionDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - type OpCheckedMultiplyLabel = - static member Name = "op_Multiply" - static member BuiltInName = "op_CheckedMultiply" - let CheckedMultiplyDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + type OpModulusInfo = static member Name = "op_Modulus" + let ModulusDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - type OpDivisionLabel = static member Name = "op_Division" - let DivisionDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + type OpUnaryNegationInfo = static member Name = "op_UnaryNegation" + let UnaryNegationDynamic<'T,'U> value = UnaryOpDynamicImplTable.Impl value - type OpModulusLabel = static member Name = "op_Modulus" - let ModulusDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + type OpCheckedAdditionInfo = + static member Name = "op_Addition" + static member BuiltInName = "op_CheckedAddition" + let CheckedAdditionDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + + type OpCheckedSubtractionInfo = + static member Name = "op_Subtraction" + static member BuiltInName = "op_CheckedSubtraction" + let CheckedSubtractionDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - type OpLeftShiftLabel = static member Name = "op_LeftShift" - let LeftShiftDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + type OpCheckedMultiplyInfo = + static member Name = "op_Multiply" + static member BuiltInName = "op_CheckedMultiply" + let CheckedMultiplyDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - type OpRightShiftLabel = static member Name = "op_RightShift" - let RightShiftDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + type OpCheckedUnaryNegationInfo = + static member Name = "op_UnaryNegation" + static member BuiltInName = "op_CheckedUnaryNegation" + let CheckedUnaryNegationDynamic<'T,'U> value = UnaryOpDynamicImplTable.Impl value - type OpBitwiseAndLabel = static member Name = "op_BitwiseAnd" - let BitwiseAndDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + type OpLeftShiftInfo = static member Name = "op_LeftShift" + let OpLeftShiftDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - type OpBitwiseOrLabel = static member Name = "op_BitwiseOr" - let BitwiseOrDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + type OpRightShiftInfo = static member Name = "op_RightShift" + let OpRightShiftDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - type OpBitwiseAndLabel = static member Name = "op_BitwiseAnd" - let BitwiseAndDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + type OpBitwiseAndInfo = static member Name = "op_BitwiseAnd" + let OpBitwiseAndDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - type OpBitwiseExclusiveOrLabel = static member Name = "op_BitwiseExclusiveOr" - let BitwiseExclusiveOrDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + type OpBitwiseOrInfo = static member Name = "op_BitwiseOr" + let OpBitwiseOrDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - type OpLogicalNotLabel = static member Name = "op_LogicalNot" - let LogicalNotDynamic<'T,'U> x = UnaryOpDynamicImplTable.Impl x + type OpBitwiseExclusiveOrInfo = static member Name = "op_BitwiseExclusiveOr" + let OpBitwiseExclusiveOrDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - type OpExplicitLabel = static member Name = "op_Explicit" - let OpExplicitDynamic<'T,'U> x y = UnaryOpDynamicImplTable.Impl x y + type OpLogicalNotInfo = static member Name = "op_LogicalNot" + let OpLogicalNotDynamic<'T,'U> x = UnaryOpDynamicImplTable.Impl x - type OpLessThanLabel = static member Name = "op_LessThan" - let OpLessThanDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + type OpExplicitInfo = static member Name = "op_Explicit" + let OpExplicitDynamic<'T,'U> x = UnaryOpDynamicImplTable.Impl x - type OpGreaterThanLabel = static member Name = "op_GreaterThan" - let OpGreaterThanDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + type OpLessThanInfo = static member Name = "op_LessThan" + let OpLessThanDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - type OpLessThanOrEqualLabel = static member Name = "op_LessThanOrEqual" - let OpLessThanOrEqualDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + type OpGreaterThanInfo = static member Name = "op_GreaterThan" + let OpGreaterThanDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - type OpGreaterThanOrEqualLabel = static member Name = "op_GreaterThanOrEqual" - let OpGreaterThanOrEqualDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + type OpLessThanOrEqualInfo = static member Name = "op_LessThanOrEqual" + let OpLessThanOrEqualDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - type OpEqualityLabel = static member Name = "op_Equality" - let OpEqualityDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + type OpGreaterThanOrEqualInfo = static member Name = "op_GreaterThanOrEqual" + let OpGreaterThanOrEqualDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - type OpInequalityLabel = static member Name = "op_Inequality" - let InequalityDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + type OpEqualityInfo = static member Name = "op_Equality" + let OpEqualityDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - type OpBitwiseAndLabel = static member Name = "op_BitwiseAnd" - let BitwiseAndDynamic<'T,'U,'V> x y = BitwiseAndDynamicImplTable.Impl x y + type OpInequalityInfo = static member Name = "op_Inequality" + let OpInequalityDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y namespace Microsoft.FSharp.Core @@ -3573,10 +3620,7 @@ namespace Microsoft.FSharp.Core namespace Microsoft.FSharp.Collections - //------------------------------------------------------------------------- - // Lists - //------------------------------------------------------------------------- - + open System open System.Collections.Generic open System.Diagnostics open Microsoft.FSharp.Core @@ -3636,10 +3680,6 @@ namespace Microsoft.FSharp.Collections type ResizeArray<'T> = System.Collections.Generic.List<'T> - //------------------------------------------------------------------------- - // List (augmentation) - //------------------------------------------------------------------------- - module PrivateListHelpers = let notStarted() = raise (new System.InvalidOperationException(SR.GetString(SR.enumerationNotStarted))) @@ -4071,7 +4111,7 @@ namespace Microsoft.FSharp.Core when ^T : ^T = (^T: (static member (~+) : ^T -> ^T) (value)) let inline (<<<) (value: ^T) (shift:int) : ^T = - LeftShiftDynamic<(^T),int,(^T)> value shift + OpLeftShiftDynamic<(^T),int,(^T)> value shift when ^T : int32 = (# "shl" value (mask shift 31) : int #) when ^T : uint32 = (# "shl" value (mask shift 31) : uint32 #) when ^T : int64 = (# "shl" value (mask shift 63) : int64 #) @@ -4087,7 +4127,7 @@ namespace Microsoft.FSharp.Core when ^T : ^T = (^T: (static member (<<<) : ^T * int -> ^T) (value,shift)) let inline (>>>) (value: ^T) (shift:int) : ^T = - RightShiftDynamic<(^T),int,(^T)> value shift + OpRightShiftDynamic<(^T),int,(^T)> value shift when ^T : int32 = (# "shr" value (mask shift 31) : int32 #) when ^T : uint32 = (# "shr.un" value (mask shift 31) : uint32 #) when ^T : int64 = (# "shr" value (mask shift 63) : int64 #) @@ -4103,7 +4143,7 @@ namespace Microsoft.FSharp.Core when ^T : ^T = (^T: (static member (>>>) : ^T * int -> ^T) (value, shift)) let inline (&&&) (x: ^T) (y: ^T) : ^T = - BitwiseAndDynamic<(^T),(^T),(^T)> x y + OpBitwiseAndDynamic<(^T),(^T),(^T)> x y when ^T : int32 = (# "and" x y : int32 #) when ^T : int64 = (# "and" x y : int64 #) when ^T : uint64 = (# "and" x y : uint64 #) @@ -4119,7 +4159,7 @@ namespace Microsoft.FSharp.Core when ^T : ^T = (^T: (static member (&&&) : ^T * ^T -> ^T) (x, y)) let inline (|||) (x: ^T) (y: ^T) : ^T = - BitwiseOrDynamic<(^T),(^T),(^T)> x y + OpBitwiseOrDynamic<(^T),(^T),(^T)> x y when ^T : int32 = (# "or" x y : int32 #) when ^T : int64 = (# "or" x y : int64 #) when ^T : uint64 = (# "or" x y : uint64 #) @@ -4135,7 +4175,7 @@ namespace Microsoft.FSharp.Core when ^T : ^T = (^T: (static member (|||) : ^T * ^T -> ^T) (x, y)) let inline (^^^) (x: ^T) (y: ^T) : ^T = - BitwiseExclusiveOrDynamic<(^T),(^T),(^T)> x y + OpBitwiseExclusiveOrDynamic<(^T),(^T),(^T)> x y when ^T : int32 = (# "xor" x y : int32 #) when ^T : int64 = (# "xor" x y : int64 #) when ^T : uint64 = (# "xor" x y : uint64 #) @@ -4151,7 +4191,7 @@ namespace Microsoft.FSharp.Core when ^T : ^T = (^T: (static member (^^^) : ^T * ^T -> ^T) (x, y)) let inline (~~~) (value: ^T) : ^T = - LogicalNotDynamic<(^T),(^T)> x y + OpLogicalNotDynamic<(^T),(^T)> value when ^T : int32 = (# "not" value : int32 #) when ^T : int64 = (# "not" value : int64 #) when ^T : uint64 = (# "not" value : uint64 #) @@ -4554,7 +4594,7 @@ namespace Microsoft.FSharp.Core module NonStructuralComparison = /// Static less-than with static optimizations for some well-known cases. let inline (<) (x:^T) (y:^U) = - OpLessThanDynamic<(^T), (^U), bool> value + OpLessThanDynamic<(^T), (^U), bool> x y when ^T : bool = (# "clt" x y : bool #) when ^T : sbyte = (# "clt" x y : bool #) when ^T : int16 = (# "clt" x y : bool #) @@ -4577,7 +4617,7 @@ namespace Microsoft.FSharp.Core /// Static greater-than with static optimizations for some well-known cases. let inline (>) (x:^T) (y:^U) = - OpGreaterThanDynamic<(^T), (^U), bool> value + OpGreaterThanDynamic<(^T), (^U), bool> x y when 'T : bool = (# "cgt" x y : bool #) when 'T : sbyte = (# "cgt" x y : bool #) when 'T : int16 = (# "cgt" x y : bool #) @@ -4600,7 +4640,7 @@ namespace Microsoft.FSharp.Core /// Static less-than-or-equal with static optimizations for some well-known cases. let inline (<=) (x:^T) (y:^U) = - OpLessThanOrEqualDynamic<(^T), (^U), bool> value + OpLessThanOrEqualDynamic<(^T), (^U), bool> x y when 'T : bool = not (# "cgt" x y : bool #) when 'T : sbyte = not (# "cgt" x y : bool #) when 'T : int16 = not (# "cgt" x y : bool #) @@ -4623,7 +4663,7 @@ namespace Microsoft.FSharp.Core /// Static greater-than-or-equal with static optimizations for some well-known cases. let inline (>=) (x:^T) (y:^U) = - OpGreaterThanOrEqualDynamic<(^T), (^U), bool> value + OpGreaterThanOrEqualDynamic<(^T), (^U), bool> x y when 'T : bool = not (# "clt" x y : bool #) when 'T : sbyte = not (# "clt" x y : bool #) when 'T : int16 = not (# "clt" x y : bool #) @@ -4646,7 +4686,7 @@ namespace Microsoft.FSharp.Core /// Static greater-than-or-equal with static optimizations for some well-known cases. let inline (=) (x:^T) (y:^T) = - OpEqualityDynamic<(^T), (^T), bool> value + OpEqualityDynamic<(^T), (^T), bool> x y when ^T : bool = (# "ceq" x y : bool #) when ^T : sbyte = (# "ceq" x y : bool #) when ^T : int16 = (# "ceq" x y : bool #) @@ -4666,7 +4706,7 @@ namespace Microsoft.FSharp.Core when ^T : ^T = (^T : (static member (=) : ^T * ^T -> bool) (x,y)) let inline (<>) (x:^T) (y:^T) = - InequalityDynamic<(^T), (^T), bool> value + OpInequalityDynamic<(^T), (^T), bool> x y when ^T : bool = not (# "ceq" x y : bool #) when ^T : sbyte = not (# "ceq" x y : bool #) when ^T : int16 = not (# "ceq" x y : bool #) @@ -4989,7 +5029,7 @@ namespace Microsoft.FSharp.Core // According to the somewhat subtle rules of static optimizations, // this condition is used whenever ^T is resolved to a nominal type or witnesses are available // That is, not in the generic implementation of '*' - when ^T : ^T = (^T : (static member op_Explicit: ^T -> byte) (value)) + when ^T : ^T = (^T : (static member op_Explicit: ^T -> uint16) (value)) [] let inline char (value: ^T) = @@ -5817,17 +5857,6 @@ namespace Microsoft.FSharp.Core when ^T : float = System.Math.Pow((retype x : float), (retype y: float)) when ^T : float32 = System.Math.Pow(toFloat (retype x), toFloat(retype y)) |> toFloat32 - let UnaryDynamicImpl nm : ('T -> 'U) = - let aty = typeof<'T> - let minfo = aty.GetMethod(nm, [| aty |]) - (fun x -> unboxPrim<_>(minfo.Invoke(null,[| box x|]))) - - let BinaryDynamicImpl nm : ('T -> 'U -> 'V) = - let aty = typeof<'T> - let bty = typeof<'U> - let minfo = aty.GetMethod(nm,[| aty;bty |]) - (fun x y -> unboxPrim<_>(minfo.Invoke(null,[| box x; box y|]))) - type AbsDynamicImplTable<'T>() = static let result : ('T -> 'T) = let aty = typeof<'T> diff --git a/src/fsharp/FSharp.Core/prim-types.fsi b/src/fsharp/FSharp.Core/prim-types.fsi index e0aa07db283..b596c806a71 100644 --- a/src/fsharp/FSharp.Core/prim-types.fsi +++ b/src/fsharp/FSharp.Core/prim-types.fsi @@ -1065,30 +1065,106 @@ namespace Microsoft.FSharp.Core [] val GenericOneDynamic : unit -> 'T - /// A compiler intrinsic that implements dynamic invocations to the '+' operator. + /// A compiler intrinsic that implements dynamic invocations to the '+' operator when used in quotations. [] val AdditionDynamic : x:'T1 -> y:'T2 -> 'U - /// A compiler intrinsic that implements dynamic invocations to the checked '+' operator. + /// A compiler intrinsic that implements dynamic invocations to the '-' operator when used in quotations. [] - val CheckedAdditionDynamic : x:'T1 -> y:'T2 -> 'U + val SubtractionDynamic : x:'T1 -> y:'T2 -> 'U - /// A compiler intrinsic that implements dynamic invocations to the '*' operator. + /// A compiler intrinsic that implements dynamic invocations to the '*' operator when used in quotations. [] val MultiplyDynamic : x:'T1 -> y:'T2 -> 'U - /// A compiler intrinsic that implements dynamic invocations to the checked '*' operator. + /// A compiler intrinsic that implements dynamic invocations to the '/' operator when used in quotations. + [] + val DivisionDynamic : x:'T1 -> y:'T2 -> 'U + + /// A compiler intrinsic that implements dynamic invocations to the unary '-' operator when used in quotations. + [] + val UnaryNegationDynamic : value:'T -> 'U + + /// A compiler intrinsic that implements dynamic invocations to the '%' operator when used in quotations. + [] + val ModulusDynamic : x:'T1 -> y:'T2 -> 'U + + /// A compiler intrinsic that implements dynamic invocations to the checked '+' operator when used in quotations. + [] + val CheckedAdditionDynamic : x:'T1 -> y:'T2 -> 'U + + /// A compiler intrinsic that implements dynamic invocations to the checked '-' operator when used in quotations. + [] + val CheckedSubtractionDynamic : x:'T1 -> y:'T2 -> 'U + + /// A compiler intrinsic that implements dynamic invocations to the checked '*' operator when used in quotations. [] val CheckedMultiplyDynamic : x:'T1 -> y:'T2 -> 'U - /// A compiler intrinsic that implements dynamic invocations for the DivideByInt primitive. + /// A compiler intrinsic that implements dynamic invocations to the checked unary '-' operator when used in quotations. + [] + val CheckedUnaryNegationDynamic : value:'T -> 'U + + /// A compiler intrinsic that implements dynamic invocations to the '<<<' operator when used in quotations. + [] + val OpLeftShiftDynamic : value:'T1 -> shift:'T2 -> 'U + + /// A compiler intrinsic that implements dynamic invocations to the '>>>' operator when used in quotations. + [] + val OpRightShiftDynamic : value:'T1 -> shift:'T2 -> 'U + + /// A compiler intrinsic that implements dynamic invocations to the '&&&' operator when used in quotations. + [] + val OpBitwiseAndDynamic : x:'T1 -> y:'T2 -> 'U + + /// A compiler intrinsic that implements dynamic invocations to the '|||' operator when used in quotations. + [] + val OpBitwiseOrDynamic : x:'T1 -> y:'T2 -> 'U + + /// A compiler intrinsic that implements dynamic invocations related to the '^^^' operator when used in quotations. + [] + val OpBitwiseExclusiveOrDynamic : x:'T1 -> y:'T2 -> 'U + + /// A compiler intrinsic that implements dynamic invocations related to the '~~~' operator when used in quotations. + [] + val OpLogicalNotDynamic : value:'T1 -> 'U + + /// A compiler intrinsic that implements dynamic invocations related to conversion operators when used in quotations. + [] + val OpExplicitDynamic : value:'T1 -> 'U + + /// A compiler intrinsic that implements dynamic invocations related to the '<' operator when used in quotations. + [] + val OpLessThanDynamic : x:'T1 -> y:'T2 -> 'U + + /// A compiler intrinsic that implements dynamic invocations related to the '>' operator when used in quotations. + [] + val OpGreaterThanDynamic : x:'T1 -> y:'T2 -> 'U + + /// A compiler intrinsic that implements dynamic invocations related to the '<=' operator when used in quotations. + [] + val OpLessThanOrEqualDynamic : x:'T1 -> y:'T2 -> 'U + + /// A compiler intrinsic that implements dynamic invocations related to the '>=' operator when used in quotations. + [] + val OpGreaterThanOrEqualDynamic : x:'T1 -> y:'T2 -> 'U + + /// A compiler intrinsic that implements dynamic invocations related to the '=' operator when used in quotations. + [] + val OpEqualityDynamic : x:'T1 -> y:'T2 -> 'U + + /// A compiler intrinsic that implements dynamic invocations related to the '=' operator when used in quotations. + [] + val OpInequalityDynamic : x:'T1 -> y:'T2 -> 'U + + /// A compiler intrinsic that implements dynamic invocations for the DivideByInt primitive when used in quotations. [] val DivideByIntDynamic : x:'T -> y:int -> 'T /// Resolves to the zero value for any primitive numeric type or any type with a static member called 'Zero' val inline GenericZero< ^T > : ^T when ^T : (static member Zero : ^T) - /// Resolves to the value 'one' for any primitive numeric type or any type with a static member called 'One' + /// Resolves to the value one for any primitive numeric type or any type with a static member called One val inline GenericOne< ^T > : ^T when ^T : (static member One : ^T) val internal anyToStringShowingNull : 'T -> string @@ -1099,6 +1175,7 @@ namespace Microsoft.FSharp.Core /// The division result. val inline DivideByInt< ^T > : x:^T -> y:int -> ^T when ^T : (static member DivideByInt : ^T * int -> ^T) +(* type BuiltInWitnesses = static member inline op_Addition: x: int32 * y: int32 -> int32 static member inline op_Addition: x: float * y: float -> float @@ -1563,6 +1640,7 @@ namespace Microsoft.FSharp.Core static member inline DivideByInt: x: float * y: int -> float static member inline DivideByInt: x: float32 * y: int -> float32 static member inline DivideByInt: x: decimal * y: int -> decimal +*) /// For compiler use only module (* internal *) ErrorStrings = From fbacb04787649003635be8d71c335110ee4acccc Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 29 Mar 2019 19:21:22 +0000 Subject: [PATCH 39/77] more witness --- src/fsharp/FSharp.Build/FSharp.Build.fsproj | 3 ++- ...Sharp.Compiler.Interactive.Settings.fsproj | 3 ++- .../FSharp.Compiler.Private.fsproj | 3 ++- src/fsharp/Optimizer.fs | 22 +++++++++++++------ src/fsharp/fsc/fsc.fsproj | 3 ++- src/fsharp/fsi/fsi.fsproj | 3 ++- 6 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/fsharp/FSharp.Build/FSharp.Build.fsproj b/src/fsharp/FSharp.Build/FSharp.Build.fsproj index 4bf0eb97289..bb0b498048e 100644 --- a/src/fsharp/FSharp.Build/FSharp.Build.fsproj +++ b/src/fsharp/FSharp.Build/FSharp.Build.fsproj @@ -32,7 +32,8 @@ - + + diff --git a/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj b/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj index 3569093c47f..72fdc53ab88 100644 --- a/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj +++ b/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj @@ -27,7 +27,8 @@ - + + diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj index ce3e578f7ae..9ec5526ffc1 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj @@ -671,7 +671,8 @@ - + + diff --git a/src/fsharp/Optimizer.fs b/src/fsharp/Optimizer.fs index ea36eb2890f..95ef2634084 100644 --- a/src/fsharp/Optimizer.fs +++ b/src/fsharp/Optimizer.fs @@ -136,16 +136,24 @@ type ValInfos(entries) = t.Add (vref.Deref, (vref, x)) t) - // The compiler ValRef's into fslib stored in env.fs break certain invariants that hold elsewhere, + // The compiler ValRef's in TcGLobals.fs break certain invariants that hold elsewhere, // because they dereference to point to Val's from signatures rather than Val's from implementations. // Thus a backup alternative resolution technique is needed for these. let valInfosForFslib = - lazy ( - let dict = Dictionary<_, _>() + LazyWithContext<_, TcGlobals>.Create ((fun g -> + let dict = + Dictionary + (HashIdentity.FromFunctions + (fun (k: ValLinkageFullKey) -> hash k.PartialKey) + (fun k1 k2 -> + k1.PartialKey = k2.PartialKey && + match k1.TypeForLinkage, k2.TypeForLinkage with + | Some ty1, Some ty2 -> typeEquiv g ty1 ty2 + | _ -> false)) for (vref, _x) as p in entries do - let vkey = vref.Deref.GetLinkagePartialKey() + let vkey = vref.Deref.GetLinkageFullKey() dict.Add(vkey, p) |> ignore - dict) + dict), id) member x.Entries = valInfoTable.Force().Values @@ -155,7 +163,7 @@ type ValInfos(entries) = member x.TryFind (v: ValRef) = valInfoTable.Force().TryFind v.Deref - member x.TryFindForFslib (v: ValRef) = valInfosForFslib.Force().TryGetValue(v.Deref.GetLinkagePartialKey()) + member x.TryFindForFslib (g, v: ValRef) = valInfosForFslib.Force(g).TryGetValue(v.Deref.GetLinkageFullKey()) type ModuleInfo = { ValInfos: ValInfos @@ -616,7 +624,7 @@ let GetInfoForNonLocalVal cenv env (vref: ValRef) = //dprintn ("\n\n*** Optimization info for value "+n+" from module "+(full_name_of_nlpath smv)+" not found, module contains values: "+String.concat ", " (NameMap.domainL structInfo.ValInfos)) //System.Diagnostics.Debug.Assert(false, sprintf "Break for module %s, value %s" (full_name_of_nlpath smv) n) if cenv.g.compilingFslib then - match structInfo.ValInfos.TryFindForFslib(vref) with + match structInfo.ValInfos.TryFindForFslib(cenv.g, vref) with | true, ninfo -> snd ninfo | _ -> UnknownValInfo else diff --git a/src/fsharp/fsc/fsc.fsproj b/src/fsharp/fsc/fsc.fsproj index 581b4a11797..e572c4bad2e 100644 --- a/src/fsharp/fsc/fsc.fsproj +++ b/src/fsharp/fsc/fsc.fsproj @@ -30,7 +30,8 @@ - + + diff --git a/src/fsharp/fsi/fsi.fsproj b/src/fsharp/fsi/fsi.fsproj index 77a9274a1e6..f00aa6b4062 100644 --- a/src/fsharp/fsi/fsi.fsproj +++ b/src/fsharp/fsi/fsi.fsproj @@ -27,7 +27,8 @@ - + + From 076ce4d6701daf5fe9d6c4ad4016ca40bcb53a13 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 29 Mar 2019 23:06:35 +0000 Subject: [PATCH 40/77] fix build --- src/fsharp/FSharp.Core/FSharp.Core.fsproj | 2 +- src/fsharp/MethodCalls.fs | 7 ++++-- src/fsharp/Optimizer.fs | 26 ++++++++++++++++------- src/fsharp/TastOps.fs | 14 ++++++------ src/fsharp/TastOps.fsi | 2 +- src/fsharp/fsc.fs | 2 +- src/fsharp/symbols/SymbolHelpers.fs | 4 ++-- 7 files changed, 35 insertions(+), 22 deletions(-) diff --git a/src/fsharp/FSharp.Core/FSharp.Core.fsproj b/src/fsharp/FSharp.Core/FSharp.Core.fsproj index b7f089b3e0c..01efaaa4b1d 100644 --- a/src/fsharp/FSharp.Core/FSharp.Core.fsproj +++ b/src/fsharp/FSharp.Core/FSharp.Core.fsproj @@ -231,7 +231,7 @@ - + diff --git a/src/fsharp/MethodCalls.fs b/src/fsharp/MethodCalls.fs index eb9b7b4c79b..71cdff4a3ac 100644 --- a/src/fsharp/MethodCalls.fs +++ b/src/fsharp/MethodCalls.fs @@ -1422,10 +1422,13 @@ let GenWitnessExpr amap g m (traitInfo: TraitConstraintInfo) argExprs = Some (MakeApplicationAndBetaReduce g (expr, tyOfExpr g expr, [], argExprs, m)) | Choice5Of5 () -> + match traitInfo.Solution with + | None -> None // the trait has been generalized + | Some _-> let rty = match traitInfo.ReturnType with None -> g.unit_ty | Some ty -> ty match traitInfo.MemberName, traitInfo.MemberFlags.IsInstance, traitInfo.ArgumentTypes, argExprs with - | "op_Division", false, [argty1;argty2], [arg1; arg2] -> mkCallDivisionOperator g m argty1 argty2 rty arg1 arg2 |> Some - | "op_Addition", false, [argty1;argty2], [arg1; arg2] -> mkCallAdditionOperator g m argty1 argty2 rty arg1 arg2 |> Some + | "op_Division", false, [argty1;argty2], [arg1; arg2] -> mkCallDivisionOperator g m argty1 argty2 rty arg1 arg2 |> Some + | "op_Addition", false, [argty1;argty2], [arg1; arg2] -> mkCallAdditionOperator g m argty1 argty2 rty arg1 arg2 |> Some (* | "op_Multiply", [argty1;argty2], [arg1; arg2] | "op_Subtraction", [argty1;argty2], [arg1; arg2] diff --git a/src/fsharp/Optimizer.fs b/src/fsharp/Optimizer.fs index 95ef2634084..f19a1a7ea5f 100644 --- a/src/fsharp/Optimizer.fs +++ b/src/fsharp/Optimizer.fs @@ -136,22 +136,31 @@ type ValInfos(entries) = t.Add (vref.Deref, (vref, x)) t) - // The compiler ValRef's in TcGLobals.fs break certain invariants that hold elsewhere, + // The compiler's ValRef's in TcGlobals.fs that refer to things in FSharp.Core break certain invariants that hold elsewhere, // because they dereference to point to Val's from signatures rather than Val's from implementations. - // Thus a backup alternative resolution technique is needed for these. + // Thus a backup alternative resolution technique is needed for these when processing the FSharp.Core implementation files + // holding these items. This resolution must be able to distinguish between overloaded methods, so we use + // XmlDocSigOfVal as a cheap hack to get a unique item of data for a value. let valInfosForFslib = LazyWithContext<_, TcGlobals>.Create ((fun g -> let dict = - Dictionary + Dictionary<(ValRef * ValLinkageFullKey), (ValRef * ValInfo)> (HashIdentity.FromFunctions - (fun (k: ValLinkageFullKey) -> hash k.PartialKey) - (fun k1 k2 -> + (fun (_: ValRef, k: ValLinkageFullKey) -> hash k.PartialKey) + (fun (v1, k1) (v2, k2) -> k1.PartialKey = k2.PartialKey && + // dismbiguate overloads, somewhat low-perf but only use for a handful of overloads in FSharp.Core match k1.TypeForLinkage, k2.TypeForLinkage with - | Some ty1, Some ty2 -> typeEquiv g ty1 ty2 + | Some _, Some _ -> + let sig1 = XmlDocSigOfVal g true "" v1.Deref + let sig2 = XmlDocSigOfVal g true "" v2.Deref + (sig1 = sig2) + | None, None -> true | _ -> false)) for (vref, _x) as p in entries do - let vkey = vref.Deref.GetLinkageFullKey() + let vkey = (vref, vref.Deref.GetLinkageFullKey()) + if dict.ContainsKey vkey then + failwithf "dictionary already contains key %A" vkey dict.Add(vkey, p) |> ignore dict), id) @@ -163,7 +172,8 @@ type ValInfos(entries) = member x.TryFind (v: ValRef) = valInfoTable.Force().TryFind v.Deref - member x.TryFindForFslib (g, v: ValRef) = valInfosForFslib.Force(g).TryGetValue(v.Deref.GetLinkageFullKey()) + member x.TryFindForFslib (g, vref: ValRef) = + valInfosForFslib.Force(g).TryGetValue((vref, vref.Deref.GetLinkageFullKey())) type ModuleInfo = { ValInfos: ValInfos diff --git a/src/fsharp/TastOps.fs b/src/fsharp/TastOps.fs index ddbc57a4136..9d4e52b6c99 100644 --- a/src/fsharp/TastOps.fs +++ b/src/fsharp/TastOps.fs @@ -7766,8 +7766,8 @@ let buildAccessPath (cp: CompilationPath option) = | None -> "Extension Type" let prependPath path name = if path = "" then name else path + "." + name -let XmlDocSigOfVal g path (v: Val) = - let parentTypars, methTypars, cxs, argInfos, prefix, path, name = +let XmlDocSigOfVal g full path (v: Val) = + let parentTypars, methTypars, cxs, argInfos, rty, prefix, path, name = // CLEANUP: this is one of several code paths that treat module values and members // separately when really it would be cleaner to make sure GetTopValTypeInFSharpForm, GetMemberTypeInFSharpForm etc. @@ -7776,7 +7776,7 @@ let XmlDocSigOfVal g path (v: Val) = match v.MemberInfo with | Some membInfo when not v.IsExtensionMember -> // Methods, Properties etc. - let tps, cxs, argInfos, _, _ = GetMemberTypeInMemberForm g membInfo.MemberFlags (Option.get v.ValReprInfo) v.Type v.Range + let tps, cxs, argInfos, rty, _ = GetMemberTypeInMemberForm g membInfo.MemberFlags (Option.get v.ValReprInfo) v.Type v.Range let prefix, name = match membInfo.MemberFlags.MemberKind with | MemberKind.ClassConstructor @@ -7790,20 +7790,20 @@ let XmlDocSigOfVal g path (v: Val) = match PartitionValTypars g v with | Some(_, memberParentTypars, memberMethodTypars, _, _) -> memberParentTypars, memberMethodTypars | None -> [], tps - parentTypars, methTypars, cxs, argInfos, prefix, path, name + parentTypars, methTypars, cxs, argInfos, rty, prefix, path, name | _ -> // Regular F# values and extension members let w = arityOfVal v - let tps, cxs, argInfos, _, _ = GetTopValTypeInCompiledForm g w v.Type v.Range + let tps, cxs, argInfos, rty, _ = GetTopValTypeInCompiledForm g w v.Type v.Range let name = v.CompiledName let prefix = if w.NumCurriedArgs = 0 && isNil tps then "P:" else "M:" - [], tps, cxs, argInfos, prefix, path, name + [], tps, cxs, argInfos, rty, prefix, path, name let witnessArgTys = GenWitnessTys g cxs let argTys = argInfos |> List.concat |> List.map fst - let argTys = witnessArgTys @ argTys + let argTys = witnessArgTys @ argTys @ (match rty with Some t when full -> [t] | _ -> []) let args = XmlDocArgsEnc g (parentTypars, methTypars) argTys let arity = List.length methTypars in (* C# XML doc adds `` to *generic* member names *) let genArity = if arity=0 then "" else sprintf "``%d" arity diff --git a/src/fsharp/TastOps.fsi b/src/fsharp/TastOps.fsi index e37ba7e35ae..dd7fb879d0b 100755 --- a/src/fsharp/TastOps.fsi +++ b/src/fsharp/TastOps.fsi @@ -2130,7 +2130,7 @@ val buildAccessPath : CompilationPath option -> string val XmlDocArgsEnc : TcGlobals -> Typars * Typars -> TType list -> string -val XmlDocSigOfVal : TcGlobals -> string -> Val -> string +val XmlDocSigOfVal : TcGlobals -> full: bool -> string -> Val -> string val XmlDocSigOfUnionCase : (string list -> string) diff --git a/src/fsharp/fsc.fs b/src/fsharp/fsc.fs index 30436d31578..eb4be62a15e 100644 --- a/src/fsharp/fsc.fs +++ b/src/fsharp/fsc.fs @@ -335,7 +335,7 @@ module XmlDocWriter = let computeXmlDocSigs (tcGlobals, generatedCcu: CcuThunk) = (* the xmlDocSigOf* functions encode type into string to be used in "id" *) let g = tcGlobals - let doValSig ptext (v: Val) = if (hasDoc v.XmlDoc) then v.XmlDocSig <- XmlDocSigOfVal g ptext v + let doValSig ptext (v: Val) = if hasDoc v.XmlDoc then v.XmlDocSig <- XmlDocSigOfVal g false ptext v let doTyconSig ptext (tc: Tycon) = if (hasDoc tc.XmlDoc) then tc.XmlDocSig <- XmlDocSigOfTycon [ptext; tc.CompiledName] for vref in tc.MembersOfFSharpTyconSorted do diff --git a/src/fsharp/symbols/SymbolHelpers.fs b/src/fsharp/symbols/SymbolHelpers.fs index 943337a7da6..94b49eaf951 100644 --- a/src/fsharp/symbols/SymbolHelpers.fs +++ b/src/fsharp/symbols/SymbolHelpers.fs @@ -510,7 +510,7 @@ module internal SymbolHelpers = ap + sep + vref.TopValDeclaringEntity.CompiledName else ap - v.XmlDocSig <- XmlDocSigOfVal g path v + v.XmlDocSig <- XmlDocSigOfVal g false path v Some (ccuFileName, v.XmlDocSig) let GetXmlDocSigOfRecdFieldInfo (rfinfo: RecdFieldInfo) = @@ -563,7 +563,7 @@ module internal SymbolHelpers = let ccuFileName = vref.nlr.Ccu.FileName let v = vref.Deref if v.XmlDocSig = "" && v.HasDeclaringEntity then - v.XmlDocSig <- XmlDocSigOfVal g vref.TopValDeclaringEntity.CompiledRepresentationForNamedType.Name v + v.XmlDocSig <- XmlDocSigOfVal g false vref.TopValDeclaringEntity.CompiledRepresentationForNamedType.Name v Some (ccuFileName, v.XmlDocSig) else None From f4bd2211d871ce82c4ea3a6355f63d6a14da4aa8 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 29 Mar 2019 23:55:45 +0000 Subject: [PATCH 41/77] use proto on mac and linux --- .vsts-pr.yaml | 6 ++--- FSharpBuild.Directory.Build.props | 4 +-- FSharpTests.Directory.Build.props | 4 +++ eng/Build.ps1 | 2 +- eng/build-utils.ps1 | 4 --- eng/build.sh | 43 ++++++++++++++++++++++++------- fcs/Directory.Build.props | 6 +---- fcs/build.fsx | 10 ++++--- proto.proj | 2 +- src/buildtools/buildtools.proj | 13 +++++----- 10 files changed, 59 insertions(+), 35 deletions(-) diff --git a/.vsts-pr.yaml b/.vsts-pr.yaml index b7d3862888d..b0186db4e1e 100644 --- a/.vsts-pr.yaml +++ b/.vsts-pr.yaml @@ -11,7 +11,7 @@ jobs: _configuration: Release _testKind: testcoreclr steps: - - script: ./eng/cibuild.sh --configuration $(_configuration) --$(_testKind) + - script: ./eng/cibuild.sh --configuration $(_configuration) --$(_testKind) --verbosity normal - task: PublishBuildArtifacts@1 displayName: Publish Build Logs inputs: @@ -55,7 +55,7 @@ jobs: _configuration: Release _testKind: testcoreclr steps: - - script: ./eng/cibuild.sh --configuration $(_configuration) --$(_testKind) + - script: ./eng/cibuild.sh --configuration $(_configuration) --$(_testKind) --verbosity normal - task: PublishBuildArtifacts@1 displayName: Publish Build Logs inputs: @@ -108,7 +108,7 @@ jobs: _configuration: Release _testKind: testVs steps: - - script: eng\CIBuild.cmd -configuration $(_configuration) -$(_testKind) + - script: eng\CIBuild.cmd -configuration $(_configuration) -$(_testKind) -verbosity normal - task: PublishBuildArtifacts@1 displayName: Publish Build Logs inputs: diff --git a/FSharpBuild.Directory.Build.props b/FSharpBuild.Directory.Build.props index 31d24301299..9d1161037b8 100644 --- a/FSharpBuild.Directory.Build.props +++ b/FSharpBuild.Directory.Build.props @@ -12,7 +12,7 @@ $(RepoRoot)src $(ArtifactsDir)\SymStore $(ArtifactsDir)\Bootstrap - $(ArtifactsDir)/fsc/Proto/netcoreapp2.1 + $(ArtifactsDir)/bin/fsc/Proto/netcoreapp2.1 4.4.0 1182;0025;$(WarningsAsErrors) @@ -80,7 +80,7 @@ - + $(ProtoOutputPath)\Microsoft.FSharp.Targets $(ProtoOutputPath)\Microsoft.FSharp.NetSdk.props $(ProtoOutputPath)\Microsoft.FSharp.NetSdk.targets diff --git a/FSharpTests.Directory.Build.props b/FSharpTests.Directory.Build.props index 6c298fe4426..d62503cea93 100644 --- a/FSharpTests.Directory.Build.props +++ b/FSharpTests.Directory.Build.props @@ -35,6 +35,10 @@ <_FSharpBuildTargetFramework Condition="'$(FSharpTestCompilerVersion)' == 'net40'">net46 <_FSharpBuildTargetFramework Condition="'$(FSharpTestCompilerVersion)' == 'coreclr'">netstandard2.0 <_FSharpBuildBinPath>$(MSBuildThisFileDirectory)artifacts\bin\FSharp.Build\$(Configuration)\$(_FSharpBuildTargetFramework) + $(_FSharpBuildBinPath)\FSharp.Build.dll diff --git a/eng/Build.ps1 b/eng/Build.ps1 index 865cf231575..e93d735e44b 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -155,10 +155,10 @@ function BuildSolution() { /p:Publish=$publish ` /p:ContinuousIntegrationBuild=$ci ` /p:OfficialBuildId=$officialBuildId ` - /p:BootstrapBuildPath=$bootstrapDir ` /p:QuietRestore=$quietRestore ` /p:QuietRestoreBinaryLog=$binaryLog ` /p:TestTargetFrameworks=$testTargetFrameworks ` + /v:$verbosity ` $suppressExtensionDeployment ` @properties } diff --git a/eng/build-utils.ps1 b/eng/build-utils.ps1 index 304eac5a3e5..26b0c0ad8ab 100644 --- a/eng/build-utils.ps1 +++ b/eng/build-utils.ps1 @@ -216,10 +216,6 @@ function Run-MSBuild([string]$projectFilePath, [string]$buildArgs = "", [string] $args += " /p:ContinuousIntegrationBuild=true" } - if ($bootstrapDir -ne "") { - $args += " /p:BootstrapBuildPath=$bootstrapDir" - } - $args += " $buildArgs" $args += " $projectFilePath" $args += " $properties" diff --git a/eng/build.sh b/eng/build.sh index d814dcd04d4..43803435b56 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -13,6 +13,7 @@ usage() echo " --binaryLog Create MSBuild binary log (short: -bl)" echo "" echo "Actions:" + echo " --bootstrap Force the build of the bootstrap compiler" echo " --restore Restore projects required to build (short: -r)" echo " --build Build all projects (short: -b)" echo " --rebuild Rebuild all projects" @@ -44,7 +45,7 @@ while [[ -h "$source" ]]; do done scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" -restore=false +restore=true build=false rebuild=false pack=false @@ -54,6 +55,7 @@ test_core_clr=false configuration="Debug" verbosity='minimal' binary_log=false +force_bootstrap=false ci=false skip_analyzers=false prepare_machine=false @@ -88,6 +90,9 @@ while [[ $# > 0 ]]; do --binarylog|-bl) binary_log=true ;; + --bootstrap) + force_bootstrap=true + ;; --restore|-r) restore=true ;; @@ -204,22 +209,42 @@ function BuildSolution { if [[ "$ci" != true ]]; then quiet_restore=true fi + fslexyacc_target_framework=netcoreapp2.0 + + # Node reuse fails because multiple different versions of FSharp.Build.dll get loaded into MSBuild nodes + node_reuse=false # build bootstrap tools bootstrap_config=Proto - MSBuild "$repo_root/src/buildtools/buildtools.proj" \ - /restore \ - /p:Configuration=$bootstrap_config \ - /t:Build - bootstrap_dir=$artifacts_dir/Bootstrap - mkdir -p "$bootstrap_dir" - cp $artifacts_dir/bin/fslex/$bootstrap_config/netcoreapp2.0/* $bootstrap_dir - cp $artifacts_dir/bin/fsyacc/$bootstrap_config/netcoreapp2.0/* $bootstrap_dir + if [[ "$force_bootstrap" == true ]]; then + rm -fr $bootstrap_dir + fi + if [ ! -f "$bootstrap_dir/fslex.dll" ]; then + MSBuild "$repo_root/src/buildtools/buildtools.proj" \ + /restore \ + /v:$verbosity \ + /p:Configuration=$bootstrap_config \ + /t:Build + + mkdir -p "$bootstrap_dir" + cp $artifacts_dir/bin/fslex/$bootstrap_config/$fslexyacc_target_framework/* $bootstrap_dir + cp $artifacts_dir/bin/fsyacc/$bootstrap_config/$fslexyacc_target_framework/* $bootstrap_dir + fi + if [ ! -f "$bootstrap_dir/fsc.exe" ]; then + MSBuild "$repo_root/proto.proj" \ + /restore \ + /v:$verbosity \ + /p:Configuration=$bootstrap_config \ + /t:Build + + cp $artifacts_dir/bin/fsc/$bootstrap_config/netcoreapp2.1/* $bootstrap_dir + fi # do real build MSBuild $toolset_build_proj \ $bl \ + /v:$verbosity \ /p:Configuration=$configuration \ /p:Projects="$projects" \ /p:RepoRoot="$repo_root" \ diff --git a/fcs/Directory.Build.props b/fcs/Directory.Build.props index 3179fe221f9..e09dc41a671 100644 --- a/fcs/Directory.Build.props +++ b/fcs/Directory.Build.props @@ -17,11 +17,7 @@ $(ArtifactsDir)\obj $(ArtifactsBinDir)\fcs $(ArtifactsObjDir)\fcs - true + true - - - $(ArtifactsBinDir)\FSharp.Build\Proto\net46 - diff --git a/fcs/build.fsx b/fcs/build.fsx index d1d575c4f76..d03f9664fe5 100644 --- a/fcs/build.fsx +++ b/fcs/build.fsx @@ -24,6 +24,8 @@ let isMono = false // Utilities // -------------------------------------------------------------------------------------- +let fslexyaccTargetFramework = "netcoreapp2.0" + let dotnetExePath = // Build.cmd normally downloads a dotnet cli to: \artifacts\toolset\dotnet // check if there is one there to avoid downloading an additional one here @@ -92,14 +94,14 @@ Target "BuildVersion" (fun _ -> Target "Build" (fun _ -> runDotnet __SOURCE_DIRECTORY__ "build ../src/buildtools/buildtools.proj -v n -c Proto" - let fslexPath = __SOURCE_DIRECTORY__ + "/../artifacts/bin/fslex/Proto/netcoreapp2.0/fslex.dll" - let fsyaccPath = __SOURCE_DIRECTORY__ + "/../artifacts/bin/fsyacc/Proto/netcoreapp2.0/fsyacc.dll" + let fslexPath = __SOURCE_DIRECTORY__ + "/../artifacts/bin/fslex/Proto/" + fslexyaccTargetFramework + "/fslex.dll" + let fsyaccPath = __SOURCE_DIRECTORY__ + "/../artifacts/bin/fsyacc/Proto/" + fslexyaccTargetFramework + "/fsyacc.dll" runDotnet __SOURCE_DIRECTORY__ (sprintf "build FSharp.Compiler.Service.sln -v n -c Release /p:FsLexPath=%s /p:FsYaccPath=%s" fslexPath fsyaccPath) ) Target "Test" (fun _ -> - // This project file is used for the netcoreapp2.0 tests to work out reference sets - runDotnet __SOURCE_DIRECTORY__ "build ../tests/projects/Sample_NETCoreSDK_FSharp_Library_netstandard2_0/Sample_NETCoreSDK_FSharp_Library_netstandard2_0.fsproj -v n /restore /p:DisableCompilerRedirection=true" + // This project file is used for the tests to work out reference sets + runDotnet __SOURCE_DIRECTORY__ "build ../tests/projects/Sample_NETCoreSDK_FSharp_Library_netstandard2_0/Sample_NETCoreSDK_FSharp_Library_netstandard2_0.fsproj -v n /restore /p:DisableProtoCompiler=true" // Now run the tests let logFilePath = Path.Combine(__SOURCE_DIRECTORY__, "..", "artifacts", "TestResults", "Release", "FSharp.Compiler.Service.Test.xml") diff --git a/proto.proj b/proto.proj index bbad2c34cc5..b0bff16a289 100644 --- a/proto.proj +++ b/proto.proj @@ -8,7 +8,7 @@ TargetFramework=net46 - TargetFramework=netcoreapp2.1 + TargetFramework=netstandard2.0 TargetFramework=net46 diff --git a/src/buildtools/buildtools.proj b/src/buildtools/buildtools.proj index 593f086dd07..d96cf6a8d8c 100644 --- a/src/buildtools/buildtools.proj +++ b/src/buildtools/buildtools.proj @@ -2,7 +2,8 @@ Debug - + true + @@ -10,23 +11,23 @@ - + - + - + - + - + From 8a4baf313be5834a729b26c843bdcac647e3e100 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Sat, 30 Mar 2019 12:21:44 +0000 Subject: [PATCH 42/77] reduce diff --- FSharpBuild.Directory.Build.props | 2 +- fcs/Directory.Build.props | 2 +- fcs/build.fsx | 2 +- src/buildtools/buildtools.proj | 12 ++++++------ 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/FSharpBuild.Directory.Build.props b/FSharpBuild.Directory.Build.props index 9d1161037b8..93b66901c80 100644 --- a/FSharpBuild.Directory.Build.props +++ b/FSharpBuild.Directory.Build.props @@ -80,7 +80,7 @@ - + $(ProtoOutputPath)\Microsoft.FSharp.Targets $(ProtoOutputPath)\Microsoft.FSharp.NetSdk.props $(ProtoOutputPath)\Microsoft.FSharp.NetSdk.targets diff --git a/fcs/Directory.Build.props b/fcs/Directory.Build.props index e09dc41a671..99ac310b2a3 100644 --- a/fcs/Directory.Build.props +++ b/fcs/Directory.Build.props @@ -17,7 +17,7 @@ $(ArtifactsDir)\obj $(ArtifactsBinDir)\fcs $(ArtifactsObjDir)\fcs - true + true diff --git a/fcs/build.fsx b/fcs/build.fsx index d03f9664fe5..39fb3070e74 100644 --- a/fcs/build.fsx +++ b/fcs/build.fsx @@ -101,7 +101,7 @@ Target "Build" (fun _ -> Target "Test" (fun _ -> // This project file is used for the tests to work out reference sets - runDotnet __SOURCE_DIRECTORY__ "build ../tests/projects/Sample_NETCoreSDK_FSharp_Library_netstandard2_0/Sample_NETCoreSDK_FSharp_Library_netstandard2_0.fsproj -v n /restore /p:DisableProtoCompiler=true" + runDotnet __SOURCE_DIRECTORY__ "build ../tests/projects/Sample_NETCoreSDK_FSharp_Library_netstandard2_0/Sample_NETCoreSDK_FSharp_Library_netstandard2_0.fsproj -v n /restore /p:DisableCompilerRedirection=true" // Now run the tests let logFilePath = Path.Combine(__SOURCE_DIRECTORY__, "..", "artifacts", "TestResults", "Release", "FSharp.Compiler.Service.Test.xml") diff --git a/src/buildtools/buildtools.proj b/src/buildtools/buildtools.proj index d96cf6a8d8c..630bb678561 100644 --- a/src/buildtools/buildtools.proj +++ b/src/buildtools/buildtools.proj @@ -2,7 +2,7 @@ Debug - true + true @@ -11,23 +11,23 @@ - + - + - + - + - + From 0474a23faf73ef71fc4ddb2313613dc480d9a3e0 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Sat, 30 Mar 2019 12:24:30 +0000 Subject: [PATCH 43/77] reduce diff --- fcs/Directory.Build.props | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fcs/Directory.Build.props b/fcs/Directory.Build.props index 99ac310b2a3..3179fe221f9 100644 --- a/fcs/Directory.Build.props +++ b/fcs/Directory.Build.props @@ -20,4 +20,8 @@ true + + + $(ArtifactsBinDir)\FSharp.Build\Proto\net46 + From b96120e417c7131ac93fb46305a6770f5d5d2d75 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Sat, 30 Mar 2019 12:25:25 +0000 Subject: [PATCH 44/77] reduce diff --- fcs/build.fsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/fcs/build.fsx b/fcs/build.fsx index 39fb3070e74..dd5d3c64fc1 100644 --- a/fcs/build.fsx +++ b/fcs/build.fsx @@ -24,8 +24,6 @@ let isMono = false // Utilities // -------------------------------------------------------------------------------------- -let fslexyaccTargetFramework = "netcoreapp2.0" - let dotnetExePath = // Build.cmd normally downloads a dotnet cli to: \artifacts\toolset\dotnet // check if there is one there to avoid downloading an additional one here @@ -94,8 +92,8 @@ Target "BuildVersion" (fun _ -> Target "Build" (fun _ -> runDotnet __SOURCE_DIRECTORY__ "build ../src/buildtools/buildtools.proj -v n -c Proto" - let fslexPath = __SOURCE_DIRECTORY__ + "/../artifacts/bin/fslex/Proto/" + fslexyaccTargetFramework + "/fslex.dll" - let fsyaccPath = __SOURCE_DIRECTORY__ + "/../artifacts/bin/fsyacc/Proto/" + fslexyaccTargetFramework + "/fsyacc.dll" + let fslexPath = __SOURCE_DIRECTORY__ + "/../artifacts/bin/fslex/Proto/netcoreapp2.0/fslex.dll" + let fsyaccPath = __SOURCE_DIRECTORY__ + "/../artifacts/bin/fsyacc/Proto/netcoreapp2.0/fsyacc.dll" runDotnet __SOURCE_DIRECTORY__ (sprintf "build FSharp.Compiler.Service.sln -v n -c Release /p:FsLexPath=%s /p:FsYaccPath=%s" fslexPath fsyaccPath) ) From cf9147bd2dd42febdea9e37082ff46fa34f0ed64 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Sat, 30 Mar 2019 12:26:18 +0000 Subject: [PATCH 45/77] reduce diff --- FSharpTests.Directory.Build.props | 4 ---- 1 file changed, 4 deletions(-) diff --git a/FSharpTests.Directory.Build.props b/FSharpTests.Directory.Build.props index d62503cea93..6c298fe4426 100644 --- a/FSharpTests.Directory.Build.props +++ b/FSharpTests.Directory.Build.props @@ -35,10 +35,6 @@ <_FSharpBuildTargetFramework Condition="'$(FSharpTestCompilerVersion)' == 'net40'">net46 <_FSharpBuildTargetFramework Condition="'$(FSharpTestCompilerVersion)' == 'coreclr'">netstandard2.0 <_FSharpBuildBinPath>$(MSBuildThisFileDirectory)artifacts\bin\FSharp.Build\$(Configuration)\$(_FSharpBuildTargetFramework) - $(_FSharpBuildBinPath)\FSharp.Build.dll From 286c336d7b0fe6e783edd42c2d02ac99cae083d9 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Sat, 30 Mar 2019 12:26:48 +0000 Subject: [PATCH 46/77] reduce diff --- fcs/build.fsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fcs/build.fsx b/fcs/build.fsx index dd5d3c64fc1..d1d575c4f76 100644 --- a/fcs/build.fsx +++ b/fcs/build.fsx @@ -98,7 +98,7 @@ Target "Build" (fun _ -> ) Target "Test" (fun _ -> - // This project file is used for the tests to work out reference sets + // This project file is used for the netcoreapp2.0 tests to work out reference sets runDotnet __SOURCE_DIRECTORY__ "build ../tests/projects/Sample_NETCoreSDK_FSharp_Library_netstandard2_0/Sample_NETCoreSDK_FSharp_Library_netstandard2_0.fsproj -v n /restore /p:DisableCompilerRedirection=true" // Now run the tests From 7a6448eda01bfe982c942b707c1110ac4a767d20 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Sat, 30 Mar 2019 13:00:00 +0000 Subject: [PATCH 47/77] reduce diff --- FSharpBuild.Directory.Build.props | 2 +- eng/Build.ps1 | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/FSharpBuild.Directory.Build.props b/FSharpBuild.Directory.Build.props index 93b66901c80..1d456ec2d72 100644 --- a/FSharpBuild.Directory.Build.props +++ b/FSharpBuild.Directory.Build.props @@ -80,7 +80,7 @@ - + $(ProtoOutputPath)\Microsoft.FSharp.Targets $(ProtoOutputPath)\Microsoft.FSharp.NetSdk.props $(ProtoOutputPath)\Microsoft.FSharp.NetSdk.targets diff --git a/eng/Build.ps1 b/eng/Build.ps1 index e93d735e44b..0acdb67cdb7 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -99,6 +99,7 @@ function Process-Arguments() { Print-Usage exit 0 } + $script:nodeReuse = $False; if ($testAll) { $script:testDesktop = $True From 56892449df9db3e1d885d352d6fda0b197f3856b Mon Sep 17 00:00:00 2001 From: Don Syme Date: Mon, 1 Apr 2019 15:23:54 +0100 Subject: [PATCH 48/77] fix recursive generation of witnesses --- eng/build-utils.ps1 | 2 +- scripts/AssemblyVersionCheck.fsx | 1 - src/fsharp/ExtensionTyping.fs | 4 +- src/fsharp/FSharp.Build/FSharp.Build.fsproj | 1 + ...Sharp.Compiler.Interactive.Settings.fsproj | 1 + .../FSharp.Compiler.Private.fsproj | 1 + .../FSharp.Compiler.Server.Shared.fsproj | 4 +- src/fsharp/FSharp.Core/quotations.fs | 45 ++++++++++++++----- src/fsharp/MethodCalls.fs | 2 +- src/fsharp/QuotationTranslator.fs | 42 ++++++++++------- src/fsharp/fsc/fsc.fsproj | 4 ++ src/fsharp/fsi/fsi.fsproj | 4 ++ src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj | 7 ++- .../ProductVersion.fs | 30 ++++++------- tests/fsharp/single-test.fs | 4 +- 15 files changed, 101 insertions(+), 51 deletions(-) diff --git a/eng/build-utils.ps1 b/eng/build-utils.ps1 index 26b0c0ad8ab..e17376ce2a7 100644 --- a/eng/build-utils.ps1 +++ b/eng/build-utils.ps1 @@ -245,7 +245,7 @@ function Make-BootstrapBuild() { $projectPath = "$RepoRoot\proto.proj" Run-MSBuild $projectPath "/restore /t:Build" -logFileName "Bootstrap" -configuration $bootstrapConfiguration Copy-Item "$ArtifactsDir\bin\fsc\$bootstrapConfiguration\$bootstrapTfm\*" -Destination $dir - Copy-Item "$ArtifactsDir\bin\fsi\$bootstrapConfiguration\$bootstrapTfm\*" -Destination $dir + Copy-Item "$ArtifactsDir\bin\fsi\$bootstrapConfiguration\$bootstrapTfm\*" -Destination $dir -force return $dir } diff --git a/scripts/AssemblyVersionCheck.fsx b/scripts/AssemblyVersionCheck.fsx index 4c547d19cae..0f3816a2e6c 100644 --- a/scripts/AssemblyVersionCheck.fsx +++ b/scripts/AssemblyVersionCheck.fsx @@ -26,7 +26,6 @@ module AssemblyVersionCheck = |> List.map (fun p -> Directory.EnumerateFiles(binariesPath, p, SearchOption.AllDirectories)) |> Seq.concat |> List.ofSeq - |> List.filter (fun p -> not (p.Contains("Proto"))) |> List.filter (fun p -> (Set.contains (Path.GetFileName(p)) excludedAssemblies) |> not) // verify that all assemblies have a version number other than 0.0.0.0 or 1.0.0.0 diff --git a/src/fsharp/ExtensionTyping.fs b/src/fsharp/ExtensionTyping.fs index 97c4feddbc4..9bf54e3be79 100755 --- a/src/fsharp/ExtensionTyping.fs +++ b/src/fsharp/ExtensionTyping.fs @@ -45,9 +45,9 @@ module internal ExtensionTyping = // Detect the host tooling context let toolingCompatibleVersions() = if typeof.Assembly.GetName().Name = "mscorlib" then - [ "net471"; "net47"; "net462"; "net461"; "net452"; "net451"; "net45"; "netstandard2.0"] + [ "net461"; "net452"; "net451"; "net45"; "netstandard2.0"] elif typeof.Assembly.GetName().Name = "System.Private.CoreLib" then - [ "netcoreapp2.1"; "netcoreapp2.0"; "netstandard2.0"] + [ "netcoreapp2.0"; "netstandard2.0"] else System.Diagnostics.Debug.Assert(false, "Couldn't determine runtime tooling context, assuming it supports at least .NET Standard 2.0") [ "netstandard2.0"] diff --git a/src/fsharp/FSharp.Build/FSharp.Build.fsproj b/src/fsharp/FSharp.Build/FSharp.Build.fsproj index 5e44dc6d3ca..2f03cb6ec59 100644 --- a/src/fsharp/FSharp.Build/FSharp.Build.fsproj +++ b/src/fsharp/FSharp.Build/FSharp.Build.fsproj @@ -32,6 +32,7 @@ + diff --git a/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj b/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj index 9066ea64a79..e192e71d207 100644 --- a/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj +++ b/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj @@ -27,6 +27,7 @@ + diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj index a0c4341b834..24fc68c62f0 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj @@ -663,6 +663,7 @@ + diff --git a/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj b/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj index fd1a2470534..4bcc1113845 100644 --- a/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj +++ b/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj @@ -18,8 +18,10 @@ + - + + diff --git a/src/fsharp/FSharp.Core/quotations.fs b/src/fsharp/FSharp.Core/quotations.fs index 4197b38488d..de9005c30b9 100644 --- a/src/fsharp/FSharp.Core/quotations.fs +++ b/src/fsharp/FSharp.Core/quotations.fs @@ -175,7 +175,9 @@ and | NewObjectOp of ConstructorInfo | InstanceMethodCallOp of MethodInfo | StaticMethodCallOp of MethodInfo + /// A new Call node type in F# 5.0, storing extra information about witnesses | InstanceMethodCallWOp of MethodInfo * MethodInfo * int + /// A new Call node type in F# 5.0, storing extra information about witnesses | StaticMethodCallWOp of MethodInfo * MethodInfo * int | CoerceOp of Type | NewArrayOp of Type @@ -264,9 +266,17 @@ and [] | CombTerm(ValueOp(v,_,None),[]) -> combL "Value" [objL v] | CombTerm(WithValueOp(v,_),[defn]) -> combL "WithValue" [objL v; expr defn] | CombTerm(InstanceMethodCallOp(minfo),obj::args) -> combL "Call" [someL obj; minfoL minfo; listL (exprs args)] - | CombTerm(StaticMethodCallOp(minfo),args) -> combL "Call" [noneL; minfoL minfo; listL (exprs args)] - | CombTerm(InstanceMethodCallWOp(minfo, _minfoW, nWitnesses),obj::args) -> combL "Call" [someL obj; minfoL minfo; listL (exprs (List.skip nWitnesses args))] - | CombTerm(StaticMethodCallWOp(minfo, _minfoW, nWitnesses),args) -> combL "Call" [noneL; minfoL minfo; listL (exprs (List.skip nWitnesses args))] + | CombTerm(StaticMethodCallOp(minfo),args) -> combL "Call" [noneL; minfoL minfo; listL (exprs args)] + + | CombTerm(InstanceMethodCallWOp(minfo, _minfoW, nWitnesses),args) -> + let argsWithoutWitnesses = List.skip nWitnesses args + match argsWithoutWitnesses with + | objArg :: argsWithoutObj -> combL "Call" [someL objArg; minfoL minfo; listL (exprs argsWithoutObj)] + | _ -> failwithf "Unexpected term in layout %A" x.Tree + + | CombTerm(StaticMethodCallWOp(minfo, _minfoW, nWitnesses),args) -> + combL "Call" [noneL; minfoL minfo; listL (exprs (List.skip nWitnesses args))] + | CombTerm(InstancePropGetOp(pinfo),(obj::args)) -> combL "PropertyGet" [someL obj; pinfoL pinfo; listL (exprs args)] | CombTerm(StaticPropGetOp(pinfo),args) -> combL "PropertyGet" [noneL; pinfoL pinfo; listL (exprs args)] | CombTerm(InstancePropSetOp(pinfo),(obj::args)) -> combL "PropertySet" [someL obj; pinfoL pinfo; listL (exprs args)] @@ -523,8 +533,16 @@ module Patterns = match input with | E(CombTerm(StaticMethodCallOp minfo,args)) -> Some(None,minfo,args) | E(CombTerm(InstanceMethodCallOp minfo,(obj::args))) -> Some(Some(obj),minfo,args) - | E(CombTerm(StaticMethodCallWOp (minfo, _minfoW, nWitnesses),args)) -> Some(None,minfo,List.skip nWitnesses args) - | E(CombTerm(InstanceMethodCallWOp (minfo, _minfoW, nWitnesses),(obj::args))) -> Some(Some(obj),minfo,List.skip nWitnesses args) + + | E(CombTerm(StaticMethodCallWOp (minfo, _minfoW, nWitnesses), args)) -> + Some(None,minfo,List.skip nWitnesses args) + + | E(CombTerm(InstanceMethodCallWOp (minfo, _minfoW, nWitnesses), args)) -> + let argsWithoutWitnesses = List.skip nWitnesses args + match argsWithoutWitnesses with + | obj :: argsWithoutObj -> Some (Some obj, minfo, argsWithoutObj) + | _ -> None + | _ -> None [] @@ -533,7 +551,14 @@ module Patterns = | E(CombTerm(StaticMethodCallOp minfo,args)) -> Some(None,minfo,minfo,[],args) | E(CombTerm(InstanceMethodCallOp minfo,(obj::args))) -> Some(Some(obj),minfo,minfo,[],args) | E(CombTerm(StaticMethodCallWOp (minfo, minfoW, nWitnesses),args)) -> Some(None,minfo,minfoW,List.take nWitnesses args, List.skip nWitnesses args) - | E(CombTerm(InstanceMethodCallWOp (minfo, minfoW, nWitnesses),(obj::args))) -> Some(Some(obj),minfo,minfoW,List.take nWitnesses args, List.skip nWitnesses args) + | E(CombTerm(InstanceMethodCallWOp (minfo, minfoW, nWitnesses), args)) -> + if args.Length >= nWitnesses then + let witnessArgs, argsWithoutWitnesses = List.splitAt nWitnesses args + match argsWithoutWitnesses with + | objArgs :: argsWithoutObjectArg -> Some (Some objArgs, minfo, minfoW, witnessArgs, argsWithoutObjectArg) + | _ -> None + else + None | _ -> None let (|LetRaw|_|) input = @@ -644,8 +669,8 @@ module Patterns = | NewObjectOp ctor,_ -> ctor.DeclaringType | InstanceMethodCallOp minfo,_ -> minfo.ReturnType |> removeVoid | StaticMethodCallOp minfo,_ -> minfo.ReturnType |> removeVoid - | InstanceMethodCallWOp (_,minfoW,_),_ -> minfoW.ReturnType |> removeVoid - | StaticMethodCallWOp (_,minfoW,_),_ -> minfoW.ReturnType |> removeVoid + | InstanceMethodCallWOp (_, minfoW, _),_ -> minfoW.ReturnType |> removeVoid + | StaticMethodCallWOp (_, minfoW, _), _ -> minfoW.ReturnType |> removeVoid | CoerceOp ty,_ -> ty | SequentialOp,[_;b] -> typeOf b | ForIntegerRangeLoopOp,_ -> typeof @@ -2331,8 +2356,8 @@ module ExprShape = | DefaultValueOp(ty),_ -> mkDefaultValue(ty) | StaticMethodCallOp(minfo),_ -> mkStaticMethodCall(minfo,arguments) | InstanceMethodCallOp(minfo),obj::args -> mkInstanceMethodCall(obj,minfo,args) - | StaticMethodCallWOp(minfo, minfoW, n),_ -> mkStaticMethodCallW(minfo,minfoW,n,arguments) - | InstanceMethodCallWOp(minfo, minfoW, n),obj::args -> mkInstanceMethodCallW(obj,minfo,minfoW,n,args) + | StaticMethodCallWOp(minfo, minfoW, n),_ -> mkStaticMethodCallW(minfo, minfoW, n, arguments) + | InstanceMethodCallWOp(minfo, minfoW, n),obj::args -> mkInstanceMethodCallW(obj, minfo, minfoW, n, args) | CoerceOp(ty),[arg] -> mkCoerce(ty,arg) | NewArrayOp(ty),_ -> mkNewArray(ty,arguments) | NewDelegateOp(ty),[arg] -> mkNewDelegate(ty,arg) diff --git a/src/fsharp/MethodCalls.fs b/src/fsharp/MethodCalls.fs index 71cdff4a3ac..ce33346f236 100644 --- a/src/fsharp/MethodCalls.fs +++ b/src/fsharp/MethodCalls.fs @@ -1451,7 +1451,7 @@ let GenWitnessExpr amap g m (traitInfo: TraitConstraintInfo) argExprs = | "op_RightShift", [argty1;argty2], [arg1; arg2] | "op_UnaryPlus", [argty1], [arg1] *) - | "op_UnaryNegation", false, [argty1], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some + //| "op_UnaryNegation", false, [argty1], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some (* | "get_Sign", [], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some | "op_LogicalNot", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some diff --git a/src/fsharp/QuotationTranslator.fs b/src/fsharp/QuotationTranslator.fs index 3c26bafb06a..712894a9edb 100644 --- a/src/fsharp/QuotationTranslator.fs +++ b/src/fsharp/QuotationTranslator.fs @@ -84,6 +84,9 @@ type QuotationTranslationEnv = /// Map from typar stamps to binding index tyvs: StampMap + /// Indicates this is a witness arg we we disable further generation of witnesses + isWitness: bool + // Map for values bound by the // 'let v = isinst e in .... if nonnull v then ...v .... ' // construct arising out the compilation of pattern matching. We decode these back to the form @@ -97,6 +100,7 @@ type QuotationTranslationEnv = { vs = ValMap<_>.Empty nvs = 0 tyvs = Map.empty + isWitness = false isinstVals = ValMap<_>.Empty substVals = ValMap<_>.Empty } @@ -307,7 +311,7 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP. let witnessArgTys = GenWitnessTys cenv.g cxs let witnessArgs = - if cenv.g.generateWitnesses then + if cenv.g.generateWitnesses && not env.isWitness then ConstraintSolver.CodegenWitnessesForTyparInst cenv.tcVal cenv.g cenv.amap m tps tyargs |> CommitOperationResult else @@ -316,8 +320,6 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP. let subCall = if isMember then - let callArgs = (objArgs::witnessArgs::untupledCurriedArgs) |> List.concat - let parentTyconR = ConvTyconRef cenv vref.TopValDeclaringEntity m let isNewObj = isNewObj || valUseFlags || isSelfInit // The signature types are w.r.t. to the formal context @@ -328,7 +330,7 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP. let methRetTypeR = ConvReturnType cenv envinner m retTy let methName = vref.CompiledName let numGenericArgs = tyargs.Length - numEnclTypeArgs - ConvObjectModelCall cenv env m (isPropGet, isPropSet, isNewObj, parentTyconR, witnessArgTypesR, methArgTypesR, methRetTypeR, methName, tyargs, numGenericArgs, callArgs) + ConvObjectModelCall cenv env m (isPropGet, isPropSet, isNewObj, parentTyconR, witnessArgTypesR, methArgTypesR, methRetTypeR, methName, tyargs, numGenericArgs, objArgs, witnessArgs, untupledCurriedArgs) else // This is an application of the module value. ConvModuleValueApp cenv env m vref tyargs witnessArgs untupledCurriedArgs @@ -598,7 +600,7 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP. let isPropGet = isProp && methName.StartsWithOrdinal("get_") let isPropSet = isProp && methName.StartsWithOrdinal("set_") let tyargs = (enclTypeArgs@methTypeArgs) - ConvObjectModelCall cenv env m (isPropGet, isPropSet, isNewObj, parentTyconR, [], methArgTypesR, methRetTypeR, methName, tyargs, methTypeArgs.Length, callArgs) + ConvObjectModelCall cenv env m (isPropGet, isPropSet, isNewObj, parentTyconR, [], methArgTypesR, methRetTypeR, methName, tyargs, methTypeArgs.Length, [], [], [callArgs]) | TOp.TryFinally _, [_resty], [Expr.Lambda(_, _, _, [_], e1, _, _); Expr.Lambda(_, _, _, [_], e2, _, _)] -> QP.mkTryFinally(ConvExpr cenv env e1, ConvExpr cenv env e2) @@ -690,6 +692,9 @@ and ConvLValueArgs cenv env args = | obj::rest -> ConvLValueExpr cenv env obj :: ConvExprs cenv env rest | [] -> [] +and ConvWitnessArgs cenv env witnessArgs = + ConvExprs cenv { env with isWitness = true } witnessArgs + and ConvLValueExpr cenv env expr = EmitDebugInfoIfNecessary cenv env expr.Range (ConvLValueExprCore cenv env expr) @@ -716,25 +721,28 @@ and ConvLValueExprCore cenv env expr = and ConvObjectModelCall cenv env m callInfo = EmitDebugInfoIfNecessary cenv env m (ConvObjectModelCallCore cenv env m callInfo) -and ConvObjectModelCallCore cenv env m (isPropGet, isPropSet, isNewObj, parentTyconR, witnessArgTypesR, methArgTypesR, methRetTypeR, methName, tyargs, numGenericArgs, callArgs) = +and ConvObjectModelCallCore cenv env m (isPropGet, isPropSet, isNewObj, parentTyconR, witnessArgTypesR, methArgTypesR, methRetTypeR, methName, tyargs, numGenericArgs, objArgs, witnessArgs, untupledCurriedArgs) = let tyargsR = ConvTypes cenv env m tyargs + let callArgs = (objArgs::untupledCurriedArgs) |> List.concat let callArgsR = ConvLValueArgs cenv env callArgs - + let witnessArgsR = ConvWitnessArgs cenv env witnessArgs + let allArgsR = witnessArgsR @ callArgsR + if isPropGet || isPropSet then assert witnessArgTypesR.IsEmpty let propName = ChopPropertyName methName if isPropGet then - QP.mkPropGet( (parentTyconR, propName, methRetTypeR, methArgTypesR), tyargsR, callArgsR) + QP.mkPropGet( (parentTyconR, propName, methRetTypeR, methArgTypesR), tyargsR, allArgsR) else let args, propTy = List.frontAndBack methArgTypesR - QP.mkPropSet( (parentTyconR, propName, propTy, args), tyargsR, callArgsR) + QP.mkPropSet( (parentTyconR, propName, propTy, args), tyargsR, allArgsR) elif isNewObj then assert witnessArgTypesR.IsEmpty let ctorR : QuotationPickler.CtorData = { ctorParent = parentTyconR ctorArgTypes = methArgTypesR } - QP.mkCtorCall(ctorR, tyargsR, callArgsR) + QP.mkCtorCall(ctorR, tyargsR, allArgsR) elif witnessArgTypesR.IsEmpty then @@ -745,7 +753,7 @@ and ConvObjectModelCallCore cenv env m (isPropGet, isPropSet, isNewObj, parentTy methName = methName numGenericArgs = numGenericArgs } - QP.mkMethodCall(methR, tyargsR, callArgsR) + QP.mkMethodCall(methR, tyargsR, allArgsR) else @@ -765,7 +773,7 @@ and ConvObjectModelCallCore cenv env m (isPropGet, isPropSet, isNewObj, parentTy methName = ExtraWitnessMethodName methName numGenericArgs = numGenericArgs } - QP.mkMethodCallW(methR, methWR, List.length witnessArgTypesR, tyargsR, callArgsR) + QP.mkMethodCallW(methR, methWR, List.length witnessArgTypesR, tyargsR, allArgsR) and ConvModuleValueApp cenv env m (vref:ValRef) tyargs witnessArgs (args: Expr list list) = EmitDebugInfoIfNecessary cenv env m (ConvModuleValueAppCore cenv env m vref tyargs witnessArgs args) @@ -778,12 +786,14 @@ and ConvModuleValueAppCore cenv env m (vref:ValRef) tyargs witnessArgs (curriedA let tcrefR = ConvTyconRef cenv tcref m let tyargsR = ConvTypes cenv env m tyargs let nm = vref.CompiledName - let argsR = ConvExprs cenv env (List.concat (witnessArgs::curriedArgs)) + let witnessArgsR = ConvWitnessArgs cenv env witnessArgs + let uncurriedArgsR = ConvExprs cenv env (List.concat curriedArgs) + let allArgsR = witnessArgsR @ uncurriedArgsR let nWitnesses = witnessArgs.Length if nWitnesses = 0 then - QP.mkModuleValueApp(tcrefR, nm, isProperty, tyargsR, argsR) + QP.mkModuleValueApp(tcrefR, nm, isProperty, tyargsR, allArgsR) else - QP.mkModuleValueWApp(tcrefR, nm, isProperty, ExtraWitnessMethodName nm, nWitnesses, tyargsR, argsR) + QP.mkModuleValueWApp(tcrefR, nm, isProperty, ExtraWitnessMethodName nm, nWitnesses, tyargsR, allArgsR) and ConvExprs cenv env args = List.map (ConvExpr cenv env) args @@ -818,7 +828,7 @@ and private ConvValRefCore holeOk cenv env m (vref: ValRef) tyargs = | Parent _ -> let witnessArgs = - if cenv.g.generateWitnesses then + if cenv.g.generateWitnesses && not env.isWitness then ConstraintSolver.CodegenWitnessesForTyparInst cenv.tcVal cenv.g cenv.amap m vref.Typars tyargs |> CommitOperationResult else [] diff --git a/src/fsharp/fsc/fsc.fsproj b/src/fsharp/fsc/fsc.fsproj index e572c4bad2e..4f5507c8474 100644 --- a/src/fsharp/fsc/fsc.fsproj +++ b/src/fsharp/fsc/fsc.fsproj @@ -29,9 +29,13 @@ + + + + diff --git a/src/fsharp/fsi/fsi.fsproj b/src/fsharp/fsi/fsi.fsproj index f00aa6b4062..9e911b37dca 100644 --- a/src/fsharp/fsi/fsi.fsproj +++ b/src/fsharp/fsi/fsi.fsproj @@ -26,9 +26,13 @@ + + + + diff --git a/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj b/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj index b310a33b43c..d1c2d08c218 100644 --- a/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj +++ b/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj @@ -25,8 +25,13 @@ + + + + + + - diff --git a/tests/FSharp.Compiler.UnitTests/ProductVersion.fs b/tests/FSharp.Compiler.UnitTests/ProductVersion.fs index 77ff2e60d3b..fe95e82a977 100644 --- a/tests/FSharp.Compiler.UnitTests/ProductVersion.fs +++ b/tests/FSharp.Compiler.UnitTests/ProductVersion.fs @@ -93,21 +93,21 @@ module TypeProviderDesignTimeComponentLoading = let ``check tooling paths for type provider design time component loading`` () = let expected = [ -#if NET46 - // only searched when executing on .NET Framework - for tfm in ["net471"; "net47"; "net462"; "net461"; "net452"; "net451"; "net45"] do - yield Path.Combine("typeproviders", "fsharp41", tfm) - yield Path.Combine("tools", "fsharp41", tfm) -#else - // only searched when executing on .NET Core - for tfm in ["netcoreapp2.1"; "netcoreapp2.0"] do - yield Path.Combine("typeproviders", "fsharp41", tfm) - yield Path.Combine("tools", "fsharp41", tfm) -#endif - // always searched - for tfm in ["netstandard2.0"] do - yield Path.Combine("typeproviders", "fsharp41", tfm) - yield Path.Combine("tools", "fsharp41", tfm) +#if NET46 // only available on net46 + Path.Combine("typeproviders", "fsharp41", "net461") + Path.Combine("tools", "fsharp41", "net461") + Path.Combine("typeproviders", "fsharp41", "net452") + Path.Combine("tools", "fsharp41", "net452") + Path.Combine("typeproviders", "fsharp41", "net451") + Path.Combine("tools", "fsharp41", "net451") + Path.Combine("typeproviders", "fsharp41", "net45") + Path.Combine("tools", "fsharp41", "net45") +#else // only available on netcoreapp2.0 + Path.Combine("typeproviders", "fsharp41", "netcoreapp2.0") + Path.Combine("tools", "fsharp41", "netcoreapp2.0") +#endif // available in both + Path.Combine("typeproviders", "fsharp41", "netstandard2.0") + Path.Combine("tools", "fsharp41", "netstandard2.0") ] let actual = FSharp.Compiler.ExtensionTyping.toolingCompatiblePaths() printfn "actual = %A" actual diff --git a/tests/fsharp/single-test.fs b/tests/fsharp/single-test.fs index 614183b319f..b0a24ccb8e9 100644 --- a/tests/fsharp/single-test.fs +++ b/tests/fsharp/single-test.fs @@ -219,8 +219,7 @@ let singleTestBuildAndRunCore cfg copyFiles p = let projectBody = generateProjectArtifacts pc targetFramework cfg.BUILD_CONFIG emitFile projectFileName projectBody use testOkFile = new FileGuard(Path.Combine(directory, "test.ok")) - printfn "executeFsc: cfg.DotNetExe = %s" cfg.DotNetExe - exec { cfg with Directory = directory } cfg.DotNetExe "help" // (sprintf "run -f %s" targetFramework) + exec { cfg with Directory = directory } cfg.DotNetExe (sprintf "run -f %s" targetFramework) testOkFile.CheckExists() executeFsc compilerType targetFramework else @@ -230,7 +229,6 @@ let singleTestBuildAndRunCore cfg copyFiles p = let projectBody = generateProjectArtifacts pc targetFramework cfg.BUILD_CONFIG emitFile projectFileName projectBody use testOkFile = new FileGuard(Path.Combine(directory, "test.ok")) - printfn "executeFsi: cfg.DotNetExe = %s" cfg.DotNetExe exec { cfg with Directory = directory } cfg.DotNetExe "build /t:RunFSharpScript" testOkFile.CheckExists() executeFsi compilerType targetFramework From 80a14f9f96f90e3b2225863d56e7c24a90d9979d Mon Sep 17 00:00:00 2001 From: Don Syme Date: Mon, 1 Apr 2019 19:02:57 +0100 Subject: [PATCH 49/77] complete primitive witnesses --- src/fsharp/FSharp.Core/prim-types.fs | 57 +- src/fsharp/FSharp.Core/prim-types.fsi | 856 +++++++++++++++++- src/fsharp/FSharp.Core/quotations.fs | 37 +- src/fsharp/MethodCalls.fs | 69 +- src/fsharp/NicePrint.fs | 11 +- src/fsharp/TastOps.fs | 23 +- src/fsharp/TastOps.fsi | 10 +- src/fsharp/TcGlobals.fs | 59 +- src/fsharp/symbols/Exprs.fs | 4 +- tests/fsharp/core/quotes/test.fsx | 23 +- tests/fsharpqa/Source/Printing/Quotation01.fs | 4 +- 11 files changed, 1019 insertions(+), 134 deletions(-) diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index c444959d005..a53ceebc172 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -2499,6 +2499,7 @@ namespace Microsoft.FSharp.Core static member inline op_Multiply(x: uint16, y: uint16) = (# "conv.u2" (# "mul" x y : uint32 #) : uint16 #) static member inline op_Multiply(x: sbyte, y: sbyte) = (# "conv.i1" (# "mul" x y : int32 #) : sbyte #) static member inline op_Multiply(x: byte, y: byte) = (# "conv.u1" (# "mul" x y : uint32 #) : byte #) + static member inline op_Multiply(x: decimal, y: decimal) = Decimal.op_Multiply(x, y) static member inline op_UnaryNegation(value: int32) = (# "neg" value : int32 #) static member inline op_UnaryNegation(value: float) = (# "neg" value : float #) @@ -2507,6 +2508,7 @@ namespace Microsoft.FSharp.Core static member inline op_UnaryNegation(value: int16) = (# "neg" value : int16 #) static member inline op_UnaryNegation(value: nativeint) = (# "neg" value : nativeint #) static member inline op_UnaryNegation(value: sbyte) = (# "neg" value : sbyte #) + static member inline op_UnaryNegation(value: decimal) = Decimal.op_UnaryNegation(value) static member inline op_Subtraction(x: int32, y: int32) = (# "sub" x y : int32 #) static member inline op_Subtraction(x: float, y: float) = (# "sub" x y : float #) @@ -2978,7 +2980,10 @@ namespace Microsoft.FSharp.Core static member inline op_Inequality(x: string, y: string) = not (String.Equals(x, y)) static member inline op_Inequality(x: decimal, y: decimal) = Decimal.op_Inequality(x, y) - // TODO: rationalise these + static member inline DivideByInt (x: decimal, n: int) = Decimal.Divide(x, Convert.ToDecimal(n)) + static member inline DivideByInt (x: float, n: int) = (# "div" x ((# "conv.r8" n : float #)) : float #) + static member inline DivideByInt (x: float32, n:int) = (# "div" x ((# "conv.r4" n : float32 #)) : float32 #) + type GenericZeroDynamicImplTable<'T>() = static let result : 'T = // The dynamic implementation @@ -3071,39 +3076,11 @@ namespace Microsoft.FSharp.Core // That is, not in the generic implementation of '+' when ^T : ^T = (^T : (static member One : ^T) ()) - // TODO: rationalise these - type GenericDivideByIntDynamicImplTable<'T>() = - static let result : ('T -> int -> 'T) = - // The dynamic implementation - let aty = typeof<'T> - if aty.Equals(typeof) then unboxPrim<_> (box (fun (x:decimal) (n:int) -> Decimal.Divide(x, Convert.ToDecimal(n)))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float) (n:int) -> (# "div" x ((# "conv.r8" n : float #)) : float #))) - elif aty.Equals(typeof) then unboxPrim<_> (box (fun (x:float32) (n:int) -> (# "div" x ((# "conv.r4" n : float32 #)) : float32 #))) - else - match aty.GetRuntimeMethod("DivideByInt",[| aty; typeof |]) with - | null -> raise (NotSupportedException (SR.GetString(SR.dyInvDivByIntCoerce))) - | m -> (fun x n -> unboxPrim<_> (m.Invoke(null,[| box x; box n |]))) - - static member Result : ('T -> int -> 'T) = result - - // TODO: rationalise these - let DivideByIntDynamic<'T> x y = GenericDivideByIntDynamicImplTable<('T)>.Result x y - - // TODO: rationalise these - let inline DivideByInt< ^T when ^T : (static member DivideByInt : ^T * int -> ^T) > (x:^T) (y:int) : ^T = - DivideByIntDynamic<'T> x y - when ^T : float = (# "div" x ((# "conv.r8" (y:int) : float #)) : float #) - when ^T : float32 = (# "div" x ((# "conv.r4" (y:int) : float32 #)) : float32 #) - when ^T : decimal = Decimal.Divide((retype x:decimal), Convert.ToDecimal(y)) - when ^T : ^T = (^T : (static member DivideByInt : ^T * int -> ^T) (x, y)) - - // TODO: rationalise these let UnaryDynamicImpl nm : ('T -> 'U) = let aty = typeof<'T> let minfo = aty.GetRuntimeMethod(nm, [| aty |]) (fun x -> unboxPrim<_>(minfo.Invoke(null,[| box x|]))) - // TODO: rationalise these let BinaryDynamicImpl nm : ('T -> 'U -> 'V) = let aty = typeof<'T> let bty = typeof<'U> @@ -3257,6 +3234,16 @@ namespace Microsoft.FSharp.Core type OpInequalityInfo = static member Name = "op_Inequality" let OpInequalityDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y + type DivideByIntInfo = static member Name = "DivideByInt" + let DivideByIntDynamic<'T> x y = BinaryOpDynamicImplTable.Impl x y + + let inline DivideByInt< ^T when ^T : (static member DivideByInt : ^T * int -> ^T) > (x: ^T) (y: int) : ^T = + DivideByIntDynamic<'T> x y + when ^T : float = BuiltInWitnesses.DivideByInt ((retype x: float), y) + when ^T : float32 = BuiltInWitnesses.DivideByInt ((retype x: float32), y) + when ^T : decimal = BuiltInWitnesses.DivideByInt ((retype x: decimal), y) + when ^T : ^T = (^T : (static member DivideByInt : ^T * int -> ^T) (x, y)) + namespace Microsoft.FSharp.Core open System @@ -5742,11 +5729,13 @@ namespace Microsoft.FSharp.Core when ^T : float32 = let x : float32 = retype x in System.Math.Abs(x) when ^T : int64 = let x : int64 = retype x in System.Math.Abs(x) when ^T : nativeint = - let x : nativeint = retype x in - if x >= 0n then x else - let res = -x in - if res < 0n then raise (System.OverflowException(ErrorStrings.NoNegateMinValueString)) - res + (let x : nativeint = retype x + if x >= 0n then + x + else + let res = -x + if res < 0n then raise (System.OverflowException(ErrorStrings.NoNegateMinValueString)) + res) when ^T : int16 = let x : int16 = retype x in System.Math.Abs(x) when ^T : sbyte = let x : sbyte = retype x in System.Math.Abs(x) when ^T : decimal = System.Math.Abs(retype x : decimal) diff --git a/src/fsharp/FSharp.Core/prim-types.fsi b/src/fsharp/FSharp.Core/prim-types.fsi index b596c806a71..e5139a7a03d 100644 --- a/src/fsharp/FSharp.Core/prim-types.fsi +++ b/src/fsharp/FSharp.Core/prim-types.fsi @@ -1175,472 +1175,1302 @@ namespace Microsoft.FSharp.Core /// The division result. val inline DivideByInt< ^T > : x:^T -> y:int -> ^T when ^T : (static member DivideByInt : ^T * int -> ^T) -(* + [] + /// Representative witnesses for traits solved by the F# compiler type BuiltInWitnesses = + + /// A representative witness for traits solved by the F# compiler static member inline op_Addition: x: int32 * y: int32 -> int32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Addition: x: float * y: float -> float + + /// A representative witness for traits solved by the F# compiler static member inline op_Addition: x: float32 * y: float32 -> float32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Addition: x: int64 * y: int64 -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Addition: x: uint64 * y: uint64 -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Addition: x: uint32 * y: uint32 -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Addition: x: nativeint * y: nativeint -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Addition: x: unativeint * y: unativeint -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Addition: x: int16 * y: int16 -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Addition: x: uint16 * y: uint16 -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Addition: x: char * y: char -> char + + /// A representative witness for traits solved by the F# compiler static member inline op_Addition: x: sbyte * y: sbyte -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_Addition: x: byte * y: byte -> byte + + /// A representative witness for traits solved by the F# compiler static member inline op_Addition: x: string * y: string -> string + + /// A representative witness for traits solved by the F# compiler static member inline op_Addition: x: decimal * y: decimal -> decimal - + + /// A representative witness for traits solved by the F# compiler static member inline op_Multiply: x: int32 * y: int32 -> int32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Multiply: x: float * y: float -> float + + /// A representative witness for traits solved by the F# compiler static member inline op_Multiply: x: float32 * y: float32 -> float32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Multiply: x: int64 * y: int64 -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Multiply: x: uint64 * y: uint64 -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Multiply: x: uint32 * y: uint32 -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Multiply: x: nativeint * y: nativeint -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Multiply: x: unativeint * y: unativeint -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Multiply: x: int16 * y: int16 -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Multiply: x: uint16 * y: uint16 -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Multiply: x: sbyte * y: sbyte -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_Multiply: x: byte * y: byte -> byte + + /// A representative witness for traits solved by the F# compiler static member inline op_Multiply: x: decimal * y: decimal -> decimal - static member inline op_UnaryNegation: x: int32 -> int32 - static member inline op_UnaryNegation: x: float -> float - static member inline op_UnaryNegation: x: float32 -> float32 - static member inline op_UnaryNegation: x: int64 -> int64 - static member inline op_UnaryNegation: x: int16 -> int16 - static member inline op_UnaryNegation: x: nativeint -> nativeint - static member inline op_UnaryNegation: x: sbyte -> sbyte - static member inline op_UnaryNegation: x: decimal -> decimal + /// A representative witness for traits solved by the F# compiler + static member inline op_UnaryNegation: value: int32 -> int32 + + /// A representative witness for traits solved by the F# compiler + static member inline op_UnaryNegation: value: float -> float + + /// A representative witness for traits solved by the F# compiler + static member inline op_UnaryNegation: value: float32 -> float32 + + /// A representative witness for traits solved by the F# compiler + static member inline op_UnaryNegation: value: int64 -> int64 + + /// A representative witness for traits solved by the F# compiler + static member inline op_UnaryNegation: value: int16 -> int16 + + /// A representative witness for traits solved by the F# compiler + static member inline op_UnaryNegation: value: nativeint -> nativeint + + /// A representative witness for traits solved by the F# compiler + static member inline op_UnaryNegation: value: sbyte -> sbyte + + /// A representative witness for traits solved by the F# compiler + static member inline op_UnaryNegation: value: decimal -> decimal + /// A representative witness for traits solved by the F# compiler static member inline op_Subtraction: x: int32 * y: int32 -> int32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Subtraction: x: float * y: float -> float + + /// A representative witness for traits solved by the F# compiler static member inline op_Subtraction: x: float32 * y: float32 -> float32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Subtraction: x: int64 * y: int64 -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Subtraction: x: uint64 * y: uint64 -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Subtraction: x: uint32 * y: uint32 -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Subtraction: x: nativeint * y: nativeint -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Subtraction: x: unativeint * y: unativeint -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Subtraction: x: int16 * y: int16 -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Subtraction: x: uint16 * y: uint16 -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Subtraction: x: sbyte * y: sbyte -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_Subtraction: x: byte * y: byte -> byte + + /// A representative witness for traits solved by the F# compiler static member inline op_Subtraction: x: decimal * y: decimal -> decimal + /// A representative witness for traits solved by the F# compiler static member inline op_Division: x: int32 * y: int32 -> int32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Division: x: float * y: float -> float + + /// A representative witness for traits solved by the F# compiler static member inline op_Division: x: float32 * y: float32 -> float32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Division: x: int64 * y: int64 -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Division: x: uint64 * y: uint64 -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Division: x: uint32 * y: uint32 -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Division: x: nativeint * y: nativeint -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Division: x: unativeint * y: unativeint -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Division: x: int16 * y: int16 -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Division: x: uint16 * y: uint16 -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Division: x: sbyte * y: sbyte -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_Division: x: byte * y: byte -> byte + + /// A representative witness for traits solved by the F# compiler static member inline op_Division: x: decimal * y: decimal -> decimal + /// A representative witness for traits solved by the F# compiler static member inline op_Modulus: x: int32 * y: int32 -> int32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Modulus: x: float * y: float -> float + + /// A representative witness for traits solved by the F# compiler static member inline op_Modulus: x: float32 * y: float32 -> float32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Modulus: x: int64 * y: int64 -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Modulus: x: uint64 * y: uint64 -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Modulus: x: uint32 * y: uint32 -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Modulus: x: nativeint * y: nativeint -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Modulus: x: unativeint * y: unativeint -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Modulus: x: int16 * y: int16 -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Modulus: x: uint16 * y: uint16 -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Modulus: x: sbyte * y: sbyte -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_Modulus: x: byte * y: byte -> byte + + /// A representative witness for traits solved by the F# compiler static member inline op_Modulus: x: decimal * y: decimal -> decimal + /// A representative witness for traits solved by the F# compiler static member inline op_LeftShift: value: int32 * shift: int32 -> int32 + + /// A representative witness for traits solved by the F# compiler static member inline op_LeftShift: value: uint32 * shift: int32 -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_LeftShift: value: int64 * shift: int32 -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_LeftShift: value: uint64 * shift: int32 -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_LeftShift: value: nativeint * shift: int32 -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_LeftShift: value: unativeint * shift: int32 -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_LeftShift: value: int16 * shift: int32 -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_LeftShift: value: uint16 * shift: int32 -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_LeftShift: value: sbyte * shift: int32 -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_LeftShift: value: byte * shift: int32 -> byte + /// A representative witness for traits solved by the F# compiler static member inline op_RightShift: value: byte * shift: int32 -> byte + + /// A representative witness for traits solved by the F# compiler static member inline op_RightShift: value: uint32 * shift: int32 -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_RightShift: value: int64 * shift: int32 -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_RightShift: value: uint64 * shift: int32 -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_RightShift: value: nativeint * shift: int32 -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_RightShift: value: unativeint * shift: int32 -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_RightShift: value: int16 * shift: int32 -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_RightShift: value: uint16 * shift: int32 -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_RightShift: value: sbyte * shift: int32 -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_RightShift: value: byte * shift: int32 -> byte + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseAnd: x: int32 * y: int32 -> int32 + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseAnd: x: int64 * y: int64 -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseAnd: x: uint64 * y: uint64 -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseAnd: x: uint32 * y: uint32 -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseAnd: x: int16 * y: int16 -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseAnd: x: uint16 * y: uint16 -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseAnd: x: nativeint * y: nativeint -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseAnd: x: unativeint * y: unativeint -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseAnd: x: sbyte * y: sbyte -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseAnd: x: byte * y: byte -> byte + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseOr: x: int32 * y: int32 -> int32 + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseOr: x: int64 * y: int64 -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseOr: x: uint64 * y: uint64 -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseOr: x: uint32 * y: uint32 -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseOr: x: int16 * y: int16 -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseOr: x: uint16 * y: uint16 -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseOr: x: nativeint * y: nativeint -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseOr: x: unativeint * y: unativeint -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseOr: x: sbyte * y: sbyte -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseOr: x: byte * y: byte -> byte + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseExclusiveOr: x: int32 * y: int32 -> int32 + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseExclusiveOr: x: int64 * y: int64 -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseExclusiveOr: x: uint64 * y: uint64 -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseExclusiveOr: x: uint32 * y: uint32 -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseExclusiveOr: x: int16 * y: int16 -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseExclusiveOr: x: uint16 * y: uint16 -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseExclusiveOr: x: nativeint * y: nativeint -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseExclusiveOr: x: unativeint * y: unativeint -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseExclusiveOr: x: sbyte * y: sbyte -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseExclusiveOr: x: byte * y: byte -> byte + /// A representative witness for traits solved by the F# compiler static member inline op_LogicalNot: value: int32 -> int32 + + /// A representative witness for traits solved by the F# compiler static member inline op_LogicalNot: value: int64 -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_LogicalNot: value: uint64 -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_LogicalNot: value: uint32 -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_LogicalNot: value: nativeint -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_LogicalNot: value: unativeint -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_LogicalNot: value: int16 -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_LogicalNot: value: uint16 -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_LogicalNot: value: sbyte -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_LogicalNot: value: byte -> byte + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: string -> byte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float -> byte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float32 -> byte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int64 -> byte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int32 -> byte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int16 -> byte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: nativeint -> byte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: sbyte -> byte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint64 -> byte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint32 -> byte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint16 -> byte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: char -> byte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: unativeint -> byte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: byte -> byte + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: byte -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float32 -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int64 -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int32 -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int16 -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: nativeint -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: sbyte -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint64 -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint32 -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint16 -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: char -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: unativeint -> sbyte + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: byte -> sbyte + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: string -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float32 -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int64 -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int32 -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int16 -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: nativeint -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: sbyte -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint64 -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint32 -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint16 -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: char -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: unativeint -> uint16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: byte -> uint16 + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: string -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float32 -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int64 -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int32 -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int16 -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: nativeint -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: sbyte -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint64 -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint32 -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint16 -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: char -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: unativeint -> int16 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: byte -> int16 + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: string -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float32 -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int64 -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: nativeint -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int32 -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int16 -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: sbyte -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint64 -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint32 -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint16 -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: char -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: unativeint -> uint32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: byte -> uint32 + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: string -> int32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float -> int32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float32 -> int32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int64 -> int32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: nativeint -> int32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int32 -> int32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int16 -> int32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: sbyte -> int32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint64 -> int32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint32 -> int32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint16 -> int32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: char -> int32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: unativeint -> int32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: byte -> int32 + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: string -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float32 -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int64 -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int32 -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int16 -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: nativeint -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: sbyte -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint64 -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint32 -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint16 -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: char -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: unativeint -> uint64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: byte -> uint64 + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: string -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: string -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float32 -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int64 -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int32 -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int16 -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: nativeint -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: sbyte -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint64 -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint32 -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint16 -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: char -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: unativeint -> int64 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: byte -> int64 + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: string -> float32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float -> float32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float32 -> float32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int64 -> float32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int32 -> float32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int16 -> float32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: nativeint -> float32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: sbyte -> float32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint64 -> float32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint32 -> float32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint16 -> float32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: char -> float32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: unativeint -> float32 + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: byte -> float32 + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: string -> float + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float -> float + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float32 -> float + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int64 -> float + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int32 -> float + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int16 -> float + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: nativeint -> float + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: sbyte -> float + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint64 -> float + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint32 -> float + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint16 -> float + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: char -> float + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: unativeint -> float + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: byte -> float + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: decimal -> float + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: string -> decimal + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float -> decimal + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float32 -> decimal + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int64 -> decimal + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int32 -> decimal + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int16 -> decimal + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: nativeint -> decimal + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: sbyte -> decimal + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint64 -> decimal + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint32 -> decimal + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint16 -> decimal + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: unativeint -> decimal + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: byte -> decimal + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: decimal -> decimal + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: string -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float32 -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int64 -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int32 -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int16 -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: nativeint -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: sbyte -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint64 -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint32 -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint16 -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: char -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: unativeint -> unativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: byte -> unativeint + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: string -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float32 -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int64 -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int32 -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int16 -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: nativeint -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: sbyte -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint64 -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint32 -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint16 -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: char -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: unativeint -> nativeint + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: byte -> nativeint + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: string -> char + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float -> char + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float32 -> char + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int64 -> char + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int32 -> char + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: int16 -> char + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: nativeint -> char + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: sbyte -> char + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint64 -> char + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint32 -> char + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: uint16 -> char + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: char -> char + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: unativeint -> char + + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: byte -> char + /// A representative witness for traits solved by the F# compiler static member inline op_LessThan: x: bool * y: bool -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThan: x: sbyte * y: sbyte -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThan: x: int16 * y: int16 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThan: x: int32 * y: int32 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThan: x: int64 * y: int64 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThan: x: byte * y: byte -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThan: x: uint16 * y: uint16 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThan: x: uint32 * y: uint32 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThan: x: uint64 * y: uint64 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThan: x: unativeint * y: unativeint -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThan: x: nativeint * y: nativeint -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThan: x: float * y: float -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThan: x: float32 * y: float32 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThan: x: char * y: char -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThan: x: decimal * y: decimal -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThan: x: string * y: string -> bool + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThan: x: bool * y: bool -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThan: x: sbyte * y: sbyte -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThan: x: int16 * y: int16 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThan: x: int32 * y: int32 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThan: x: int64 * y: int64 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThan: x: nativeint * y: nativeint -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThan: x: byte * y: byte -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThan: x: uint16 * y: uint16 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThan: x: uint32 * y: uint32 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThan: x: uint64 * y: uint64 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThan: x: unativeint * y: unativeint -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThan: x: float * y: float -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThan: x: float32 * y: float32 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThan: x: char * y: char -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThan: x: decimal * y: decimal -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThan: x: string * y: string -> bool + /// A representative witness for traits solved by the F# compiler static member inline op_LessThanOrEqual: x: bool * y: bool -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThanOrEqual: x: sbyte * y: sbyte -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThanOrEqual: x: int16 * y: int16 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThanOrEqual: x: int32 * y: int32 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThanOrEqual: x: int64 * y: int64 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThanOrEqual: x: nativeint * y: nativeint -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThanOrEqual: x: byte * y: byte -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThanOrEqual: x: uint16 * y: uint16 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThanOrEqual: x: uint32 * y: uint32 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThanOrEqual: x: uint64 * y: uint64 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThanOrEqual: x: unativeint * y: unativeint -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThanOrEqual: x: float * y: unativeint -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThanOrEqual: x: float32 * y: float32 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThanOrEqual: x: char * y: char -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThanOrEqual: x: decimal * y: decimal -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_LessThanOrEqual: x: string * y: string -> bool + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThanOrEqual: x: bool * y: bool -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThanOrEqual: x: sbyte * y: sbyte -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThanOrEqual: x: int16 * y: int16 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThanOrEqual: x: int32 * y: int32 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThanOrEqual: x: int64 * y: int64 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThanOrEqual: x: nativeint * y: nativeint -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThanOrEqual: x: byte * y: byte -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThanOrEqual: x: uint16 * y: uint16 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThanOrEqual: x: uint32 * y: uint32 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThanOrEqual: x: uint64 * y: uint64 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThanOrEqual: x: unativeint * y: unativeint -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThanOrEqual: x: float * y: float -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThanOrEqual: x: float32 * y: float32 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThanOrEqual: x: char * y: char -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThanOrEqual: x: decimal * y: decimal -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_GreaterThanOrEqual: x: string * y: string -> bool + /// A representative witness for traits solved by the F# compiler static member inline op_Equality: x: bool * y: bool -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Equality: x: sbyte * y: sbyte -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Equality: x: int16 * y: int16 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Equality: x: int32 * y: int32 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Equality: x: int64 * y: int64 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Equality: x: byte * y: byte -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Equality: x: uint16 * y: uint16 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Equality: x: uint32 * y: uint32 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Equality: x: uint64 * y: uint64 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Equality: x: float * y: float -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Equality: x: float32 * y: float32 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Equality: x: char * y: char -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Equality: x: nativeint * y: nativeint -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Equality: x: unativeint * y: unativeint -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Equality: x: string * y: string -> bool - static member inline op_Equality: x: decimal * y: v -> bool + /// A representative witness for traits solved by the F# compiler + static member inline op_Equality: x: decimal * y: decimal -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Inequality: x: bool * y: bool -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Inequality: x: sbyte * y: sbyte -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Inequality: x: int16 * y: int16 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Inequality: x: int32 * y: int32 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Inequality: x: int64 * y: int64 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Inequality: x: byte * y: byte -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Inequality: x: uint16 * y: uint16 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Inequality: x: uint32 * y: uint32 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Inequality: x: uint64 * y: uint64 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Inequality: x: float * y: float -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Inequality: x: float32 * y: float32 -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Inequality: x: char * y: char -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Inequality: x: nativeint * y: nativeint -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Inequality: x: unativeint * y: unativeint -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Inequality: x: string * y: string -> bool + + /// A representative witness for traits solved by the F# compiler static member inline op_Inequality: x: decimal * y: decimal -> bool - + + /// A representative witness for traits solved by the F# compiler static member inline DivideByInt: x: float * y: int -> float + + /// A representative witness for traits solved by the F# compiler static member inline DivideByInt: x: float32 * y: int -> float32 + + /// A representative witness for traits solved by the F# compiler static member inline DivideByInt: x: decimal * y: int -> decimal -*) /// For compiler use only module (* internal *) ErrorStrings = diff --git a/src/fsharp/FSharp.Core/quotations.fs b/src/fsharp/FSharp.Core/quotations.fs index de9005c30b9..dd13b42b638 100644 --- a/src/fsharp/FSharp.Core/quotations.fs +++ b/src/fsharp/FSharp.Core/quotations.fs @@ -197,7 +197,7 @@ and | WithValueOp of obj * Type | DefaultValueOp of Type -and [] +and [] Expr(term:Tree,attribs:Expr list) = member x.Tree = term member x.CustomAttributes = attribs @@ -209,6 +209,27 @@ and [] match t1, t2 with // We special-case ValueOp to ensure that ValueWithName = Value | CombTerm(ValueOp(v1,ty1,_),[]),CombTerm(ValueOp(v2,ty2,_),[]) -> (v1 = v2) && (ty1 = ty2) + + // We strip off InstanceMethodCallWOp to ensure that CallWithWitness = Call + | CombTerm(InstanceMethodCallWOp(minfo1, _minfoW1, nWitnesses1), args1), _ -> + let argsWithoutWitnesses1 = List.skip nWitnesses1 args1 + eq (CombTerm(InstanceMethodCallOp(minfo1), argsWithoutWitnesses1)) t2 + + // We strip off InstanceMethodCallWOp to ensure that CallWithWitness = Call + | _, CombTerm(InstanceMethodCallWOp(minfo2, _minfoW2, nWitnesses2), args2) -> + let argsWithoutWitnesses2 = List.skip nWitnesses2 args2 + eq t1 (CombTerm(InstanceMethodCallOp(minfo2), argsWithoutWitnesses2)) + + // We strip off StaticMethodCallWOp to ensure that CallWithWitness = Call + | CombTerm(StaticMethodCallWOp(minfo1, _minfoW1, nWitnesses1), args1), _ -> + let argsWithoutWitnesses1 = List.skip nWitnesses1 args1 + eq (CombTerm(StaticMethodCallOp(minfo1), argsWithoutWitnesses1)) t2 + + // We strip off StaticMethodCallWOp to ensure that CallWithWitness = Call + | _, CombTerm(StaticMethodCallWOp(minfo2, _minfoW2, nWitnesses2), args2) -> + let argsWithoutWitnesses2 = List.skip nWitnesses2 args2 + eq t1 (CombTerm(StaticMethodCallOp(minfo2), argsWithoutWitnesses2)) + | CombTerm(c1, es1), CombTerm(c2,es2) -> c1 = c2 && es1.Length = es2.Length && (es1 = es2) | VarTerm v1, VarTerm v2 -> (v1 = v2) | LambdaTerm (v1,e1), LambdaTerm(v2,e2) -> (v1 = v2) && (e1 = e2) @@ -223,10 +244,12 @@ and [] override x.ToString() = x.ToString(false) member x.ToString(full) = - Microsoft.FSharp.Text.StructuredPrintfImpl.Display.layout_to_string Microsoft.FSharp.Text.StructuredPrintfImpl.FormatOptions.Default (x.GetLayout(full)) + Display.layout_to_string FormatOptions.Default (x.GetLayout(full)) + + member x.DebugText = x.ToString(false) member x.GetLayout(long) = - let expr (e:Expr ) = e.GetLayout(long) + let expr (e:Expr) = e.GetLayout(long) let exprs (es:Expr list) = es |> List.map expr let parens ls = bracketL (commaListL ls) let pairL l1 l2 = bracketL (l1 ^^ sepL Literals.comma ^^ l2) @@ -316,8 +339,6 @@ and [] | CombTerm(QuoteOp _,args) -> combL "Quote" (exprs args) | _ -> failwithf "Unexpected term in layout %A" x.Tree - - and [] Expr<'T>(term:Tree,attribs) = inherit Expr(term,attribs) @@ -548,8 +569,6 @@ module Patterns = [] let (|CallWithWitnesses|_|) input = match input with - | E(CombTerm(StaticMethodCallOp minfo,args)) -> Some(None,minfo,minfo,[],args) - | E(CombTerm(InstanceMethodCallOp minfo,(obj::args))) -> Some(Some(obj),minfo,minfo,[],args) | E(CombTerm(StaticMethodCallWOp (minfo, minfoW, nWitnesses),args)) -> Some(None,minfo,minfoW,List.take nWitnesses args, List.skip nWitnesses args) | E(CombTerm(InstanceMethodCallWOp (minfo, minfoW, nWitnesses), args)) -> if args.Length >= nWitnesses then @@ -2026,12 +2045,12 @@ type Expr with static member CallWithWitnesses (methodInfo:MethodInfo, methodInfoWithWitnesses:MethodInfo, witnessArguments, arguments) = checkNonNull "methodInfo" methodInfo - checkNonNull "methodInfo" methodInfoWithWitnesses + checkNonNull "methodInfoWithWitnesses" methodInfoWithWitnesses mkStaticMethodCallW (methodInfo, methodInfoWithWitnesses, List.length witnessArguments, witnessArguments@arguments) static member CallWithWitnesses (obj:Expr, methodInfo:MethodInfo, methodInfoWithWitnesses:MethodInfo, witnessArguments, arguments) = checkNonNull "methodInfo" methodInfo - checkNonNull "methodInfo" methodInfoWithWitnesses + checkNonNull "methodInfoWithWitnesses" methodInfoWithWitnesses mkInstanceMethodCallW (obj, methodInfo, methodInfoWithWitnesses, List.length witnessArguments, witnessArguments@arguments) static member Coerce (source:Expr, target:Type) = diff --git a/src/fsharp/MethodCalls.fs b/src/fsharp/MethodCalls.fs index ce33346f236..bc0c313f81b 100644 --- a/src/fsharp/MethodCalls.fs +++ b/src/fsharp/MethodCalls.fs @@ -1424,64 +1424,16 @@ let GenWitnessExpr amap g m (traitInfo: TraitConstraintInfo) argExprs = | Choice5Of5 () -> match traitInfo.Solution with | None -> None // the trait has been generalized - | Some _-> - let rty = match traitInfo.ReturnType with None -> g.unit_ty | Some ty -> ty - match traitInfo.MemberName, traitInfo.MemberFlags.IsInstance, traitInfo.ArgumentTypes, argExprs with - | "op_Division", false, [argty1;argty2], [arg1; arg2] -> mkCallDivisionOperator g m argty1 argty2 rty arg1 arg2 |> Some - | "op_Addition", false, [argty1;argty2], [arg1; arg2] -> mkCallAdditionOperator g m argty1 argty2 rty arg1 arg2 |> Some -(* - | "op_Multiply", [argty1;argty2], [arg1; arg2] - | "op_Subtraction", [argty1;argty2], [arg1; arg2] - | "op_Modulus", [argty1;argty2], [arg1; arg2] - | "op_LessThan", [argty1;argty2], [arg1; arg2] - | "op_LessThanOrEqual", [argty1;argty2], [arg1; arg2] - | "op_GreaterThan", [argty1;argty2], [arg1; arg2] - | "op_GreaterThanOrEqual", [argty1;argty2], [arg1; arg2] - | "op_Inequality", [argty1;argty2], [arg1; arg2] - | "get_Zero", [argty1;argty2], [arg1; arg2] - | "get_One", [argty1;argty2], [arg1; arg2] - | "DivideByInt", [argty1;argty2], [arg1; arg2] - | "get_Item", true, [argty1], [arg1] when isStringTy g ty - | "get_Item", true, argtys, [arg1] when isArrayTy g ty - | "set_Item", true, argtys, [arg1] when isArrayTy g ty - | "op_BitwiseAnd", [argty1;argty2], [arg1; arg2] - | "op_BitwiseOr", [argty1;argty2], [arg1; arg2] - | "op_ExclusiveOr", [argty1;argty2], [arg1; arg2] - | "op_LeftShift", [argty1;argty2], [arg1; arg2] - | "op_RightShift", [argty1;argty2], [arg1; arg2] - | "op_UnaryPlus", [argty1], [arg1] -*) - //| "op_UnaryNegation", false, [argty1], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some -(* - | "get_Sign", [], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "op_LogicalNot", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "op_OnesComplement", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "Abs", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "Sqrt", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "Sin", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "Cos", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "Tan", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "Sinh", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "Cosh", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "Tanh", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "Atan", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "Acos", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "Asin", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "Exp", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "Ceiling", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "Floor", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "Round", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "Truncate", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "Log10", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "Log", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "Sqrt", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "op_Explicit", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "Pow", [argty1; argty2], [arg1; arg2] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "Atan2", [argty1; argty2], [arg1; arg2] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some - | "Sqrt", [argty], [arg1] -> mkCallUnaryNegOperator g m argty1 arg1 |> Some -*) - | _ -> None - + | Some _-> + // For these operators, the witness is just a call to the coresponding FSharp.Core operator + match g.tryMakeOperatorAsBuiltInWitnessInfo isStringTy isArrayTy traitInfo with + | Some (info, tyargs) -> + tryMkCallCoreFunctionAsBuiltInWitness g info tyargs argExprs m + | None -> + // For all other built-in operators, the witness is a call to the coresponding BuiltInWitnesses operator + // These are called as F# methods not F# functions + tryMkCallBuiltInWitness g traitInfo argExprs m + let GenWitnessExprLambda amap g m (traitInfo: TraitConstraintInfo) = let argtysl = GenWitnessArgTys g traitInfo.TraitKey let vse = argtysl |> List.mapiSquared (fun i j ty -> mkCompGenLocal m ("arg" + string i + "_" + string j) ty) @@ -1490,6 +1442,7 @@ let GenWitnessExprLambda amap g m (traitInfo: TraitConstraintInfo) = | Some expr -> mkMemberLambdas m [] None None vsl (expr, tyOfExpr g expr) | None -> + assert ("A constraint witness could not be found for a built-in constraint solution" |> ignore; false) mkOne g m let GenWitnessArgs amap g m (traitInfos: TraitConstraintInfo list) = diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index 049ed0f854f..922e2205e1b 100755 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -716,7 +716,7 @@ module private PrintTypes = PrintIL.layoutILType denv [] ty ++ argsL /// Layout '[]' above another block - and layoutAttribs denv ty kind attrs restL = + and layoutAttribs denv isValue ty kind attrs restL = if denv.showAttributes then // Don't display DllImport attributes in generated signatures @@ -734,8 +734,9 @@ module private PrintTypes = | _ -> squareAngleL (sepListL (rightL (tagPunctuation ";")) (List.map (layoutAttrib denv) attrs)) @@ restL - elif Tastops.isStructRecordOrUnionTyconTy denv.g ty || - ((Tastops.isUnionTy denv.g ty || Tastops.isRecdTy denv.g ty) && HasFSharpAttribute denv.g denv.g.attrib_StructAttribute attrs) then + elif not isValue && + (Tastops.isStructRecordOrUnionTyconTy denv.g ty + || ((Tastops.isUnionTy denv.g ty || Tastops.isRecdTy denv.g ty) && HasFSharpAttribute denv.g denv.g.attrib_StructAttribute attrs)) then squareAngleL (wordL (tagClass "Struct")) @@ restL else match kind with @@ -1231,7 +1232,7 @@ module private PrintTastMemberOrVals = prettyTyparInst, resL | Some _ -> prettyLayoutOfMember denv typarInst v - prettyTyparInst, layoutAttribs denv v.Type TyparKind.Type v.Attribs vL + prettyTyparInst, layoutAttribs denv true v.Type TyparKind.Type v.Attribs vL let prettyLayoutOfValOrMemberNoInst denv v = prettyLayoutOfValOrMember denv emptyTyparInst v |> snd @@ -1807,7 +1808,7 @@ module private TastDefinitionPrinting = addMembersAsWithEnd (lhsL ^^ WordL.equals) | Some a -> (lhsL ^^ WordL.equals) --- (layoutType { denv with shortTypeNames = false } a) - layoutAttribs denv ty tycon.TypeOrMeasureKind tycon.Attribs reprL + layoutAttribs denv false ty tycon.TypeOrMeasureKind tycon.Attribs reprL // Layout: exception definition let layoutExnDefn denv (exnc: Entity) = diff --git a/src/fsharp/TastOps.fs b/src/fsharp/TastOps.fs index 9d4e52b6c99..8e7bb42f577 100644 --- a/src/fsharp/TastOps.fs +++ b/src/fsharp/TastOps.fs @@ -6669,13 +6669,13 @@ let mkCallGreaterThanOperator (g: TcGlobals) m ty e1 e2 = mkApps g (typedExprFor let mkCallGreaterThanOrEqualsOperator (g: TcGlobals) m ty e1 e2 = mkApps g (typedExprForIntrinsic g m g.greater_than_or_equals_operator, [[ty]], [ e1;e2 ], m) -let mkCallAdditionOperator (g: TcGlobals) m ty1 ty2 ty3 e1 e2 = mkApps g (typedExprForIntrinsic g m g.unchecked_addition_info, [[ty1; ty2; ty3]], [e1;e2], m) +let mkCallAdditionOperator (g: TcGlobals) m ty e1 e2 = mkApps g (typedExprForIntrinsic g m g.unchecked_addition_info, [[ty; ty; ty]], [e1;e2], m) let mkCallSubtractionOperator (g: TcGlobals) m ty e1 e2 = mkApps g (typedExprForIntrinsic g m g.unchecked_subtraction_info, [[ty; ty; ty]], [e1;e2], m) let mkCallMultiplyOperator (g: TcGlobals) m ty e1 e2 = mkApps g (typedExprForIntrinsic g m g.unchecked_multiply_info, [[ty; ty; ty]], [e1;e2], m) -let mkCallDivisionOperator (g: TcGlobals) m ty1 ty2 ty3 e1 e2 = mkApps g (typedExprForIntrinsic g m g.unchecked_division_info, [[ty1; ty2; ty3]], [e1;e2], m) +let mkCallDivisionOperator (g: TcGlobals) m ty e1 e2 = mkApps g (typedExprForIntrinsic g m g.unchecked_division_info, [[ty; ty; ty]], [e1;e2], m) let mkCallModulusOperator (g: TcGlobals) m ty e1 e2 = mkApps g (typedExprForIntrinsic g m g.unchecked_modulus_info, [[ty; ty; ty]], [e1;e2], m) @@ -6785,6 +6785,25 @@ let mkCallNewDecimal (g: TcGlobals) m (e1, e2, e3, e4, e5) = mkApps g (typedExpr let mkCallNewFormat (g: TcGlobals) m aty bty cty dty ety e1 = mkApps g (typedExprForIntrinsic g m g.new_format_info, [[aty;bty;cty;dty;ety]], [ e1 ], m) +let tryMkCallBuiltInWitness (g: TcGlobals) traitInfo argExprs m = + let info = g.makeBuiltInWitnessInfo traitInfo + let vref = ValRefForIntrinsic info + match vref.TryDeref with + | ValueSome v -> + let f = exprForValRef m vref + mkApps g ((f, v.Type), [], [ mkRefTupledNoTypes g m argExprs ], m) |> Some + | ValueNone -> + None + +let tryMkCallCoreFunctionAsBuiltInWitness (g: TcGlobals) info tyargs argExprs m = + let vref = ValRefForIntrinsic info + match vref.TryDeref with + | ValueSome v -> + let f = exprForValRef m vref + mkApps g ((f, v.Type), [tyargs], argExprs, m) |> Some + | ValueNone -> + None + let TryEliminateDesugaredConstants g m c = match c with | Const.Decimal d -> diff --git a/src/fsharp/TastOps.fsi b/src/fsharp/TastOps.fsi index dd7fb879d0b..d05447f6a18 100755 --- a/src/fsharp/TastOps.fsi +++ b/src/fsharp/TastOps.fsi @@ -1825,13 +1825,13 @@ val mkCallGreaterThanOperator : TcGlobals -> range -> TType -> Ex val mkCallGreaterThanOrEqualsOperator : TcGlobals -> range -> TType -> Expr -> Expr -> Expr -val mkCallAdditionOperator : TcGlobals -> range -> TType -> TType -> TType -> Expr -> Expr -> Expr +val mkCallAdditionOperator : TcGlobals -> range -> TType -> Expr -> Expr -> Expr val mkCallSubtractionOperator : TcGlobals -> range -> TType -> Expr -> Expr -> Expr val mkCallMultiplyOperator : TcGlobals -> range -> TType -> Expr -> Expr -> Expr -val mkCallDivisionOperator : TcGlobals -> range -> TType -> TType -> TType -> Expr -> Expr -> Expr +val mkCallDivisionOperator : TcGlobals -> range -> TType -> Expr -> Expr -> Expr val mkCallModulusOperator : TcGlobals -> range -> TType -> Expr -> Expr -> Expr @@ -1971,6 +1971,12 @@ val mkStaticCall_String_Concat4 : TcGlobals -> range -> Expr -> Expr -> Expr -> val mkStaticCall_String_Concat_Array : TcGlobals -> range -> Expr -> Expr +/// Use a witness in BuiltInWitnesses +val tryMkCallBuiltInWitness : TcGlobals -> TraitConstraintInfo -> Expr list -> range -> Expr option + +/// Use an operator as a witness +val tryMkCallCoreFunctionAsBuiltInWitness : TcGlobals -> IntrinsicValRef -> TType list -> Expr list -> range -> Expr option + //------------------------------------------------------------------------- // operations primarily associated with the optimization to fix // up loops to generate .NET code that does not include array bound checks diff --git a/src/fsharp/TcGlobals.fs b/src/fsharp/TcGlobals.fs index fd56558a41b..eb497958e5d 100755 --- a/src/fsharp/TcGlobals.fs +++ b/src/fsharp/TcGlobals.fs @@ -355,7 +355,7 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d // A table of all intrinsics that the compiler cares about let v_knownIntrinsics = Dictionary<(string*string), ValRef>(HashIdentity.Structural) - let makeIntrinsicValRef (enclosingEntity, logicalName, memberParentName, compiledNameOpt, typars, (argtys, rty)) = + let makeIntrinsicValRefGeneral overloaded (enclosingEntity, logicalName, memberParentName, compiledNameOpt, typars, (argtys, rty)) = let ty = mkForallTyIfNeeded typars (mkIteratedFunTy (List.map mkSmallRefTupledTy argtys) rty) let isMember = Option.isSome memberParentName let argCount = if isMember then List.sum (List.map List.length argtys) else 0 @@ -363,9 +363,12 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d let key = ValLinkageFullKey({ MemberParentMangledName=memberParentName; MemberIsOverride=false; LogicalName=logicalName; TotalArgCount= argCount }, linkageType) let vref = IntrinsicValRef(enclosingEntity, logicalName, isMember, ty, key) let compiledName = defaultArg compiledNameOpt logicalName - v_knownIntrinsics.Add((enclosingEntity.LastItemMangledName, compiledName), ValRefForIntrinsic vref) + if not overloaded then + v_knownIntrinsics.Add((enclosingEntity.LastItemMangledName, compiledName), ValRefForIntrinsic vref) vref + let makeIntrinsicValRef info = makeIntrinsicValRefGeneral false info + let makeOverloadedIntrinsicValRef info = makeIntrinsicValRefGeneral true info let v_IComparer_ty = mkSysNonGenericTy sysCollections "IComparer" let v_IEqualityComparer_ty = mkSysNonGenericTy sysCollections "IEqualityComparer" @@ -1488,6 +1491,58 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d member __.eraseClassUnionDef = EraseUnions.mkClassUnionDef (addMethodGeneratedAttrs, addPropertyGeneratedAttrs, addPropertyNeverAttrs, addFieldGeneratedAttrs, addFieldNeverAttrs, mkDebuggerTypeProxyAttribute) ilg + /// Find an FSharp.Core BuiltInWitness that corresponds to a trait witness + member g.makeBuiltInWitnessInfo (t: TraitConstraintInfo) = + makeOverloadedIntrinsicValRef (fslib_MFLanguagePrimitives_nleref, t.MemberName, Some "BuiltInWitnesses", None, [], ([t.ArgumentTypes], defaultArg t.ReturnType g.unit_ty)) + + /// Find an FSharp.Core operator that corresponds to a trait witness + member g.tryMakeOperatorAsBuiltInWitnessInfo isStringTy isArrayTy (t: TraitConstraintInfo) = + + match t.MemberName, t.ArgumentTypes, t.ReturnType with + | "Sign", [aty], _ -> + // Call Operators.sign + let info = makeIntrinsicValRef (fslib_MFOperators_nleref, "sign", None, Some "Sign", [vara], ([[varaTy]], v_int32_ty)) + let tyargs = [aty] + Some (info, tyargs) + | "Sqrt", [aty], Some bty -> + // Call Operators.sqrt + let info = makeIntrinsicValRef (fslib_MFOperators_nleref, "sqrt", None, Some "Sqrt", [vara; varb], ([[varaTy]], varbTy)) + let tyargs = [aty; bty] + Some (info, tyargs) + | "Pow", [aty;bty], _ -> + // Call Operators.(**) + let info = makeIntrinsicValRef (fslib_MFOperators_nleref, "op_Exponentiation", None, None, [vara; varb], ([[varaTy]; [varbTy]], varaTy)) + let tyargs = [aty;bty] + Some (info, tyargs) + | "Atan2", [aty;_], Some bty -> + // Call Operators.atan2 + let info = makeIntrinsicValRef (fslib_MFOperators_nleref, "atan2", None, Some "Atan2", [vara; varb], ([[varaTy]; [varaTy]], varbTy)) + let tyargs = [aty;bty] + Some (info, tyargs) + | "get_Zero", _, Some aty -> + // Call LanguagePrimitives.GenericZero + let info = makeIntrinsicValRef (fslib_MFLanguagePrimitives_nleref, "GenericZero", None, None, [vara], ([], varaTy)) + let tyargs = [aty] + Some (info, tyargs) + | "get_One", _, Some aty -> + // Call LanguagePrimitives.GenericOne + let info = makeIntrinsicValRef (fslib_MFLanguagePrimitives_nleref, "GenericOne", None, None, [vara], ([], varaTy)) + let tyargs = [aty] + Some (info, tyargs) + | ("Abs" | "Sin" | "Cos" | "Tan" | "Sinh" | "Cosh" | "Tanh" | "Atan" | "Acos" | "Asin" | "Exp" | "Ceiling" | "Floor" | "Round" | "Truncate" | "Log10"| "Log"), [aty], _ -> + // Call corresponding Operators.* + let nm = t.MemberName + let info = makeIntrinsicValRef (fslib_MFOperators_nleref, nm.ToLowerInvariant(), None, Some nm, [vara], ([[varaTy]], varaTy)) + let tyargs = [aty] + Some (info, tyargs) + | "get_Item", [arrTy; _], Some rty when isArrayTy g arrTy -> + Some (g.array_get_info, [rty]) + | "set_Item", [arrTy; _; ety], _ when isArrayTy g arrTy -> + Some (g.array_set_info, [ety]) + | "get_Item", [sty; _; _], _ when isStringTy g sty -> + Some (g.getstring_info, [] ) + | _ -> + None #if DEBUG // This global is only used during debug output diff --git a/src/fsharp/symbols/Exprs.fs b/src/fsharp/symbols/Exprs.fs index 7fecc87f1a9..fc50346f301 100644 --- a/src/fsharp/symbols/Exprs.fs +++ b/src/fsharp/symbols/Exprs.fs @@ -212,7 +212,7 @@ module FSharpExprConvert = let (|ILBinaryOp|_|) e = match e with - | AI_add -> Some (fun g m ty -> mkCallAdditionOperator g m ty ty ty) + | AI_add -> Some mkCallAdditionOperator | AI_add_ovf | AI_add_ovf_un -> Some mkCallAdditionChecked | AI_sub -> Some mkCallSubtractionOperator @@ -222,7 +222,7 @@ module FSharpExprConvert = | AI_mul_ovf | AI_mul_ovf_un -> Some mkCallMultiplyChecked | AI_div - | AI_div_un -> Some (fun g m ty -> mkCallDivisionOperator g m ty ty ty) + | AI_div_un -> Some mkCallDivisionOperator | AI_rem | AI_rem_un -> Some mkCallModulusOperator | AI_ceq -> Some mkCallEqualsOperator diff --git a/tests/fsharp/core/quotes/test.fsx b/tests/fsharp/core/quotes/test.fsx index d5ad0d762cf..6a638d8f781 100644 --- a/tests/fsharp/core/quotes/test.fsx +++ b/tests/fsharp/core/quotes/test.fsx @@ -3191,7 +3191,11 @@ module WitnessTests = (printfn "checking args.Length = %d... args.Length"; true) && args.Length = 2 && (printfn "checking witnessArgs is a Lambda..."; true) && - (match args with [ Lambda _ ] -> true | _ -> false) + (match witnessArgs with [ Lambda _ ] -> true | _ -> false) && + (printfn "checking witnessArg is the expected call..."; true) && + (match witnessArgs with [ Lambda (v1A, Lambda (v2A, Call(None, m, [ Patterns.Var v1B; Patterns.Var v2B]))) ] when m.Name = "op_Addition" && v1A = v1B && v2A = v2B -> true | _ -> false) + (printfn "checking witnessArg is not a CalWithWitnesses..."; true) && + (match witnessArgs with [ Lambda (v1A, Lambda (v2A, CallWithWitnesses _)) ] -> false | _ -> true) && (printfn "checking args..."; true) && (match args with [ Int32 _; Int32 _ ] -> true | _ -> false) | _ -> false) @@ -3206,8 +3210,19 @@ module WitnessTests = minfo2.Name = "op_AdditionWithWitnesses" && (printfn "checking minfo2.GetParameters().Length..."; true) && minfo2.GetParameters().Length = 3 && - (printfn "checking args.Length..."; true) && + (printfn "checking witnessArgs.Length..."; true) && witnessArgs.Length = 1 && + (printfn "checking witnessArg is the expected call, witnessArgs = %A" witnessArgs; true) && + (match witnessArgs with + | [ Lambda (v1A, Lambda (v2A, Call(None, m, [Patterns.Var v1B; Patterns.Var v2B]))) ] + when m.Name = "op_Addition" + && m.GetParameters().[0].ParameterType.Name = "DateTime" + && m.GetParameters().[1].ParameterType.Name = "TimeSpan" + && v1A = v1B + && v2A = v2B -> true + | _ -> false) + (printfn "checking witnessArg is not a CallWithWitnesses, witnessArgs = %A" witnessArgs; true) && + (match witnessArgs with [ Lambda (v1A, Lambda (v2A, CallWithWitnesses args)) ] -> printfn "unexpected! %A" args; false | _ -> true) && args.Length = 2 && (printfn "checking args..."; true) && (match args with [ _; _ ] -> true | _ -> false) && @@ -3300,8 +3315,8 @@ let aa = stdout.WriteLine "Test Passed" System.IO.File.WriteAllText("test.ok","ok") exit 0 - | _ -> - stdout.WriteLine "Test Failed" + | errs -> + printfn "Test Failed, errors = %A" errs exit 1 #endif diff --git a/tests/fsharpqa/Source/Printing/Quotation01.fs b/tests/fsharpqa/Source/Printing/Quotation01.fs index bf6ce9e2479..48aab89514f 100644 --- a/tests/fsharpqa/Source/Printing/Quotation01.fs +++ b/tests/fsharpqa/Source/Printing/Quotation01.fs @@ -1,7 +1,5 @@ // #NoMT #Printing // Regression test for FSHARP1.0:524 -//val it : Quotations.Expr = Value \(1\) {CustomAttributes = \[||\]; -// Raw = \.\.\.; -// Type = System\.Int32;} +//val it : Quotations.Expr = Value \(1\) <@ 1 @>;; exit 0;; From e11bafc6e893ed8c562f316fe60023184457aa4a Mon Sep 17 00:00:00 2001 From: Don Syme Date: Mon, 1 Apr 2019 23:23:47 +0100 Subject: [PATCH 50/77] fix up bugs in witnesses and expand testing --- src/fsharp/FSharp.Core/Linq.fs | 156 +++++++------- src/fsharp/FSharp.Core/prim-types.fs | 92 ++++----- src/fsharp/FSharp.Core/prim-types.fsi | 67 +++--- src/fsharp/IlxGen.fs | 14 +- src/fsharp/MethodCalls.fs | 6 +- src/fsharp/TastOps.fs | 6 +- src/fsharp/TcGlobals.fs | 68 +++---- tests/fsharp/core/quotes/test.fsx | 282 ++++++++++++++++++++++++++ 8 files changed, 495 insertions(+), 196 deletions(-) diff --git a/src/fsharp/FSharp.Core/Linq.fs b/src/fsharp/FSharp.Core/Linq.fs index 7a87af9492a..beaf5c25e07 100644 --- a/src/fsharp/FSharp.Core/Linq.fs +++ b/src/fsharp/FSharp.Core/Linq.fs @@ -502,91 +502,89 @@ module LeafExpressionConverter = let props = ctor.DeclaringType.GetProperties() Expression.New(ctor, argsR, [| for p in props -> (p :> MemberInfo) |]) |> asExpr - // Do the same thing as C# compiler for string addition | PlusQ (_, [ty1;ty2;ty3],[x1;x2]) when (ty1 = typeof) && (ty2 = typeof) && (ty3 = typeof) -> Expression.Add(ConvExprToLinqInContext env x1, ConvExprToLinqInContext env x2, StringConcat) |> asExpr - | GenericEqualityQ (_, _,[x1;x2]) - | EqualsQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.Equal - | NotEqQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.NotEqual - | GreaterQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.GreaterThan - | GreaterEqQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.GreaterThanOrEqual - | LessQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.LessThan - | LessEqQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.LessThanOrEqual + | GenericEqualityQ _ + | EqualsQ _ -> transBinOp env false args false Expression.Equal + | NotEqQ _ -> transBinOp env false args false Expression.NotEqual + | GreaterQ _ -> transBinOp env false args false Expression.GreaterThan + | GreaterEqQ _ -> transBinOp env false args false Expression.GreaterThanOrEqual + | LessQ _ -> transBinOp env false args false Expression.LessThan + | LessEqQ _ -> transBinOp env false args false Expression.LessThanOrEqual | NotQ (_, _, [x1]) -> Expression.Not(ConvExprToLinqInContext env x1) |> asExpr - | StaticEqualsQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.Equal - | StaticNotEqQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.NotEqual - | StaticGreaterQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.GreaterThan - | StaticGreaterEqQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.GreaterThanOrEqual - | StaticLessQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.LessThan - | StaticLessEqQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.LessThanOrEqual - - | NullableEqualsQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 true Expression.Equal - | NullableNotEqQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 true Expression.NotEqual - | NullableGreaterQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 true Expression.GreaterThan - | NullableGreaterEqQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 true Expression.GreaterThanOrEqual - | NullableLessQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 true Expression.LessThan - | NullableLessEqQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 true Expression.LessThanOrEqual - - | EqualsNullableQ (_, _,[x1;x2]) -> transBinOp env true x1 x2 false Expression.Equal - | NotEqNullableQ (_, _,[x1;x2]) -> transBinOp env true x1 x2 false Expression.NotEqual - | GreaterNullableQ (_, _,[x1;x2]) -> transBinOp env true x1 x2 false Expression.GreaterThan - | GreaterEqNullableQ (_, _,[x1;x2]) -> transBinOp env true x1 x2 false Expression.GreaterThanOrEqual - | LessNullableQ (_, _,[x1;x2]) -> transBinOp env true x1 x2 false Expression.LessThan - | LessEqNullableQ (_, _,[x1;x2]) -> transBinOp env true x1 x2 false Expression.LessThanOrEqual - - | NullableEqualsNullableQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.Equal - | NullableNotEqNullableQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.NotEqual - | NullableGreaterNullableQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.GreaterThan - | NullableGreaterEqNullableQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.GreaterThanOrEqual - | NullableLessNullableQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.LessThan - | NullableLessEqNullableQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.LessThanOrEqual + | StaticEqualsQ _ -> transBinOp env false args false Expression.Equal + | StaticNotEqQ _ -> transBinOp env false args false Expression.NotEqual + | StaticGreaterQ _ -> transBinOp env false args false Expression.GreaterThan + | StaticGreaterEqQ _ -> transBinOp env false args false Expression.GreaterThanOrEqual + | StaticLessQ _ -> transBinOp env false args false Expression.LessThan + | StaticLessEqQ _ -> transBinOp env false args false Expression.LessThanOrEqual + + | NullableEqualsQ _ -> transBinOp env false args true Expression.Equal + | NullableNotEqQ _ -> transBinOp env false args true Expression.NotEqual + | NullableGreaterQ _ -> transBinOp env false args true Expression.GreaterThan + | NullableGreaterEqQ _ -> transBinOp env false args true Expression.GreaterThanOrEqual + | NullableLessQ _ -> transBinOp env false args true Expression.LessThan + | NullableLessEqQ _ -> transBinOp env false args true Expression.LessThanOrEqual + + | EqualsNullableQ _ -> transBinOp env true args false Expression.Equal + | NotEqNullableQ _ -> transBinOp env true args false Expression.NotEqual + | GreaterNullableQ _ -> transBinOp env true args false Expression.GreaterThan + | GreaterEqNullableQ _ -> transBinOp env true args false Expression.GreaterThanOrEqual + | LessNullableQ _ -> transBinOp env true args false Expression.LessThan + | LessEqNullableQ _ -> transBinOp env true args false Expression.LessThanOrEqual + + | NullableEqualsNullableQ _ -> transBinOp env false args false Expression.Equal + | NullableNotEqNullableQ _ -> transBinOp env false args false Expression.NotEqual + | NullableGreaterNullableQ _ -> transBinOp env false args false Expression.GreaterThan + | NullableGreaterEqNullableQ _ -> transBinOp env false args false Expression.GreaterThanOrEqual + | NullableLessNullableQ _ -> transBinOp env false args false Expression.LessThan + | NullableLessEqNullableQ _ -> transBinOp env false args false Expression.LessThanOrEqual // Detect the F# quotation encoding of decimal literals | MakeDecimalQ (_, _, [Int32 lo; Int32 med; Int32 hi; Bool isNegative; Byte scale]) -> Expression.Constant(new System.Decimal(lo,med,hi,isNegative,scale)) |> asExpr | NegQ (_, _, [x1]) -> Expression.Negate(ConvExprToLinqInContext env x1) |> asExpr - | PlusQ (_, _,[x1;x2]) -> Expression.Add(ConvExprToLinqInContext env x1, ConvExprToLinqInContext env x2) |> asExpr - | DivideQ (_, _,[x1;x2]) -> Expression.Divide (ConvExprToLinqInContext env x1, ConvExprToLinqInContext env x2) |> asExpr - | MinusQ (_, _,[x1;x2]) -> Expression.Subtract(ConvExprToLinqInContext env x1, ConvExprToLinqInContext env x2) |> asExpr - | MultiplyQ (_, _,[x1;x2]) -> Expression.Multiply(ConvExprToLinqInContext env x1, ConvExprToLinqInContext env x2) |> asExpr - | ModuloQ (_, _,[x1;x2]) -> Expression.Modulo (ConvExprToLinqInContext env x1, ConvExprToLinqInContext env x2) |> asExpr - - | ShiftLeftQ (_, _,[x1;x2]) -> Expression.LeftShift(ConvExprToLinqInContext env x1, ConvExprToLinqInContext env x2) |> asExpr - | ShiftRightQ (_, _,[x1;x2]) -> Expression.RightShift(ConvExprToLinqInContext env x1, ConvExprToLinqInContext env x2) |> asExpr - | BitwiseAndQ (_, _,[x1;x2]) -> Expression.And(ConvExprToLinqInContext env x1, ConvExprToLinqInContext env x2) |> asExpr - | BitwiseOrQ (_, _,[x1;x2]) -> Expression.Or(ConvExprToLinqInContext env x1, ConvExprToLinqInContext env x2) |> asExpr - | BitwiseXorQ (_, _,[x1;x2]) -> Expression.ExclusiveOr(ConvExprToLinqInContext env x1, ConvExprToLinqInContext env x2) |> asExpr + | PlusQ _ -> transBinOp env false args false Expression.Add + | DivideQ _ -> transBinOp env false args false Expression.Divide + | MinusQ _ -> transBinOp env false args false Expression.Subtract + | MultiplyQ _ -> transBinOp env false args false Expression.Multiply + | ModuloQ _ -> transBinOp env false args false Expression.Modulo + + | ShiftLeftQ _ -> transBinOp env false args false Expression.LeftShift + | ShiftRightQ _ -> transBinOp env false args false Expression.RightShift + | BitwiseAndQ _ -> transBinOp env false args false Expression.And + | BitwiseOrQ _ -> transBinOp env false args false Expression.Or + | BitwiseXorQ _ -> transBinOp env false args false Expression.ExclusiveOr | BitwiseNotQ (_, _, [x1]) -> Expression.Not(ConvExprToLinqInContext env x1) |> asExpr - + | CheckedNeg (_, _, [x1]) -> Expression.NegateChecked(ConvExprToLinqInContext env x1) |> asExpr - | CheckedPlusQ (_, _,[x1;x2]) -> Expression.AddChecked(ConvExprToLinqInContext env x1, ConvExprToLinqInContext env x2) |> asExpr - | CheckedMinusQ (_, _,[x1;x2]) -> Expression.SubtractChecked(ConvExprToLinqInContext env x1, ConvExprToLinqInContext env x2) |> asExpr - | CheckedMultiplyQ (_, _,[x1;x2]) -> Expression.MultiplyChecked(ConvExprToLinqInContext env x1, ConvExprToLinqInContext env x2) |> asExpr - - - | NullablePlusQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 true Expression.Add - | PlusNullableQ (_, _,[x1;x2]) -> transBinOp env true x1 x2 false Expression.Add - | NullablePlusNullableQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.Add + | CheckedPlusQ _ -> transBinOp env false args false Expression.AddChecked + | CheckedMinusQ _ -> transBinOp env false args false Expression.SubtractChecked + | CheckedMultiplyQ _ -> transBinOp env false args false Expression.MultiplyChecked + + | NullablePlusQ _ -> transBinOp env false args true Expression.Add + | PlusNullableQ _ -> transBinOp env true args false Expression.Add + | NullablePlusNullableQ _ -> transBinOp env false args false Expression.Add - | NullableMinusQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 true Expression.Subtract - | MinusNullableQ (_, _,[x1;x2]) -> transBinOp env true x1 x2 false Expression.Subtract - | NullableMinusNullableQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.Subtract + | NullableMinusQ _ -> transBinOp env false args true Expression.Subtract + | MinusNullableQ _ -> transBinOp env true args false Expression.Subtract + | NullableMinusNullableQ _ -> transBinOp env false args false Expression.Subtract - | NullableMultiplyQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 true Expression.Multiply - | MultiplyNullableQ (_, _,[x1;x2]) -> transBinOp env true x1 x2 false Expression.Multiply - | NullableMultiplyNullableQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.Multiply + | NullableMultiplyQ _ -> transBinOp env false args true Expression.Multiply + | MultiplyNullableQ _ -> transBinOp env true args false Expression.Multiply + | NullableMultiplyNullableQ _ -> transBinOp env false args false Expression.Multiply - | NullableDivideQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 true Expression.Divide - | DivideNullableQ (_, _,[x1;x2]) -> transBinOp env true x1 x2 false Expression.Divide - | NullableDivideNullableQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.Divide + | NullableDivideQ _ -> transBinOp env false args true Expression.Divide + | DivideNullableQ _ -> transBinOp env true args false Expression.Divide + | NullableDivideNullableQ _ -> transBinOp env false args false Expression.Divide - | NullableModuloQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 true Expression.Modulo - | ModuloNullableQ (_, _,[x1;x2]) -> transBinOp env true x1 x2 false Expression.Modulo - | NullableModuloNullableQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.Modulo + | NullableModuloQ _ -> transBinOp env false args true Expression.Modulo + | ModuloNullableQ _ -> transBinOp env true args false Expression.Modulo + | NullableModuloNullableQ _ -> transBinOp env false args false Expression.Modulo | ConvNullableCharQ (_, _, [x1]) -> Expression.Convert(ConvExprToLinqInContext env x1, typeof>) |> asExpr | ConvNullableDecimalQ (_, _, [x1]) -> Expression.Convert(ConvExprToLinqInContext env x1, typeof>) |> asExpr @@ -645,6 +643,14 @@ module LeafExpressionConverter = // or type T to an argument expecting Expression. | ImplicitExpressionConversionHelperQ (_, [_], [x1]) -> ConvExprToLinqInContext env x1 + | CallWithWitnesses (objArgOpt, _, minfo2, witnessArgs, args) -> + let fullArgs = witnessArgs @ args + let replacementExpr = + match objArgOpt with + | None -> Expr.Call(minfo2, fullArgs) + | Some objArg -> Expr.Call(objArg, minfo2, fullArgs) + ConvExprToLinqInContext env replacementExpr + | _ -> let argsP = ConvExprsToLinq env args Expression.Call(ConvObjArg env objOpt None, minfo, argsP) |> asExpr @@ -797,13 +803,15 @@ module LeafExpressionConverter = | _ -> raise (new NotSupportedException(Printf.sprintf "Could not convert the following F# Quotation to a LINQ Expression Tree\n--------\n%A\n-------------\n" inp)) - and transBinOp env addConvertLeft x1 x2 addConvertRight (exprErasedConstructor : _ * _ -> _) = - let e1 = ConvExprToLinqInContext env x1 - let e2 = ConvExprToLinqInContext env x2 - let e1 = if addConvertLeft then Expression.Convert(e1, typedefof>.MakeGenericType [| e1.Type |]) |> asExpr else e1 - let e2 = if addConvertRight then Expression.Convert(e2, typedefof>.MakeGenericType [| e2.Type |]) |> asExpr else e2 - exprErasedConstructor(e1, e2) |> asExpr - + and transBinOp env addConvertLeft args addConvertRight (exprErasedConstructor : _ * _ -> _) = + match args with + | [x1; x2] -> + let e1 = ConvExprToLinqInContext env x1 + let e2 = ConvExprToLinqInContext env x2 + let e1 = if addConvertLeft then Expression.Convert(e1, typedefof>.MakeGenericType [| e1.Type |]) |> asExpr else e1 + let e2 = if addConvertRight then Expression.Convert(e2, typedefof>.MakeGenericType [| e2.Type |]) |> asExpr else e2 + exprErasedConstructor(e1, e2) |> asExpr + | _ -> raise (new NotSupportedException(Printf.sprintf "unexpected missing args in binary operator")) and ConvObjArg env objOpt coerceTo : Expression = match objOpt with diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index a53ceebc172..fd22ed6df8e 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -393,8 +393,8 @@ namespace Microsoft.FSharp.Core member inline this.IsSealed = this.GetTypeInfo().IsSealed member inline this.IsAssignableFrom(otherType: Type) = this.GetTypeInfo().IsAssignableFrom(otherType.GetTypeInfo()) member inline this.GetGenericArguments() = this.GetTypeInfo().GenericTypeArguments - member inline this.GetProperty(name) = this.GetRuntimeProperty(name) - member inline this.GetMethod(name, parameterTypes) = this.GetRuntimeMethod(name, parameterTypes) + member inline this.GetProperty(name) = this.GetTypeInfo().GetProperty(name) + member inline this.GetMethod(name:string, parameterTypes: Type[]) = this.GetTypeInfo().GetMethod(name, parameterTypes) member inline this.GetCustomAttributes(attributeType: Type, inherits: bool) : obj[] = unboxPrim<_> (box (CustomAttributeExtensions.GetCustomAttributes(this.GetTypeInfo(), attributeType, inherits).ToArray())) @@ -2612,75 +2612,75 @@ namespace Microsoft.FSharp.Core static member inline op_LeftShift(value: sbyte, shift: int32) = (# "conv.i1" (# "shl" value (mask shift 7) : int32 #) : sbyte #) static member inline op_LeftShift(value: byte, shift: int32) = (# "conv.u1" (# "shl" value (mask shift 7) : uint32 #) : byte #) + static member inline op_RightShift(value: sbyte, shift: int32) = (# "conv.i1" (# "shr" value (mask shift 7 ) : int32 #) : sbyte #) + static member inline op_RightShift(value: byte, shift: int32) = (# "conv.u1" (# "shr.un" value (mask shift 7 ) : uint32 #) : byte #) + static member inline op_RightShift(value: int16, shift: int32) = (# "conv.i2" (# "shr" value (mask shift 15) : int32 #) : int16 #) + static member inline op_RightShift(value: uint16, shift: int32) = (# "conv.u2" (# "shr.un" value (mask shift 15) : uint32 #) : uint16 #) static member inline op_RightShift(value: int32, shift: int32) = (# "shr" value (mask shift 31) : int32 #) static member inline op_RightShift(value: uint32, shift: int32) = (# "shr.un" value (mask shift 31) : uint32 #) static member inline op_RightShift(value: int64, shift: int32) = (# "shr" value (mask shift 63) : int64 #) static member inline op_RightShift(value: uint64, shift: int32) = (# "shr.un" value (mask shift 63) : uint64 #) static member inline op_RightShift(value: nativeint, shift: int32) = (# "shr" value shift : nativeint #) static member inline op_RightShift(value: unativeint, shift: int32) = (# "shr.un" value shift : unativeint #) - static member inline op_RightShift(value: int16, shift: int32) = (# "conv.i2" (# "shr" value (mask shift 15) : int32 #) : int16 #) - static member inline op_RightShift(value: uint16, shift: int32) = (# "conv.u2" (# "shr.un" value (mask shift 15) : uint32 #) : uint16 #) - static member inline op_RightShift(value: sbyte, shift: int32) = (# "conv.i1" (# "shr" value (mask shift 7 ) : int32 #) : sbyte #) - static member inline op_RightShift(value: byte, shift: int32) = (# "conv.u1" (# "shr.un" value (mask shift 7 ) : uint32 #) : byte #) + static member inline op_BitwiseAnd(x: sbyte, y: sbyte) = (# "and" x y : sbyte #) + static member inline op_BitwiseAnd(x: byte, y: byte) = (# "and" x y : byte #) + static member inline op_BitwiseAnd(x: int16, y: int16) = (# "and" x y : int16 #) + static member inline op_BitwiseAnd(x: uint16, y: uint16) = (# "and" x y : uint16 #) static member inline op_BitwiseAnd(x: int32, y: int32) = (# "and" x y : int32 #) + static member inline op_BitwiseAnd(x: uint32, y: uint32) = (# "and" x y : uint32 #) static member inline op_BitwiseAnd(x: int64, y: int64) = (# "and" x y : int64 #) static member inline op_BitwiseAnd(x: uint64, y: uint64) = (# "and" x y : uint64 #) - static member inline op_BitwiseAnd(x: uint32, y: uint32) = (# "and" x y : uint32 #) - static member inline op_BitwiseAnd(x: int16, y: int16) = (# "and" x y : int16 #) - static member inline op_BitwiseAnd(x: uint16, y: uint16) = (# "and" x y : uint16 #) static member inline op_BitwiseAnd(x: nativeint, y: nativeint) = (# "and" x y : nativeint #) static member inline op_BitwiseAnd(x: unativeint, y: unativeint) = (# "and" x y : unativeint #) - static member inline op_BitwiseAnd(x: sbyte, y: sbyte) = (# "and" x y : sbyte #) - static member inline op_BitwiseAnd(x: byte, y: byte) = (# "and" x y : byte #) + static member inline op_BitwiseOr(x: sbyte, y: sbyte) = (# "or" x y : sbyte #) + static member inline op_BitwiseOr(x: byte, y: byte) = (# "or" x y : byte #) + static member inline op_BitwiseOr(x: int16, y: int16) = (# "or" x y : int16 #) + static member inline op_BitwiseOr(x: uint16, y: uint16) = (# "or" x y : uint16 #) static member inline op_BitwiseOr(x: int32, y: int32) = (# "or" x y : int32 #) + static member inline op_BitwiseOr(x: uint32, y: uint32) = (# "or" x y : uint32 #) static member inline op_BitwiseOr(x: int64, y: int64) = (# "or" x y : int64 #) static member inline op_BitwiseOr(x: uint64, y: uint64) = (# "or" x y : uint64 #) - static member inline op_BitwiseOr(x: uint32, y: uint32) = (# "or" x y : uint32 #) - static member inline op_BitwiseOr(x: int16, y: int16) = (# "or" x y : int16 #) - static member inline op_BitwiseOr(x: uint16, y: uint16) = (# "or" x y : uint16 #) static member inline op_BitwiseOr(x: nativeint, y: nativeint) = (# "or" x y : nativeint #) static member inline op_BitwiseOr(x: unativeint, y: unativeint) = (# "or" x y : unativeint #) - static member inline op_BitwiseOr(x: sbyte, y: sbyte) = (# "or" x y : sbyte #) - static member inline op_BitwiseOr(x: byte, y: byte) = (# "or" x y : byte #) - static member inline op_BitwiseExclusiveOr(x: int32, y: int32) = (# "xor" x y : int32 #) - static member inline op_BitwiseExclusiveOr(x: int64, y: int64) = (# "xor" x y : int64 #) - static member inline op_BitwiseExclusiveOr(x: uint64, y: uint64) = (# "xor" x y : uint64 #) - static member inline op_BitwiseExclusiveOr(x: uint32, y: uint32) = (# "xor" x y : uint32 #) - static member inline op_BitwiseExclusiveOr(x: int16, y: int16) = (# "xor" x y : int16 #) - static member inline op_BitwiseExclusiveOr(x: uint16, y: uint16) = (# "xor" x y : uint16 #) - static member inline op_BitwiseExclusiveOr(x: nativeint, y: nativeint) = (# "xor" x y : nativeint #) - static member inline op_BitwiseExclusiveOr(x: unativeint, y: unativeint) = (# "xor" x y : unativeint #) - static member inline op_BitwiseExclusiveOr(x: sbyte, y: sbyte) = (# "xor" x y : sbyte #) - static member inline op_BitwiseExclusiveOr(x: byte, y: byte) = (# "xor" x y : byte #) + static member inline op_ExclusiveOr(x: sbyte, y: sbyte) = (# "xor" x y : sbyte #) + static member inline op_ExclusiveOr(x: byte, y: byte) = (# "xor" x y : byte #) + static member inline op_ExclusiveOr(x: int16, y: int16) = (# "xor" x y : int16 #) + static member inline op_ExclusiveOr(x: uint16, y: uint16) = (# "xor" x y : uint16 #) + static member inline op_ExclusiveOr(x: int32, y: int32) = (# "xor" x y : int32 #) + static member inline op_ExclusiveOr(x: uint32, y: uint32) = (# "xor" x y : uint32 #) + static member inline op_ExclusiveOr(x: int64, y: int64) = (# "xor" x y : int64 #) + static member inline op_ExclusiveOr(x: uint64, y: uint64) = (# "xor" x y : uint64 #) + static member inline op_ExclusiveOr(x: nativeint, y: nativeint) = (# "xor" x y : nativeint #) + static member inline op_ExclusiveOr(x: unativeint, y: unativeint) = (# "xor" x y : unativeint #) + static member inline op_LogicalNot(value: sbyte) = (# "conv.i1" (# "not" value : int32 #) : sbyte #) + static member inline op_LogicalNot(value: byte) = (# "conv.u1" (# "not" value : uint32 #) : byte #) + static member inline op_LogicalNot(value: int16) = (# "conv.i2" (# "not" value : int32 #) : int16 #) + static member inline op_LogicalNot(value: uint16) = (# "conv.u2" (# "not" value : uint32 #) : uint16 #) static member inline op_LogicalNot(value: int32) = (# "not" value : int32 #) + static member inline op_LogicalNot(value: uint32) = (# "not" value : uint32 #) static member inline op_LogicalNot(value: int64) = (# "not" value : int64 #) static member inline op_LogicalNot(value: uint64) = (# "not" value : uint64 #) - static member inline op_LogicalNot(value: uint32) = (# "not" value : uint32 #) static member inline op_LogicalNot(value: nativeint) = (# "not" value : nativeint #) static member inline op_LogicalNot(value: unativeint) = (# "not" value : unativeint #) - static member inline op_LogicalNot(value: int16) = (# "conv.i2" (# "not" value : int32 #) : int16 #) - static member inline op_LogicalNot(value: uint16) = (# "conv.u2" (# "not" value : uint32 #) : uint16 #) - static member inline op_LogicalNot(value: sbyte) = (# "conv.i1" (# "not" value : int32 #) : sbyte #) - static member inline op_LogicalNot(value: byte) = (# "conv.u1" (# "not" value : uint32 #) : byte #) - static member inline op_Explicit(value: string) : byte = ParseByte value - static member inline op_Explicit(value: float) : byte = (# "conv.u1" value : byte #) - static member inline op_Explicit(value: float32) : byte = (# "conv.u1" value : byte #) - static member inline op_Explicit(value: int64) : byte = (# "conv.u1" value : byte #) - static member inline op_Explicit(value: int32) : byte = (# "conv.u1" value : byte #) - static member inline op_Explicit(value: int16) : byte = (# "conv.u1" value : byte #) - static member inline op_Explicit(value: nativeint) : byte = (# "conv.u1" value : byte #) static member inline op_Explicit(value: sbyte) : byte = (# "conv.u1" value : byte #) - static member inline op_Explicit(value: uint64) : byte = (# "conv.u1" value : byte #) - static member inline op_Explicit(value: uint32) : byte = (# "conv.u1" value : byte #) + static member inline op_Explicit(value: byte) : byte = (# "conv.u1" value : byte #) + static member inline op_Explicit(value: int16) : byte = (# "conv.u1" value : byte #) static member inline op_Explicit(value: uint16) : byte = (# "conv.u1" value : byte #) - static member inline op_Explicit(value: char) : byte = (# "conv.u1" value : byte #) + static member inline op_Explicit(value: int32) : byte = (# "conv.u1" value : byte #) + static member inline op_Explicit(value: uint32) : byte = (# "conv.u1" value : byte #) + static member inline op_Explicit(value: int64) : byte = (# "conv.u1" value : byte #) + static member inline op_Explicit(value: uint64) : byte = (# "conv.u1" value : byte #) + static member inline op_Explicit(value: nativeint) : byte = (# "conv.u1" value : byte #) static member inline op_Explicit(value: unativeint) : byte = (# "conv.u1" value : byte #) - static member inline op_Explicit(value: byte) : byte = (# "conv.u1" value : byte #) + static member inline op_Explicit(value: float) : byte = (# "conv.u1" value : byte #) + static member inline op_Explicit(value: float32) : byte = (# "conv.u1" value : byte #) + static member inline op_Explicit(value: char) : byte = (# "conv.u1" value : byte #) + static member inline op_Explicit(value: string) : byte = ParseByte value static member inline op_Explicit(value: string) : sbyte = ParseSByte value static member inline op_Explicit(value: float) : sbyte = (# "conv.i1" value : sbyte #) @@ -3002,7 +3002,7 @@ namespace Microsoft.FSharp.Core elif aty.Equals(typeof) then unboxPrim<'T> (box 0.0) elif aty.Equals(typeof) then unboxPrim<'T> (box 0.0f) else - let pinfo = aty.GetProperty("Zero") + let pinfo = aty.GetTypeInfo().GetProperty("Zero") unboxPrim<'T> (pinfo.GetValue(null,null)) static member Result : 'T = result @@ -3026,7 +3026,7 @@ namespace Microsoft.FSharp.Core elif aty.Equals(typeof) then unboxPrim<'T> (box 1.0) elif aty.Equals(typeof) then unboxPrim<'T> (box 1.0f) else - let pinfo = aty.GetProperty("One") + let pinfo = aty.GetTypeInfo().GetProperty("One") unboxPrim<'T> (pinfo.GetValue(null,null)) static member Result : 'T = result @@ -3098,7 +3098,7 @@ namespace Microsoft.FSharp.Core //let staticBindingFlags = (BindingFlags.Static ||| BindingFlags.Public ||| BindingFlags.NonPublic) let opNameMeth = typeof<'OpInfo>.GetRuntimeMethod("get_Name", [| |] (*, staticBindingFlags, [| |], null*) ) let opName = opNameMeth.Invoke(null, [| |]) :?> string - let builtinNameMeth = typeof<'OpInfo>.GetRuntimeMethod("get_BuiltInName", (* staticBindingFlags, *) [| |] (*, null *) ) + let builtinNameMeth = typeof<'OpInfo>.GetTypeInfo().GetMethod("get_BuiltInName", (* staticBindingFlags, *) [| |] (*, null *) ) let builtinName = match builtinNameMeth with null -> opName | _ -> builtinNameMeth.Invoke(null, [| |]) :?> string let meth = @@ -3207,7 +3207,7 @@ namespace Microsoft.FSharp.Core type OpBitwiseOrInfo = static member Name = "op_BitwiseOr" let OpBitwiseOrDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y - type OpBitwiseExclusiveOrInfo = static member Name = "op_BitwiseExclusiveOr" + type OpBitwiseExclusiveOrInfo = static member Name = "op_ExclusiveOr" let OpBitwiseExclusiveOrDynamic<'T,'U,'V> x y = BinaryOpDynamicImplTable.Impl x y type OpLogicalNotInfo = static member Name = "op_LogicalNot" diff --git a/src/fsharp/FSharp.Core/prim-types.fsi b/src/fsharp/FSharp.Core/prim-types.fsi index e5139a7a03d..ee320825f89 100644 --- a/src/fsharp/FSharp.Core/prim-types.fsi +++ b/src/fsharp/FSharp.Core/prim-types.fsi @@ -1405,64 +1405,64 @@ namespace Microsoft.FSharp.Core static member inline op_Modulus: x: decimal * y: decimal -> decimal /// A representative witness for traits solved by the F# compiler - static member inline op_LeftShift: value: int32 * shift: int32 -> int32 + static member inline op_LeftShift: value: int32 * shift: int -> int32 /// A representative witness for traits solved by the F# compiler - static member inline op_LeftShift: value: uint32 * shift: int32 -> uint32 + static member inline op_LeftShift: value: uint32 * shift: int -> uint32 /// A representative witness for traits solved by the F# compiler - static member inline op_LeftShift: value: int64 * shift: int32 -> int64 + static member inline op_LeftShift: value: int64 * shift: int -> int64 /// A representative witness for traits solved by the F# compiler - static member inline op_LeftShift: value: uint64 * shift: int32 -> uint64 + static member inline op_LeftShift: value: uint64 * shift: int -> uint64 /// A representative witness for traits solved by the F# compiler - static member inline op_LeftShift: value: nativeint * shift: int32 -> nativeint + static member inline op_LeftShift: value: nativeint * shift: int -> nativeint /// A representative witness for traits solved by the F# compiler - static member inline op_LeftShift: value: unativeint * shift: int32 -> unativeint + static member inline op_LeftShift: value: unativeint * shift: int -> unativeint /// A representative witness for traits solved by the F# compiler - static member inline op_LeftShift: value: int16 * shift: int32 -> int16 + static member inline op_LeftShift: value: int16 * shift: int -> int16 /// A representative witness for traits solved by the F# compiler - static member inline op_LeftShift: value: uint16 * shift: int32 -> uint16 + static member inline op_LeftShift: value: uint16 * shift: int -> uint16 /// A representative witness for traits solved by the F# compiler - static member inline op_LeftShift: value: sbyte * shift: int32 -> sbyte + static member inline op_LeftShift: value: sbyte * shift: int -> sbyte /// A representative witness for traits solved by the F# compiler - static member inline op_LeftShift: value: byte * shift: int32 -> byte + static member inline op_LeftShift: value: byte * shift: int -> byte /// A representative witness for traits solved by the F# compiler - static member inline op_RightShift: value: byte * shift: int32 -> byte + static member inline op_RightShift: value: byte * shift: int -> byte /// A representative witness for traits solved by the F# compiler - static member inline op_RightShift: value: uint32 * shift: int32 -> uint32 + static member inline op_RightShift: value: sbyte * shift: int -> sbyte /// A representative witness for traits solved by the F# compiler - static member inline op_RightShift: value: int64 * shift: int32 -> int64 + static member inline op_RightShift: value: int16 * shift: int -> int16 /// A representative witness for traits solved by the F# compiler - static member inline op_RightShift: value: uint64 * shift: int32 -> uint64 + static member inline op_RightShift: value: uint16 * shift: int -> uint16 /// A representative witness for traits solved by the F# compiler - static member inline op_RightShift: value: nativeint * shift: int32 -> nativeint + static member inline op_RightShift: value: int32 * shift: int -> int32 /// A representative witness for traits solved by the F# compiler - static member inline op_RightShift: value: unativeint * shift: int32 -> unativeint + static member inline op_RightShift: value: uint32 * shift: int -> uint32 /// A representative witness for traits solved by the F# compiler - static member inline op_RightShift: value: int16 * shift: int32 -> int16 + static member inline op_RightShift: value: int64 * shift: int -> int64 /// A representative witness for traits solved by the F# compiler - static member inline op_RightShift: value: uint16 * shift: int32 -> uint16 + static member inline op_RightShift: value: uint64 * shift: int -> uint64 /// A representative witness for traits solved by the F# compiler - static member inline op_RightShift: value: sbyte * shift: int32 -> sbyte + static member inline op_RightShift: value: nativeint * shift: int -> nativeint /// A representative witness for traits solved by the F# compiler - static member inline op_RightShift: value: byte * shift: int32 -> byte + static member inline op_RightShift: value: unativeint * shift: int -> unativeint /// A representative witness for traits solved by the F# compiler static member inline op_BitwiseAnd: x: int32 * y: int32 -> int32 @@ -1525,34 +1525,34 @@ namespace Microsoft.FSharp.Core static member inline op_BitwiseOr: x: byte * y: byte -> byte /// A representative witness for traits solved by the F# compiler - static member inline op_BitwiseExclusiveOr: x: int32 * y: int32 -> int32 + static member inline op_ExclusiveOr: x: int32 * y: int32 -> int32 /// A representative witness for traits solved by the F# compiler - static member inline op_BitwiseExclusiveOr: x: int64 * y: int64 -> int64 + static member inline op_ExclusiveOr: x: int64 * y: int64 -> int64 /// A representative witness for traits solved by the F# compiler - static member inline op_BitwiseExclusiveOr: x: uint64 * y: uint64 -> uint64 + static member inline op_ExclusiveOr: x: uint64 * y: uint64 -> uint64 /// A representative witness for traits solved by the F# compiler - static member inline op_BitwiseExclusiveOr: x: uint32 * y: uint32 -> uint32 + static member inline op_ExclusiveOr: x: uint32 * y: uint32 -> uint32 /// A representative witness for traits solved by the F# compiler - static member inline op_BitwiseExclusiveOr: x: int16 * y: int16 -> int16 + static member inline op_ExclusiveOr: x: int16 * y: int16 -> int16 /// A representative witness for traits solved by the F# compiler - static member inline op_BitwiseExclusiveOr: x: uint16 * y: uint16 -> uint16 + static member inline op_ExclusiveOr: x: uint16 * y: uint16 -> uint16 /// A representative witness for traits solved by the F# compiler - static member inline op_BitwiseExclusiveOr: x: nativeint * y: nativeint -> nativeint + static member inline op_ExclusiveOr: x: nativeint * y: nativeint -> nativeint /// A representative witness for traits solved by the F# compiler - static member inline op_BitwiseExclusiveOr: x: unativeint * y: unativeint -> unativeint + static member inline op_ExclusiveOr: x: unativeint * y: unativeint -> unativeint /// A representative witness for traits solved by the F# compiler - static member inline op_BitwiseExclusiveOr: x: sbyte * y: sbyte -> sbyte + static member inline op_ExclusiveOr: x: sbyte * y: sbyte -> sbyte /// A representative witness for traits solved by the F# compiler - static member inline op_BitwiseExclusiveOr: x: byte * y: byte -> byte + static member inline op_ExclusiveOr: x: byte * y: byte -> byte /// A representative witness for traits solved by the F# compiler static member inline op_LogicalNot: value: int32 -> int32 @@ -1622,10 +1622,13 @@ namespace Microsoft.FSharp.Core /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: unativeint -> byte - + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: byte -> byte + /// A representative witness for traits solved by the F# compiler + static member inline op_Explicit: value: string -> sbyte + /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: byte -> sbyte @@ -1882,7 +1885,7 @@ namespace Microsoft.FSharp.Core static member inline op_Explicit: value: string -> int64 /// A representative witness for traits solved by the F# compiler - static member inline op_Explicit: value: string -> int64 + static member inline op_Explicit: value: float -> int64 /// A representative witness for traits solved by the F# compiler static member inline op_Explicit: value: float32 -> int64 diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 25e92fd8680..2cec8ded4b7 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -3788,9 +3788,10 @@ and MakeNotSupportedExnExpr cenv eenv (argExpr, m) = let mref = mkILCtorMethSpecForTy(ilty, [cenv.g.ilg.typ_String]).MethodRef Expr.Op(TOp.ILCall(false, false, false, true, NormalValUse, false, false, mref, [], [], [ety]), [], [argExpr], m) -and GenTraitCall cenv cgbuf eenv (traitInfo: TraitConstraintInfo, argExprs, m) expr sequel = +and GenTraitCall (cenv: cenv) cgbuf eenv (traitInfo: TraitConstraintInfo, argExprs, m) expr sequel = + let g = cenv.g let witness = - if cenv.g.generateWitnesses then + if g.generateWitnesses then match eenv.witnessesInScope.TryGetValue traitInfo.TraitKey with | true, storage -> Some storage | _ -> None @@ -3800,19 +3801,20 @@ and GenTraitCall cenv cgbuf eenv (traitInfo: TraitConstraintInfo, argExprs, m) e match witness with | Some storage -> - let ty = GenWitnessTy cenv.g traitInfo.TraitKey + let ty = GenWitnessTy g traitInfo.TraitKey + let argExprs = if argExprs.Length = 0 then [ mkUnit g m ] else argExprs GenGetStorageAndSequel cenv cgbuf eenv m (ty, GenType cenv.amap m eenv.tyenv ty) storage (Some([], argExprs, m, sequel)) | None -> // If witnesses are available, we should now always find trait witnesses in scope assert eenv.witnessesInScope.IsEmpty - let minfoOpt = CommitOperationResult (ConstraintSolver.CodegenWitnessForTraitConstraint cenv.tcVal cenv.g cenv.amap m traitInfo argExprs) + let minfoOpt = CommitOperationResult (ConstraintSolver.CodegenWitnessForTraitConstraint cenv.tcVal g cenv.amap m traitInfo argExprs) match minfoOpt with | None -> - let exnArg = mkString cenv.g m (FSComp.SR.ilDynamicInvocationNotSupported(traitInfo.MemberName)) + let exnArg = mkString g m (FSComp.SR.ilDynamicInvocationNotSupported(traitInfo.MemberName)) let exnExpr = MakeNotSupportedExnExpr cenv eenv (exnArg, m) - let replacementExpr = mkThrow m (tyOfExpr cenv.g expr) exnExpr + let replacementExpr = mkThrow m (tyOfExpr g expr) exnExpr GenExpr cenv cgbuf eenv SPSuppress replacementExpr sequel | Some expr -> let expr = cenv.optimizeDuringCodeGen expr diff --git a/src/fsharp/MethodCalls.fs b/src/fsharp/MethodCalls.fs index bc0c313f81b..b341ef57400 100644 --- a/src/fsharp/MethodCalls.fs +++ b/src/fsharp/MethodCalls.fs @@ -1426,9 +1426,9 @@ let GenWitnessExpr amap g m (traitInfo: TraitConstraintInfo) argExprs = | None -> None // the trait has been generalized | Some _-> // For these operators, the witness is just a call to the coresponding FSharp.Core operator - match g.tryMakeOperatorAsBuiltInWitnessInfo isStringTy isArrayTy traitInfo with - | Some (info, tyargs) -> - tryMkCallCoreFunctionAsBuiltInWitness g info tyargs argExprs m + match g.tryMakeOperatorAsBuiltInWitnessInfo isStringTy isArrayTy traitInfo argExprs with + | Some (info, tyargs, actualArgExprs) -> + tryMkCallCoreFunctionAsBuiltInWitness g info tyargs actualArgExprs m | None -> // For all other built-in operators, the witness is a call to the coresponding BuiltInWitnesses operator // These are called as F# methods not F# functions diff --git a/src/fsharp/TastOps.fs b/src/fsharp/TastOps.fs index 8e7bb42f577..d95e5d2ce64 100644 --- a/src/fsharp/TastOps.fs +++ b/src/fsharp/TastOps.fs @@ -2255,7 +2255,11 @@ let checkMemberValRef (vref: ValRef) = // Get information about the as-ye-unsolved constraints for a set of typars let GetTraitConstraintInfosOfTypars g (tps: Typars) = - let cxs = tps |> List.collect (fun tp -> tp.Constraints |> List.choose (fun cx -> match cx with TyparConstraint.MayResolveMember(traitInfo, _) -> Some traitInfo | _ -> None)) + let cxs = + tps |> List.collect (fun tp -> + tp.Constraints + |> List.choose (fun cx -> match cx with TyparConstraint.MayResolveMember(traitInfo, _) -> Some traitInfo | _ -> None) + |> List.sortBy (fun traitInfo -> traitInfo.MemberName, traitInfo.ArgumentTypes.Length)) let cxs = cxs |> ListSet.setify (traitsAEquiv g TypeEquivEnv.Empty) cxs diff --git a/src/fsharp/TcGlobals.fs b/src/fsharp/TcGlobals.fs index eb497958e5d..9e7cf1f7a86 100755 --- a/src/fsharp/TcGlobals.fs +++ b/src/fsharp/TcGlobals.fs @@ -355,7 +355,7 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d // A table of all intrinsics that the compiler cares about let v_knownIntrinsics = Dictionary<(string*string), ValRef>(HashIdentity.Structural) - let makeIntrinsicValRefGeneral overloaded (enclosingEntity, logicalName, memberParentName, compiledNameOpt, typars, (argtys, rty)) = + let makeIntrinsicValRefGeneral isKnown (enclosingEntity, logicalName, memberParentName, compiledNameOpt, typars, (argtys, rty)) = let ty = mkForallTyIfNeeded typars (mkIteratedFunTy (List.map mkSmallRefTupledTy argtys) rty) let isMember = Option.isSome memberParentName let argCount = if isMember then List.sum (List.map List.length argtys) else 0 @@ -363,12 +363,12 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d let key = ValLinkageFullKey({ MemberParentMangledName=memberParentName; MemberIsOverride=false; LogicalName=logicalName; TotalArgCount= argCount }, linkageType) let vref = IntrinsicValRef(enclosingEntity, logicalName, isMember, ty, key) let compiledName = defaultArg compiledNameOpt logicalName - if not overloaded then + if isKnown then v_knownIntrinsics.Add((enclosingEntity.LastItemMangledName, compiledName), ValRefForIntrinsic vref) vref - let makeIntrinsicValRef info = makeIntrinsicValRefGeneral false info - let makeOverloadedIntrinsicValRef info = makeIntrinsicValRefGeneral true info + let makeIntrinsicValRef info = makeIntrinsicValRefGeneral true info + let makeOtherIntrinsicValRef info = makeIntrinsicValRefGeneral false info let v_IComparer_ty = mkSysNonGenericTy sysCollections "IComparer" let v_IEqualityComparer_ty = mkSysNonGenericTy sysCollections "IEqualityComparer" @@ -1493,54 +1493,54 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d /// Find an FSharp.Core BuiltInWitness that corresponds to a trait witness member g.makeBuiltInWitnessInfo (t: TraitConstraintInfo) = - makeOverloadedIntrinsicValRef (fslib_MFLanguagePrimitives_nleref, t.MemberName, Some "BuiltInWitnesses", None, [], ([t.ArgumentTypes], defaultArg t.ReturnType g.unit_ty)) + makeOtherIntrinsicValRef (fslib_MFLanguagePrimitives_nleref, t.MemberName, Some "BuiltInWitnesses", None, [], ([t.ArgumentTypes], defaultArg t.ReturnType g.unit_ty)) /// Find an FSharp.Core operator that corresponds to a trait witness - member g.tryMakeOperatorAsBuiltInWitnessInfo isStringTy isArrayTy (t: TraitConstraintInfo) = + member g.tryMakeOperatorAsBuiltInWitnessInfo isStringTy isArrayTy (t: TraitConstraintInfo) argExprs = - match t.MemberName, t.ArgumentTypes, t.ReturnType with - | "Sign", [aty], _ -> + match t.MemberName, t.ArgumentTypes, t.ReturnType, argExprs with + | "get_Sign", [aty], _, (objExpr :: _) -> // Call Operators.sign - let info = makeIntrinsicValRef (fslib_MFOperators_nleref, "sign", None, Some "Sign", [vara], ([[varaTy]], v_int32_ty)) + let info = makeOtherIntrinsicValRef (fslib_MFOperators_nleref, "sign", None, Some "Sign", [vara], ([[varaTy]], v_int32_ty)) let tyargs = [aty] - Some (info, tyargs) - | "Sqrt", [aty], Some bty -> + Some (info, tyargs, [objExpr]) + | "Sqrt", [aty], Some bty, [_] -> // Call Operators.sqrt - let info = makeIntrinsicValRef (fslib_MFOperators_nleref, "sqrt", None, Some "Sqrt", [vara; varb], ([[varaTy]], varbTy)) + let info = makeOtherIntrinsicValRef (fslib_MFOperators_nleref, "sqrt", None, Some "Sqrt", [vara; varb], ([[varaTy]], varbTy)) let tyargs = [aty; bty] - Some (info, tyargs) - | "Pow", [aty;bty], _ -> + Some (info, tyargs, argExprs) + | "Pow", [aty;bty], _, [_;_] -> // Call Operators.(**) - let info = makeIntrinsicValRef (fslib_MFOperators_nleref, "op_Exponentiation", None, None, [vara; varb], ([[varaTy]; [varbTy]], varaTy)) + let info = makeOtherIntrinsicValRef (fslib_MFOperators_nleref, "op_Exponentiation", None, None, [vara; varb], ([[varaTy]; [varbTy]], varaTy)) let tyargs = [aty;bty] - Some (info, tyargs) - | "Atan2", [aty;_], Some bty -> + Some (info, tyargs, argExprs) + | "Atan2", [aty;_], Some bty, [_;_] -> // Call Operators.atan2 - let info = makeIntrinsicValRef (fslib_MFOperators_nleref, "atan2", None, Some "Atan2", [vara; varb], ([[varaTy]; [varaTy]], varbTy)) + let info = makeOtherIntrinsicValRef (fslib_MFOperators_nleref, "atan2", None, Some "Atan2", [vara; varb], ([[varaTy]; [varaTy]], varbTy)) let tyargs = [aty;bty] - Some (info, tyargs) - | "get_Zero", _, Some aty -> + Some (info, tyargs, argExprs) + | "get_Zero", _, Some aty, [_] -> // Call LanguagePrimitives.GenericZero - let info = makeIntrinsicValRef (fslib_MFLanguagePrimitives_nleref, "GenericZero", None, None, [vara], ([], varaTy)) + let info = makeOtherIntrinsicValRef (fslib_MFLanguagePrimitives_nleref, "GenericZero", None, None, [vara], ([], varaTy)) let tyargs = [aty] - Some (info, tyargs) - | "get_One", _, Some aty -> + Some (info, tyargs, []) + | "get_One", _, Some aty, [_] -> // Call LanguagePrimitives.GenericOne - let info = makeIntrinsicValRef (fslib_MFLanguagePrimitives_nleref, "GenericOne", None, None, [vara], ([], varaTy)) + let info = makeOtherIntrinsicValRef (fslib_MFLanguagePrimitives_nleref, "GenericOne", None, None, [vara], ([], varaTy)) let tyargs = [aty] - Some (info, tyargs) - | ("Abs" | "Sin" | "Cos" | "Tan" | "Sinh" | "Cosh" | "Tanh" | "Atan" | "Acos" | "Asin" | "Exp" | "Ceiling" | "Floor" | "Round" | "Truncate" | "Log10"| "Log"), [aty], _ -> + Some (info, tyargs, []) + | ("Abs" | "Sin" | "Cos" | "Tan" | "Sinh" | "Cosh" | "Tanh" | "Atan" | "Acos" | "Asin" | "Exp" | "Ceiling" | "Floor" | "Round" | "Truncate" | "Log10"| "Log"), [aty], _, [_] -> // Call corresponding Operators.* let nm = t.MemberName - let info = makeIntrinsicValRef (fslib_MFOperators_nleref, nm.ToLowerInvariant(), None, Some nm, [vara], ([[varaTy]], varaTy)) + let info = makeOtherIntrinsicValRef (fslib_MFOperators_nleref, nm.ToLowerInvariant(), None, Some nm, [vara], ([[varaTy]], varaTy)) let tyargs = [aty] - Some (info, tyargs) - | "get_Item", [arrTy; _], Some rty when isArrayTy g arrTy -> - Some (g.array_get_info, [rty]) - | "set_Item", [arrTy; _; ety], _ when isArrayTy g arrTy -> - Some (g.array_set_info, [ety]) - | "get_Item", [sty; _; _], _ when isStringTy g sty -> - Some (g.getstring_info, [] ) + Some (info, tyargs, argExprs) + | "get_Item", [arrTy; _], Some rty, [_; _] when isArrayTy g arrTy -> + Some (g.array_get_info, [rty], argExprs) + | "set_Item", [arrTy; _; ety], _, [_; _; _] when isArrayTy g arrTy -> + Some (g.array_set_info, [ety], argExprs) + | "get_Item", [sty; _; _], _, [_; _] when isStringTy g sty -> + Some (g.getstring_info, [], argExprs) | _ -> None diff --git a/tests/fsharp/core/quotes/test.fsx b/tests/fsharp/core/quotes/test.fsx index 6a638d8f781..0d1fe46f517 100644 --- a/tests/fsharp/core/quotes/test.fsx +++ b/tests/fsharp/core/quotes/test.fsx @@ -3178,6 +3178,8 @@ module TestMatchBang = testSimpleMatchBang() module WitnessTests = + open FSharp.Data.UnitSystems.SI.UnitSymbols + test "check CallWithWitness" (<@ 1 + 1 @> |> function @@ -3300,6 +3302,286 @@ module WitnessTests = false | _ -> false) + test "check CallWithWitnesses all operators)" + (let tests = + [ <@@ sin 1.0 @@>, true + <@@ sin 1.0f @@>, true + <@@ sign 1.0f @@>, true + <@@ sqrt 1.0f @@>, true + <@@ 2.0f ** 2.0f @@>, true + <@@ atan2 3.0 4.0 @@>, true + <@@ 1.0f + 4.0f @@>, true + <@@ 1.0f - 4.0f @@>, true + <@@ 1.0f * 4.0f @@>, true + <@@ 1.0M * 4.0M @@>, true + <@@ 1.0f / 4.0f @@>, true + <@@ 1 % 4 @@>, true + <@@ -(4.0M) @@>, true + + <@@ 1y <<< 3 @@>, true + <@@ 1uy <<< 3 @@>, true + <@@ 1s <<< 3 @@>, true + <@@ 1us <<< 3 @@>, true + <@@ 1 <<< 3 @@>, true + <@@ 1u <<< 3 @@>, true + <@@ 1L <<< 3 @@>, true + <@@ 1UL <<< 3 @@>, true + <@@ LanguagePrimitives.GenericOne <<< 3 @@>, false + <@@ LanguagePrimitives.GenericOne <<< 3 @@>, false + + <@@ 1y >>> 3 @@>, true + <@@ 1uy >>> 3 @@>, true + <@@ 1s >>> 3 @@>, true + <@@ 1us >>> 3 @@>, true + <@@ 1 >>> 3 @@>, true + <@@ 1u >>> 3 @@>, true + <@@ 1L >>> 3 @@>, true + <@@ 1UL >>> 3 @@>, true + <@@ LanguagePrimitives.GenericOne >>> 3 @@>, false + <@@ LanguagePrimitives.GenericOne >>> 3 @@>, false + + <@@ 1y &&& 3y @@>, true + <@@ 1uy &&& 3uy @@>, true + <@@ 1s &&& 3s @@>, true + <@@ 1us &&& 3us @@>, true + <@@ 1 &&& 3 @@>, true + <@@ 1u &&& 3u @@>, true + <@@ 1L &&& 3L @@>, true + <@@ 1UL &&& 3UL @@>, true + <@@ LanguagePrimitives.GenericOne &&& LanguagePrimitives.GenericOne @@>, false + <@@ LanguagePrimitives.GenericOne &&& LanguagePrimitives.GenericOne @@>, false + + <@@ 1y ||| 3y @@>, true + <@@ 1uy ||| 3uy @@>, true + <@@ 1s ||| 3s @@>, true + <@@ 1us ||| 3us @@>, true + <@@ 1 ||| 3 @@>, true + <@@ 1u ||| 3u @@>, true + <@@ 1L ||| 3L @@>, true + <@@ 1UL ||| 3UL @@>, true + <@@ LanguagePrimitives.GenericOne ||| LanguagePrimitives.GenericOne @@>, false + <@@ LanguagePrimitives.GenericOne ||| LanguagePrimitives.GenericOne @@>, false + + <@@ 1y ^^^ 3y @@>, true + <@@ 1uy ^^^ 3uy @@>, true + <@@ 1s ^^^ 3s @@>, true + <@@ 1us ^^^ 3us @@>, true + <@@ 1 ^^^ 3 @@>, true + <@@ 1u ^^^ 3u @@>, true + <@@ 1L ^^^ 3L @@>, true + <@@ 1UL ^^^ 3UL @@>, true + <@@ LanguagePrimitives.GenericOne ^^^ LanguagePrimitives.GenericOne @@>, false + <@@ LanguagePrimitives.GenericOne ^^^ LanguagePrimitives.GenericOne @@>, false + + <@@ ~~~3y @@>, true + <@@ ~~~3uy @@>, true + <@@ ~~~3s @@>, true + <@@ ~~~3us @@>, true + <@@ ~~~3 @@>, true + <@@ ~~~3u @@>, true + <@@ ~~~3L @@>, true + <@@ ~~~3UL @@>, true + <@@ ~~~LanguagePrimitives.GenericOne @@>, false + <@@ ~~~LanguagePrimitives.GenericOne @@>, false + + <@@ byte 3uy @@>, true + <@@ byte 3y @@>, true + <@@ byte 3s @@>, true + <@@ byte 3us @@>, true + <@@ byte 3 @@>, true + <@@ byte 3u @@>, true + <@@ byte 3L @@>, true + <@@ byte 3UL @@>, true + <@@ byte 3.0f @@>, true + <@@ byte 3.0 @@>, true + <@@ byte LanguagePrimitives.GenericOne @@>, false + <@@ byte LanguagePrimitives.GenericOne @@>, false + <@@ byte 3.0M @@>, true + <@@ byte "3" @@>, false + + <@@ sbyte 3uy @@>, true + <@@ sbyte 3y @@>, true + <@@ sbyte 3s @@>, true + <@@ sbyte 3us @@>, true + <@@ sbyte 3 @@>, true + <@@ sbyte 3u @@>, true + <@@ sbyte 3L @@>, true + <@@ sbyte 3UL @@>, true + <@@ sbyte 3.0f @@>, true + <@@ sbyte 3.0 @@>, true + <@@ sbyte LanguagePrimitives.GenericOne @@>, false + <@@ sbyte LanguagePrimitives.GenericOne @@>, false + <@@ sbyte 3.0M @@>, true + <@@ sbyte "3" @@>, false + + <@@ int16 3uy @@>, true + <@@ int16 3y @@>, true + <@@ int16 3s @@>, true + <@@ int16 3us @@>, true + <@@ int16 3 @@>, true + <@@ int16 3u @@>, true + <@@ int16 3L @@>, true + <@@ int16 3UL @@>, true + <@@ int16 3.0f @@>, true + <@@ int16 3.0 @@>, true + <@@ int16 LanguagePrimitives.GenericOne @@>, false + <@@ int16 LanguagePrimitives.GenericOne @@>, false + <@@ int16 3.0M @@>, true + <@@ int16 "3" @@>, false + + <@@ uint16 3uy @@>, true + <@@ uint16 3y @@>, true + <@@ uint16 3s @@>, true + <@@ uint16 3us @@>, true + <@@ uint16 3 @@>, true + <@@ uint16 3u @@>, true + <@@ uint16 3L @@>, true + <@@ uint16 3UL @@>, true + <@@ uint16 3.0f @@>, true + <@@ uint16 3.0 @@>, true + <@@ uint16 LanguagePrimitives.GenericOne @@>, false + <@@ uint16 LanguagePrimitives.GenericOne @@>, false + <@@ uint16 3.0M @@>, true + <@@ uint16 "3" @@>, false + + <@@ int32 3uy @@>, true + <@@ int32 3y @@>, true + <@@ int32 3s @@>, true + <@@ int32 3us @@>, true + <@@ int32 3 @@>, true + <@@ int32 3u @@>, true + <@@ int32 3L @@>, true + <@@ int32 3UL @@>, true + <@@ int32 3.0f @@>, true + <@@ int32 3.0 @@>, true + <@@ int32 LanguagePrimitives.GenericOne @@>, false + <@@ int32 LanguagePrimitives.GenericOne @@>, false + <@@ int32 3.0M @@>, true + <@@ int32 "3" @@>, false + + <@@ uint32 3uy @@>, true + <@@ uint32 3y @@>, true + <@@ uint32 3s @@>, true + <@@ uint32 3us @@>, true + <@@ uint32 3 @@>, true + <@@ uint32 3u @@>, true + <@@ uint32 3L @@>, true + <@@ uint32 3UL @@>, true + <@@ uint32 3.0f @@>, true + <@@ uint32 3.0 @@>, true + <@@ uint32 LanguagePrimitives.GenericOne @@>, false + <@@ uint32 LanguagePrimitives.GenericOne @@>, false + <@@ uint32 3.0M @@>, true + <@@ uint32 "3" @@>, false + + <@@ int64 3uy @@>, true + <@@ int64 3y @@>, true + <@@ int64 3s @@>, true + <@@ int64 3us @@>, true + <@@ int64 3 @@>, true + <@@ int64 3u @@>, true + <@@ int64 3L @@>, true + <@@ int64 3UL @@>, true + <@@ int64 3.0f @@>, true + <@@ int64 3.0 @@>, true + <@@ int64 LanguagePrimitives.GenericOne @@>, false + <@@ int64 LanguagePrimitives.GenericOne @@>, false + <@@ int64 3.0M @@>, true + <@@ int64 "3" @@>, false + + <@@ uint64 3uy @@>, true + <@@ uint64 3y @@>, true + <@@ uint64 3s @@>, true + <@@ uint64 3us @@>, true + <@@ uint64 3 @@>, true + <@@ uint64 3u @@>, true + <@@ uint64 3L @@>, true + <@@ uint64 3UL @@>, true + <@@ uint64 3.0f @@>, true + <@@ uint64 3.0 @@>, true + <@@ uint64 LanguagePrimitives.GenericOne @@>, false + <@@ uint64 LanguagePrimitives.GenericOne @@>, false + <@@ uint64 3.0M @@>, true + <@@ uint64 "3" @@>, false + + <@@ nativeint 3uy @@>, true + <@@ nativeint 3y @@>, true + <@@ nativeint 3s @@>, true + <@@ nativeint 3us @@>, true + <@@ nativeint 3 @@>, true + <@@ nativeint 3u @@>, true + <@@ nativeint 3L @@>, true + <@@ nativeint 3UL @@>, true + <@@ nativeint 3.0f @@>, true + <@@ nativeint 3.0 @@>, true + <@@ nativeint LanguagePrimitives.GenericOne @@>, false + <@@ nativeint LanguagePrimitives.GenericOne @@>, false + //<@@ nativeint 3.0M @@>, false + //<@@ nativeint "3" @@>, false + + <@@ unativeint 3uy @@>, true + <@@ unativeint 3y @@>, true + <@@ unativeint 3s @@>, true + <@@ unativeint 3us @@>, true + <@@ unativeint 3 @@>, true + <@@ unativeint 3u @@>, true + <@@ unativeint 3L @@>, true + <@@ unativeint 3UL @@>, true + <@@ unativeint 3.0f @@>, true + <@@ unativeint 3.0 @@>, true + <@@ unativeint LanguagePrimitives.GenericOne @@>, false + <@@ unativeint LanguagePrimitives.GenericOne @@>, false + //<@@ unativeint 3.0M @@>, true + //<@@ unativeint "3" @@>, true + + <@@ LanguagePrimitives.GenericZero @@>, true + <@@ LanguagePrimitives.GenericZero @@>, true + <@@ LanguagePrimitives.GenericZero @@>, true + <@@ LanguagePrimitives.GenericZero @@>, true + <@@ LanguagePrimitives.GenericZero @@>, true + <@@ LanguagePrimitives.GenericZero @@>, true + <@@ LanguagePrimitives.GenericOne @@>, true + <@@ LanguagePrimitives.GenericOne @@>, true + <@@ LanguagePrimitives.GenericOne @@>, true + <@@ LanguagePrimitives.GenericOne @@>, true + <@@ LanguagePrimitives.GenericOne @@>, true + <@@ LanguagePrimitives.GenericOne @@>, true + <@@ List.sum [ 1; 2 ] @@>, true + <@@ List.sum [ 1.0f; 2.0f ] @@>, true + <@@ List.sum [ 1.0; 2.0 ] @@>, true + <@@ List.sum [ 1.0M; 2.0M ] @@>, true + <@@ List.average [ 1.0; 2.0 ] @@>, true + <@@ List.average [ 1.0f; 2.0f ] @@>, true + <@@ List.average [ 1.0M; 2.0M ] @@>, true + ] + + tests |> List.forall (fun (test, canEval) -> + if canEval then + printfn "--> checking we can evaluate %A" test + FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.EvaluateQuotation test |> ignore + printfn "<-- evaluated!" + else + printfn "skipping evaluation of %A because LinqExpressionConverter can't handle it" test + printfn "checking %A" test + match test with + | CallWithWitnesses(None, minfo1, minfo2, witnessArgs, args) -> + minfo1.IsStatic && + minfo2.IsStatic && + minfo2.Name = minfo1.Name + "WithWitnesses" && + (* + (printfn "checking minfo2.GetParameters().Length = %d..." (minfo2.GetParameters().Length); true) && + minfo2.GetParameters().Length = 3 && + (printfn "checking witnessArgs.Length..."; true) && + witnessArgs.Length = 1 && + (printfn "checking args.Length..."; true) && + args.Length = 2 && + (printfn "witnessArgs..."; true) && + (match witnessArgs with [ Lambda _ ] -> true | _ -> false) && + (printfn "args..."; true) && + (match args with [ _; _ ] -> true | _ -> false) + *) + true + | _ -> false)) #if !FX_RESHAPED_REFLECTION module TestAssemblyAttributes = From 366ed83dc631ef0d758479d927b0f2d03a98d071 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Sun, 14 Apr 2019 17:11:41 +0100 Subject: [PATCH 51/77] do not try to build latest FSHarp.Core as part of proto build --- FSharpBuild.Directory.Build.props | 1 + src/fsharp/FSharp.Build/FSharp.Build.fsproj | 4 +++- .../FSharp.Compiler.Interactive.Settings.fsproj | 4 +++- .../FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj | 4 +++- .../FSharp.Compiler.Server.Shared.fsproj | 4 +++- src/fsharp/fsc/fsc.fsproj | 6 +++--- src/fsharp/fsi/fsi.fsproj | 4 +++- src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj | 4 +++- 8 files changed, 22 insertions(+), 9 deletions(-) diff --git a/FSharpBuild.Directory.Build.props b/FSharpBuild.Directory.Build.props index a1ba7ab156d..95036cb5ae1 100644 --- a/FSharpBuild.Directory.Build.props +++ b/FSharpBuild.Directory.Build.props @@ -92,6 +92,7 @@ fs false true + 4.6.2 diff --git a/src/fsharp/FSharp.Build/FSharp.Build.fsproj b/src/fsharp/FSharp.Build/FSharp.Build.fsproj index 0dad55058b0..7bab41796bd 100644 --- a/src/fsharp/FSharp.Build/FSharp.Build.fsproj +++ b/src/fsharp/FSharp.Build/FSharp.Build.fsproj @@ -33,7 +33,9 @@ - + + + diff --git a/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj b/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj index 6307f17baf3..799fda75246 100644 --- a/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj +++ b/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj @@ -28,7 +28,9 @@ - + + + diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj index 9fef6d27589..bed8c55e91e 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj @@ -675,7 +675,9 @@ - + + + diff --git a/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj b/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj index 75a7353bb96..39ba868aeee 100644 --- a/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj +++ b/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj @@ -21,7 +21,9 @@ - + + + diff --git a/src/fsharp/fsc/fsc.fsproj b/src/fsharp/fsc/fsc.fsproj index 8ddb082c56a..4b812970716 100644 --- a/src/fsharp/fsc/fsc.fsproj +++ b/src/fsharp/fsc/fsc.fsproj @@ -29,9 +29,9 @@ - - - + + + diff --git a/src/fsharp/fsi/fsi.fsproj b/src/fsharp/fsi/fsi.fsproj index a7bafddfded..43e95426220 100644 --- a/src/fsharp/fsi/fsi.fsproj +++ b/src/fsharp/fsi/fsi.fsproj @@ -26,7 +26,9 @@ - + + + diff --git a/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj b/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj index dbe31f6ec2a..fd6c5b7ef3e 100644 --- a/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj +++ b/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj @@ -26,7 +26,9 @@ - + + + From 6fae5c43b23e072e2dbe75afe631a035d7256733 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Sun, 14 Apr 2019 17:13:05 +0100 Subject: [PATCH 52/77] do not try to build latest FSHarp.Core as part of proto build --- src/fsharp/FSharp.Core/FSharp.Core.fsproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/FSharp.Core.fsproj b/src/fsharp/FSharp.Core/FSharp.Core.fsproj index 440850ed55c..b3ed7590476 100644 --- a/src/fsharp/FSharp.Core/FSharp.Core.fsproj +++ b/src/fsharp/FSharp.Core/FSharp.Core.fsproj @@ -232,7 +232,7 @@ - + From 6a27e0274adf747e32816ad8f6ec9143c8d4568b Mon Sep 17 00:00:00 2001 From: Don Syme Date: Sun, 14 Apr 2019 17:45:33 +0100 Subject: [PATCH 53/77] do not try to build latest FSHarp.Core as part of proto build --- eng/build-utils.ps1 | 2 +- src/fsharp/FSharp.Build/FSharp.Build.fsproj | 2 +- .../FSharp.Compiler.Interactive.Settings.fsproj | 2 +- .../FSharp.Compiler.Private.fsproj | 2 +- .../FSharp.Compiler.Server.Shared.fsproj | 2 +- src/fsharp/FSharp.Core.nuget/FSharp.Core.nuget.csproj | 2 +- src/fsharp/fsc/fsc.fsproj | 7 ++++++- src/fsharp/fsi/fsi.fsproj | 11 +++++++---- src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj | 11 +++++++---- 9 files changed, 26 insertions(+), 15 deletions(-) diff --git a/eng/build-utils.ps1 b/eng/build-utils.ps1 index d1e5dd85d55..a1e16a5f7ec 100644 --- a/eng/build-utils.ps1 +++ b/eng/build-utils.ps1 @@ -249,7 +249,7 @@ function Make-BootstrapBuild() { $projectPath = "$RepoRoot\proto.proj" Run-MSBuild $projectPath "/restore /t:Build" -logFileName "Bootstrap" -configuration $bootstrapConfiguration Copy-Item "$ArtifactsDir\bin\fsc\$bootstrapConfiguration\$bootstrapTfm\*" -Destination $dir - Copy-Item "$ArtifactsDir\bin\fsi\$bootstrapConfiguration\$bootstrapTfm\*" -Destination $dir + Copy-Item "$ArtifactsDir\bin\fsi\$bootstrapConfiguration\$bootstrapTfm\*" -Destination $dir -Force return $dir } diff --git a/src/fsharp/FSharp.Build/FSharp.Build.fsproj b/src/fsharp/FSharp.Build/FSharp.Build.fsproj index 7bab41796bd..38a1ffa90bc 100644 --- a/src/fsharp/FSharp.Build/FSharp.Build.fsproj +++ b/src/fsharp/FSharp.Build/FSharp.Build.fsproj @@ -33,7 +33,7 @@ - + diff --git a/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj b/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj index 799fda75246..51c4017d67d 100644 --- a/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj +++ b/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj @@ -28,7 +28,7 @@ - + diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj index bed8c55e91e..f7d8f20440a 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj @@ -675,7 +675,7 @@ - + diff --git a/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj b/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj index 39ba868aeee..faab0f8cc3b 100644 --- a/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj +++ b/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj @@ -21,7 +21,7 @@ - + diff --git a/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuget.csproj b/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuget.csproj index fd2d5162c75..e304369556b 100644 --- a/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuget.csproj +++ b/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuget.csproj @@ -10,7 +10,7 @@ - + false diff --git a/src/fsharp/fsc/fsc.fsproj b/src/fsharp/fsc/fsc.fsproj index 4b812970716..8ea9e6d8b07 100644 --- a/src/fsharp/fsc/fsc.fsproj +++ b/src/fsharp/fsc/fsc.fsproj @@ -29,11 +29,16 @@ - + + + + + + diff --git a/src/fsharp/fsi/fsi.fsproj b/src/fsharp/fsi/fsi.fsproj index 43e95426220..d088ca69384 100644 --- a/src/fsharp/fsi/fsi.fsproj +++ b/src/fsharp/fsi/fsi.fsproj @@ -26,14 +26,17 @@ - + - - + + + + + - + diff --git a/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj b/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj index fd6c5b7ef3e..96117f719f4 100644 --- a/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj +++ b/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj @@ -26,12 +26,15 @@ - + - - - + + + + + + From aed6752ecc08695a95f50ef87286ae0f27d01a41 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Sun, 14 Apr 2019 18:15:55 +0100 Subject: [PATCH 54/77] fix build --- .vsts-pr.yaml | 4 ++-- eng/build.sh | 3 ++- proto.proj | 2 +- src/fsharp/FSharp.Build/FSharp.Build.fsproj | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.vsts-pr.yaml b/.vsts-pr.yaml index d33bdae439e..57446ed1e85 100644 --- a/.vsts-pr.yaml +++ b/.vsts-pr.yaml @@ -11,7 +11,7 @@ jobs: _configuration: Release _testKind: testcoreclr steps: - - script: ./eng/cibuild.sh --configuration $(_configuration) --$(_testKind) --verbosity normal + - script: ./eng/cibuild.sh --configuration $(_configuration) --$(_testKind) - task: PublishBuildArtifacts@1 displayName: Publish Build Logs inputs: @@ -55,7 +55,7 @@ jobs: _configuration: Release _testKind: testcoreclr steps: - - script: ./eng/cibuild.sh --configuration $(_configuration) --$(_testKind) --verbosity normal + - script: ./eng/cibuild.sh --configuration $(_configuration) --$(_testKind) - task: PublishBuildArtifacts@1 displayName: Publish Build Logs inputs: diff --git a/eng/build.sh b/eng/build.sh index b874fb842d6..ea44f9e9237 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -15,6 +15,7 @@ usage() echo "Actions:" echo " --bootstrap Force the build of the bootstrap compiler" echo " --restore Restore projects required to build (short: -r)" + echo " --norestore Don't restore projects required to build (short: -r)" echo " --build Build all projects (short: -b)" echo " --rebuild Rebuild all projects" echo " --pack Build nuget packages" @@ -45,7 +46,7 @@ while [[ -h "$source" ]]; do done scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" -restore=true +restore=false build=false rebuild=false pack=false diff --git a/proto.proj b/proto.proj index e6f7a4f8cc0..84103f6fdf8 100644 --- a/proto.proj +++ b/proto.proj @@ -8,7 +8,7 @@ TargetFramework=net472 - TargetFramework=netstandard2.0 + TargetFramework=netcoreapp2.1 TargetFramework=net472 diff --git a/src/fsharp/FSharp.Build/FSharp.Build.fsproj b/src/fsharp/FSharp.Build/FSharp.Build.fsproj index f5f297bda75..0dad55058b0 100644 --- a/src/fsharp/FSharp.Build/FSharp.Build.fsproj +++ b/src/fsharp/FSharp.Build/FSharp.Build.fsproj @@ -4,8 +4,8 @@ Library - net472;netstandard2.0 - netstandard2.0 + net472;netcoreapp2.1 + netcoreapp2.1 FSharp.Build $(NoWarn);45;55;62;75;1204 true From bb78e5f53dbbf6addf82829cfad9f5614b36fb06 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Sun, 14 Apr 2019 18:18:27 +0100 Subject: [PATCH 55/77] fix build --- .vsts-pr.yaml | 2 +- eng/Build.ps1 | 1 + eng/build.sh | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.vsts-pr.yaml b/.vsts-pr.yaml index 57446ed1e85..eeebe57d085 100644 --- a/.vsts-pr.yaml +++ b/.vsts-pr.yaml @@ -108,7 +108,7 @@ jobs: _configuration: Release _testKind: testVs steps: - - script: eng\CIBuild.cmd -configuration $(_configuration) -$(_testKind) -verbosity normal + - script: eng\CIBuild.cmd -configuration $(_configuration) -$(_testKind) - task: PublishBuildArtifacts@1 displayName: Publish Build Logs inputs: diff --git a/eng/Build.ps1 b/eng/Build.ps1 index 352fd9e0583..993adc1d1e9 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -65,6 +65,7 @@ function Print-Usage() { Write-Host "" Write-Host "Actions:" Write-Host " -restore Restore packages (short: -r)" + Write-Host " -norestore Don't restore packages" Write-Host " -build Build main solution (short: -b)" Write-Host " -rebuild Rebuild main solution" Write-Host " -pack Build NuGet packages, VS insertion manifests and installer" diff --git a/eng/build.sh b/eng/build.sh index ea44f9e9237..6b0ddf324b3 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -15,7 +15,7 @@ usage() echo "Actions:" echo " --bootstrap Force the build of the bootstrap compiler" echo " --restore Restore projects required to build (short: -r)" - echo " --norestore Don't restore projects required to build (short: -r)" + echo " --norestore Don't restore projects required to build" echo " --build Build all projects (short: -b)" echo " --rebuild Rebuild all projects" echo " --pack Build nuget packages" From 7982865dcb3a33be9fb30a97a9693ffc084c095a Mon Sep 17 00:00:00 2001 From: Don Syme Date: Sun, 14 Apr 2019 19:59:43 +0100 Subject: [PATCH 56/77] add diagnostics to check which FSharp.Core is referenced --- tests/fsharp/single-test.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/fsharp/single-test.fs b/tests/fsharp/single-test.fs index 2355cc85b4f..a3d33640eb9 100644 --- a/tests/fsharp/single-test.fs +++ b/tests/fsharp/single-test.fs @@ -222,7 +222,7 @@ let singleTestBuildAndRunCore cfg copyFiles p = let projectBody = generateProjectArtifacts pc targetFramework cfg.BUILD_CONFIG emitFile projectFileName projectBody use testOkFile = new FileGuard(Path.Combine(directory, "test.ok")) - exec { cfg with Directory = directory } cfg.DotNetExe (sprintf "run -f %s" targetFramework) + exec { cfg with Directory = directory } cfg.DotNetExe (sprintf "run -f %s -v:n" targetFramework) testOkFile.CheckExists() executeFsc compilerType targetFramework else @@ -232,7 +232,7 @@ let singleTestBuildAndRunCore cfg copyFiles p = let projectBody = generateProjectArtifacts pc targetFramework cfg.BUILD_CONFIG emitFile projectFileName projectBody use testOkFile = new FileGuard(Path.Combine(directory, "test.ok")) - exec { cfg with Directory = directory } cfg.DotNetExe "build /t:RunFSharpScript" + exec { cfg with Directory = directory } cfg.DotNetExe "build /t:RunFSharpScript -v:n" testOkFile.CheckExists() executeFsi compilerType targetFramework result <- true From 250127e353d84e1aa0b85554707d1e97d0461ee3 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Sun, 14 Apr 2019 20:15:44 +0100 Subject: [PATCH 57/77] add diagnostics to check which FSharp.Core is referenced --- tests/fsharp/single-test.fs | 41 ++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/tests/fsharp/single-test.fs b/tests/fsharp/single-test.fs index a3d33640eb9..e2541b6d9bd 100644 --- a/tests/fsharp/single-test.fs +++ b/tests/fsharp/single-test.fs @@ -216,28 +216,31 @@ let singleTestBuildAndRunCore cfg copyFiles p = emitFile targetsFileName targetsBody emitFile overridesFileName overridesBody if outputType = OutputType.Exe then - let executeFsc testCompilerVersion targetFramework = - let propsBody = generateProps testCompilerVersion cfg.BUILD_CONFIG - emitFile propsFileName propsBody - let projectBody = generateProjectArtifacts pc targetFramework cfg.BUILD_CONFIG - emitFile projectFileName projectBody - use testOkFile = new FileGuard(Path.Combine(directory, "test.ok")) - exec { cfg with Directory = directory } cfg.DotNetExe (sprintf "run -f %s -v:n" targetFramework) - testOkFile.CheckExists() - executeFsc compilerType targetFramework + let propsBody = generateProps compilerType cfg.BUILD_CONFIG + emitFile propsFileName propsBody + let projectBody = generateProjectArtifacts pc targetFramework cfg.BUILD_CONFIG + emitFile projectFileName projectBody + use testOkFile = new FileGuard(Path.Combine(directory, "test.ok")) + printfn "------ Props file: %s" propsFileName + printfn "%s" propsBody + printfn "------ Project file: %s" projectFileName + printfn "%s" projectBody + printfn "------ Project file: %s" projectFileName + printfn "------ Execute:" + exec { cfg with Directory = directory } cfg.DotNetExe (sprintf "run -f %s -v:n" targetFramework) + testOkFile.CheckExists() + result <- true else - let executeFsi testCompilerVersion targetFramework = - let propsBody = generateProps testCompilerVersion cfg.BUILD_CONFIG - emitFile propsFileName propsBody - let projectBody = generateProjectArtifacts pc targetFramework cfg.BUILD_CONFIG - emitFile projectFileName projectBody - use testOkFile = new FileGuard(Path.Combine(directory, "test.ok")) - exec { cfg with Directory = directory } cfg.DotNetExe "build /t:RunFSharpScript -v:n" - testOkFile.CheckExists() - executeFsi compilerType targetFramework + let propsBody = generateProps compilerType cfg.BUILD_CONFIG + emitFile propsFileName propsBody + let projectBody = generateProjectArtifacts pc targetFramework cfg.BUILD_CONFIG + emitFile projectFileName projectBody + use testOkFile = new FileGuard(Path.Combine(directory, "test.ok")) + exec { cfg with Directory = directory } cfg.DotNetExe "build /t:RunFSharpScript -v:n" + testOkFile.CheckExists() result <- true finally - if result <> false then + if result then Directory.Delete(directory, true) else printfn "Configuration: %s" cfg.Directory From 5eb6c15449c764eb3b66568ffb6b96d236364428 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Sun, 14 Apr 2019 20:16:52 +0100 Subject: [PATCH 58/77] add diagnostics to check which FSharp.Core is referenced --- tests/fsharp/single-test.fs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/fsharp/single-test.fs b/tests/fsharp/single-test.fs index e2541b6d9bd..5bf2005ef41 100644 --- a/tests/fsharp/single-test.fs +++ b/tests/fsharp/single-test.fs @@ -221,11 +221,14 @@ let singleTestBuildAndRunCore cfg copyFiles p = let projectBody = generateProjectArtifacts pc targetFramework cfg.BUILD_CONFIG emitFile projectFileName projectBody use testOkFile = new FileGuard(Path.Combine(directory, "test.ok")) + printfn "------ Overrides file: %s" overridesFileName + printfn "%s" overridesFileName + printfn "------ Targets file: %s" targetsFileName + printfn "%s" targetsBody printfn "------ Props file: %s" propsFileName printfn "%s" propsBody printfn "------ Project file: %s" projectFileName printfn "%s" projectBody - printfn "------ Project file: %s" projectFileName printfn "------ Execute:" exec { cfg with Directory = directory } cfg.DotNetExe (sprintf "run -f %s -v:n" targetFramework) testOkFile.CheckExists() From 362172c23931203ce925f905fdd34b0da6c6823b Mon Sep 17 00:00:00 2001 From: Don Syme Date: Sun, 14 Apr 2019 20:17:04 +0100 Subject: [PATCH 59/77] merge fixcore --- tests/fsharp/single-test.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fsharp/single-test.fs b/tests/fsharp/single-test.fs index 5bf2005ef41..376da60b99f 100644 --- a/tests/fsharp/single-test.fs +++ b/tests/fsharp/single-test.fs @@ -222,7 +222,7 @@ let singleTestBuildAndRunCore cfg copyFiles p = emitFile projectFileName projectBody use testOkFile = new FileGuard(Path.Combine(directory, "test.ok")) printfn "------ Overrides file: %s" overridesFileName - printfn "%s" overridesFileName + printfn "%s" overridesBody printfn "------ Targets file: %s" targetsFileName printfn "%s" targetsBody printfn "------ Props file: %s" propsFileName From a678c8fa381c719bc2ed92e9dfae4c9d5cc6d482 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Sun, 14 Apr 2019 20:18:32 +0100 Subject: [PATCH 60/77] add diagnostics to check which FSharp.Core is referenced --- tests/fsharp/single-test.fs | 39 +++++++++++++++---------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/tests/fsharp/single-test.fs b/tests/fsharp/single-test.fs index 376da60b99f..ffaafb51d91 100644 --- a/tests/fsharp/single-test.fs +++ b/tests/fsharp/single-test.fs @@ -215,33 +215,26 @@ let singleTestBuildAndRunCore cfg copyFiles p = try File.Delete(Path.Combine(directory, "FSharp.Core.dll")) with _ -> () emitFile targetsFileName targetsBody emitFile overridesFileName overridesBody + let propsBody = generateProps compilerType cfg.BUILD_CONFIG + emitFile propsFileName propsBody + let projectBody = generateProjectArtifacts pc targetFramework cfg.BUILD_CONFIG + emitFile projectFileName projectBody + printfn "------ Overrides file: %s" overridesFileName + printfn "%s" overridesBody + printfn "------ Targets file: %s" targetsFileName + printfn "%s" targetsBody + printfn "------ Props file: %s" propsFileName + printfn "%s" propsBody + printfn "------ Project file: %s" projectFileName + printfn "%s" projectBody + printfn "------ Execute:" + use testOkFile = new FileGuard(Path.Combine(directory, "test.ok")) if outputType = OutputType.Exe then - let propsBody = generateProps compilerType cfg.BUILD_CONFIG - emitFile propsFileName propsBody - let projectBody = generateProjectArtifacts pc targetFramework cfg.BUILD_CONFIG - emitFile projectFileName projectBody - use testOkFile = new FileGuard(Path.Combine(directory, "test.ok")) - printfn "------ Overrides file: %s" overridesFileName - printfn "%s" overridesBody - printfn "------ Targets file: %s" targetsFileName - printfn "%s" targetsBody - printfn "------ Props file: %s" propsFileName - printfn "%s" propsBody - printfn "------ Project file: %s" projectFileName - printfn "%s" projectBody - printfn "------ Execute:" exec { cfg with Directory = directory } cfg.DotNetExe (sprintf "run -f %s -v:n" targetFramework) - testOkFile.CheckExists() - result <- true else - let propsBody = generateProps compilerType cfg.BUILD_CONFIG - emitFile propsFileName propsBody - let projectBody = generateProjectArtifacts pc targetFramework cfg.BUILD_CONFIG - emitFile projectFileName projectBody - use testOkFile = new FileGuard(Path.Combine(directory, "test.ok")) exec { cfg with Directory = directory } cfg.DotNetExe "build /t:RunFSharpScript -v:n" - testOkFile.CheckExists() - result <- true + testOkFile.CheckExists() + result <- true finally if result then Directory.Delete(directory, true) From 67830410c9ae4fea919cef0f2e7bdb364ccb0d98 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Sun, 14 Apr 2019 21:03:31 +0100 Subject: [PATCH 61/77] fix build --- .../FSharp.Compiler.Service.MSBuild.v12.fsproj | 3 --- .../FSharp.Compiler.Service.ProjectCracker.fsproj | 3 --- .../FSharp.Compiler.Service.fsproj | 1 - fcs/samples/EditorService/EditorService.fsproj | 2 -- fcs/samples/FscExe/FscExe.fsproj | 2 -- fcs/samples/FsiExe/FsiExe.fsproj | 2 -- .../InteractiveService/InteractiveService.fsproj | 2 -- fcs/samples/Tokenizer/Tokenizer.fsproj | 2 -- fcs/samples/UntypedTree/UntypedTree.fsproj | 2 -- src/fsharp/FSharp.Build/FSharp.Build.fsproj | 4 +--- .../FSharp.Compiler.Interactive.Settings.fsproj | 4 +--- .../FSharp.Compiler.Private.fsproj | 4 +--- .../FSharp.Compiler.Server.Shared.fsproj | 4 +--- .../FSharp.Core.nuget/FSharp.Core.nuget.csproj | 2 +- src/fsharp/fsc/fsc.fsproj | 12 +++--------- src/fsharp/fsi/fsi.fsproj | 14 +++----------- src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj | 13 +++++-------- 17 files changed, 16 insertions(+), 60 deletions(-) diff --git a/fcs/FSharp.Compiler.Service.MSBuild.v12/FSharp.Compiler.Service.MSBuild.v12.fsproj b/fcs/FSharp.Compiler.Service.MSBuild.v12/FSharp.Compiler.Service.MSBuild.v12.fsproj index ee02c4fb197..20e1f29af35 100644 --- a/fcs/FSharp.Compiler.Service.MSBuild.v12/FSharp.Compiler.Service.MSBuild.v12.fsproj +++ b/fcs/FSharp.Compiler.Service.MSBuild.v12/FSharp.Compiler.Service.MSBuild.v12.fsproj @@ -29,9 +29,6 @@ - - - diff --git a/fcs/FSharp.Compiler.Service.ProjectCracker/FSharp.Compiler.Service.ProjectCracker.fsproj b/fcs/FSharp.Compiler.Service.ProjectCracker/FSharp.Compiler.Service.ProjectCracker.fsproj index 932e3b87c16..648f66924df 100644 --- a/fcs/FSharp.Compiler.Service.ProjectCracker/FSharp.Compiler.Service.ProjectCracker.fsproj +++ b/fcs/FSharp.Compiler.Service.ProjectCracker/FSharp.Compiler.Service.ProjectCracker.fsproj @@ -28,9 +28,6 @@ - - - \ No newline at end of file diff --git a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj index ebd96c88b52..dcdf91eef4a 100644 --- a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj +++ b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj @@ -639,7 +639,6 @@ - diff --git a/fcs/samples/EditorService/EditorService.fsproj b/fcs/samples/EditorService/EditorService.fsproj index 4f86815c922..25795d9299c 100644 --- a/fcs/samples/EditorService/EditorService.fsproj +++ b/fcs/samples/EditorService/EditorService.fsproj @@ -13,8 +13,6 @@ - - diff --git a/fcs/samples/FscExe/FscExe.fsproj b/fcs/samples/FscExe/FscExe.fsproj index 4a4dcc02e0d..a160f690d2f 100644 --- a/fcs/samples/FscExe/FscExe.fsproj +++ b/fcs/samples/FscExe/FscExe.fsproj @@ -15,8 +15,6 @@ - - diff --git a/fcs/samples/FsiExe/FsiExe.fsproj b/fcs/samples/FsiExe/FsiExe.fsproj index 526d71589c8..4ce18ab142c 100644 --- a/fcs/samples/FsiExe/FsiExe.fsproj +++ b/fcs/samples/FsiExe/FsiExe.fsproj @@ -17,8 +17,6 @@ - - diff --git a/fcs/samples/InteractiveService/InteractiveService.fsproj b/fcs/samples/InteractiveService/InteractiveService.fsproj index 36ada2d3db2..75686578f21 100644 --- a/fcs/samples/InteractiveService/InteractiveService.fsproj +++ b/fcs/samples/InteractiveService/InteractiveService.fsproj @@ -13,8 +13,6 @@ - - diff --git a/fcs/samples/Tokenizer/Tokenizer.fsproj b/fcs/samples/Tokenizer/Tokenizer.fsproj index 36ada2d3db2..75686578f21 100644 --- a/fcs/samples/Tokenizer/Tokenizer.fsproj +++ b/fcs/samples/Tokenizer/Tokenizer.fsproj @@ -13,8 +13,6 @@ - - diff --git a/fcs/samples/UntypedTree/UntypedTree.fsproj b/fcs/samples/UntypedTree/UntypedTree.fsproj index 60879414172..75686578f21 100644 --- a/fcs/samples/UntypedTree/UntypedTree.fsproj +++ b/fcs/samples/UntypedTree/UntypedTree.fsproj @@ -13,8 +13,6 @@ - - diff --git a/src/fsharp/FSharp.Build/FSharp.Build.fsproj b/src/fsharp/FSharp.Build/FSharp.Build.fsproj index d15d907037d..2fb62838060 100644 --- a/src/fsharp/FSharp.Build/FSharp.Build.fsproj +++ b/src/fsharp/FSharp.Build/FSharp.Build.fsproj @@ -34,9 +34,7 @@ - - - + diff --git a/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj b/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj index 0b4f175853b..f7345f1dc11 100644 --- a/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj +++ b/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj @@ -29,9 +29,7 @@ - - - + diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj index e368c5f7257..d57c2f75955 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj @@ -676,9 +676,7 @@ - - - + diff --git a/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj b/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj index 3406a8a3401..c4e83c160ac 100644 --- a/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj +++ b/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj @@ -22,9 +22,7 @@ - - - + diff --git a/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuget.csproj b/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuget.csproj index e304369556b..fd2d5162c75 100644 --- a/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuget.csproj +++ b/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuget.csproj @@ -10,7 +10,7 @@ - + false diff --git a/src/fsharp/fsc/fsc.fsproj b/src/fsharp/fsc/fsc.fsproj index 5aa44f4b122..f2161a048f2 100644 --- a/src/fsharp/fsc/fsc.fsproj +++ b/src/fsharp/fsc/fsc.fsproj @@ -30,19 +30,13 @@ - - - - - - - + - - + + diff --git a/src/fsharp/fsi/fsi.fsproj b/src/fsharp/fsi/fsi.fsproj index 0832a68217a..df7daaaafdb 100644 --- a/src/fsharp/fsi/fsi.fsproj +++ b/src/fsharp/fsi/fsi.fsproj @@ -27,24 +27,16 @@ - - + + - - - - - - - - - + diff --git a/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj b/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj index 1326474fc38..427046b7fd6 100644 --- a/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj +++ b/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj @@ -27,23 +27,20 @@ - - + + - - - - - - + + + From e2be246e0aa5686114e98fcb6569aa99ba243aff Mon Sep 17 00:00:00 2001 From: Don Syme Date: Sun, 14 Apr 2019 21:44:12 +0100 Subject: [PATCH 62/77] fix files --- src/fsharp/FSharp.Build/FSharp.Build.fsproj | 2 +- .../FSharp.Compiler.Interactive.Settings.fsproj | 2 +- .../FSharp.Compiler.Private.fsproj | 2 +- .../FSharp.Compiler.Server.Shared.fsproj | 2 +- src/fsharp/fsc/fsc.fsproj | 6 +++--- src/fsharp/fsi/fsi.fsproj | 2 +- src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj | 8 +------- 7 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/fsharp/FSharp.Build/FSharp.Build.fsproj b/src/fsharp/FSharp.Build/FSharp.Build.fsproj index 2fb62838060..3779622065e 100644 --- a/src/fsharp/FSharp.Build/FSharp.Build.fsproj +++ b/src/fsharp/FSharp.Build/FSharp.Build.fsproj @@ -34,7 +34,7 @@ - + diff --git a/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj b/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj index f7345f1dc11..9b434c5210e 100644 --- a/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj +++ b/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj @@ -29,7 +29,7 @@ - + diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj index d57c2f75955..f3977e422f6 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj @@ -676,7 +676,7 @@ - + diff --git a/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj b/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj index c4e83c160ac..1756ed91163 100644 --- a/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj +++ b/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj @@ -22,7 +22,7 @@ - + diff --git a/src/fsharp/fsc/fsc.fsproj b/src/fsharp/fsc/fsc.fsproj index f2161a048f2..f3a1b35135d 100644 --- a/src/fsharp/fsc/fsc.fsproj +++ b/src/fsharp/fsc/fsc.fsproj @@ -30,13 +30,13 @@ - + - - + + diff --git a/src/fsharp/fsi/fsi.fsproj b/src/fsharp/fsi/fsi.fsproj index df7daaaafdb..747173218af 100644 --- a/src/fsharp/fsi/fsi.fsproj +++ b/src/fsharp/fsi/fsi.fsproj @@ -27,7 +27,7 @@ - + diff --git a/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj b/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj index 427046b7fd6..1e4fd2193e7 100644 --- a/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj +++ b/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj @@ -27,7 +27,7 @@ - + @@ -37,12 +37,6 @@ - - - - - - From 1aa6a410178ba7f250372dfe170a1958b886ee27 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Mon, 15 Apr 2019 22:34:31 +0100 Subject: [PATCH 63/77] load right FSHarp.Build --- FSharpTests.Directory.Build.props | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/FSharpTests.Directory.Build.props b/FSharpTests.Directory.Build.props index 7c00805dda5..8a7a832a43e 100644 --- a/FSharpTests.Directory.Build.props +++ b/FSharpTests.Directory.Build.props @@ -32,9 +32,9 @@ - <_FSharpBuildTargetFramework Condition="'$(FSharpTestCompilerVersion)' == 'net40'">net472 - <_FSharpBuildTargetFramework Condition="'$(FSharpTestCompilerVersion)' == 'coreclr'">netcoreapp2.1 - <_FSharpBuildBinPath>$(MSBuildThisFileDirectory)artifacts\bin\FSharp.Build\$(Configuration)\$(_FSharpBuildTargetFramework) + <_FSharpBuildTargetFramework Condition="'$(MSBuildRuntimeType)'!='Core'">net472 + <_FSharpBuildTargetFramework Condition="'$(MSBuildRuntimeType)'=='Core'">netcoreapp2.1 + <_FSharpBuildBinPath>$(MSBuildThisFileDirectory)artifacts\bin\fsc\$(Configuration)\$(_FSharpBuildTargetFramework) $(_FSharpBuildBinPath)\FSharp.Build.dll From 058bdc9a5a5ab6d9906c80618ae6486dc739434a Mon Sep 17 00:00:00 2001 From: Don Syme Date: Mon, 15 Apr 2019 23:01:00 +0100 Subject: [PATCH 64/77] publish proto apps --- FSharpBuild.Directory.Build.props | 11 +++++------ FSharpTests.Directory.Build.props | 10 +++++----- eng/Build.ps1 | 2 +- eng/build-utils.ps1 | 12 ++++++------ eng/build.sh | 10 +++++----- fcs/Directory.Build.props | 5 ----- proto.proj | 4 ++++ src/buildtools/buildtools.targets | 4 ++-- 8 files changed, 28 insertions(+), 30 deletions(-) diff --git a/FSharpBuild.Directory.Build.props b/FSharpBuild.Directory.Build.props index 905ea66544f..515de9bbdc7 100644 --- a/FSharpBuild.Directory.Build.props +++ b/FSharpBuild.Directory.Build.props @@ -11,8 +11,7 @@ $(RepoRoot)src $(ArtifactsDir)\SymStore - $(ArtifactsDir)\Bootstrap - $(ArtifactsDir)/bin/fsc/Proto/netcoreapp2.1 + $(ArtifactsDir)\Bootstrap 4.4.0 1182;0025;$(WarningsAsErrors) @@ -96,10 +95,10 @@ - $(ProtoOutputPath)\Microsoft.FSharp.Targets - $(ProtoOutputPath)\Microsoft.FSharp.NetSdk.props - $(ProtoOutputPath)\Microsoft.FSharp.NetSdk.targets - $(ProtoOutputPath)\Microsoft.FSharp.Overrides.NetSdk.targets + $(ProtoOutputPath)\fsc\Microsoft.FSharp.Targets + $(ProtoOutputPath)\fsc\Microsoft.FSharp.NetSdk.props + $(ProtoOutputPath)\fsc\Microsoft.FSharp.NetSdk.targets + $(ProtoOutputPath)\fsc\Microsoft.FSharp.Overrides.NetSdk.targets diff --git a/FSharpTests.Directory.Build.props b/FSharpTests.Directory.Build.props index 8a7a832a43e..9ad765f036d 100644 --- a/FSharpTests.Directory.Build.props +++ b/FSharpTests.Directory.Build.props @@ -7,11 +7,11 @@ true - $(MSBuildThisFileDirectory)artifacts\bin\fsc\$(Configuration)\net472 + $(MSBuildThisFileDirectory)artifacts\bin\fsc\$(Configuration)\net472\publish fsc.exe - $(MSBuildThisFileDirectory)artifacts\bin\fsi\$(Configuration)\net472 + $(MSBuildThisFileDirectory)artifacts\bin\fsi\$(Configuration)\net472\publish fsi.exe @@ -22,19 +22,19 @@ $([System.IO.Path]::GetDirectoryName('$(DOTNET_HOST_PATH)')) dotnet.exe dotnet - $(MSBuildThisFileDirectory)artifacts\bin\fsc\$(Configuration)\netcoreapp2.1\fsc.exe + $(MSBuildThisFileDirectory)artifacts\bin\fsc\$(Configuration)\netcoreapp2.1\publish\fsc.exe $([System.IO.Path]::GetDirectoryName('$(DOTNET_HOST_PATH)')) dotnet.exe dotnet - $(MSBuildThisFileDirectory)artifacts\bin\fsi\$(Configuration)\netcoreapp2.1\fsi.exe + $(MSBuildThisFileDirectory)artifacts\bin\fsi\$(Configuration)\netcoreapp2.1\publish\fsi.exe <_FSharpBuildTargetFramework Condition="'$(MSBuildRuntimeType)'!='Core'">net472 <_FSharpBuildTargetFramework Condition="'$(MSBuildRuntimeType)'=='Core'">netcoreapp2.1 - <_FSharpBuildBinPath>$(MSBuildThisFileDirectory)artifacts\bin\fsc\$(Configuration)\$(_FSharpBuildTargetFramework) + <_FSharpBuildBinPath>$(MSBuildThisFileDirectory)artifacts\bin\fsc\$(Configuration)\$(_FSharpBuildTargetFramework)\publish $(_FSharpBuildBinPath)\FSharp.Build.dll diff --git a/eng/Build.ps1 b/eng/Build.ps1 index 993adc1d1e9..30ef852db76 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -196,7 +196,7 @@ function UpdatePath() { } function VerifyAssemblyVersions() { - $fsiPath = Join-Path $ArtifactsDir "bin\fsi\Proto\net472\fsi.exe" + $fsiPath = Join-Path $ArtifactsDir "bin\fsi\Proto\net472\publish\fsi.exe" # Only verify versions on CI or official build if ($ci -or $official) { diff --git a/eng/build-utils.ps1 b/eng/build-utils.ps1 index 9c626f7c8f3..c16e31ebfc2 100644 --- a/eng/build-utils.ps1 +++ b/eng/build-utils.ps1 @@ -237,15 +237,15 @@ function Make-BootstrapBuild() { Create-Directory $dir # prepare FsLex and Fsyacc - Run-MSBuild "$RepoRoot\src\buildtools\buildtools.proj" "/restore /t:Build" -logFileName "BuildTools" -configuration $bootstrapConfiguration - Copy-Item "$ArtifactsDir\bin\fslex\$bootstrapConfiguration\netcoreapp2.1\*" -Destination $dir - Copy-Item "$ArtifactsDir\bin\fsyacc\$bootstrapConfiguration\netcoreapp2.1\*" -Destination $dir + Run-MSBuild "$RepoRoot\src\buildtools\buildtools.proj" "/restore /t:Publish" -logFileName "BuildTools" -configuration $bootstrapConfiguration + Copy-Item "$ArtifactsDir\bin\fslex\$bootstrapConfiguration\netcoreapp2.1\publish" -Destination "$dir\fslex" -Force -Recurse + Copy-Item "$ArtifactsDir\bin\fsyacc\$bootstrapConfiguration\netcoreapp2.1\publish" -Destination "$dir\fsyacc" -Force -Recurse # prepare compiler $projectPath = "$RepoRoot\proto.proj" - Run-MSBuild $projectPath "/restore /t:Build" -logFileName "Bootstrap" -configuration $bootstrapConfiguration - Copy-Item "$ArtifactsDir\bin\fsc\$bootstrapConfiguration\$bootstrapTfm\*" -Destination $dir - Copy-Item "$ArtifactsDir\bin\fsi\$bootstrapConfiguration\$bootstrapTfm\*" -Destination $dir + Run-MSBuild $projectPath "/restore /t:Publish" -logFileName "Bootstrap" -configuration $bootstrapConfiguration + Copy-Item "$ArtifactsDir\bin\fsc\$bootstrapConfiguration\$bootstrapTfm\publish" -Destination "$dir\fsc" -Force -Recurse + Copy-Item "$ArtifactsDir\bin\fsi\$bootstrapConfiguration\$bootstrapTfm\publish" -Destination "$dir\fsi" -Force -Recurse return $dir } diff --git a/eng/build.sh b/eng/build.sh index 6b0ddf324b3..8a236373f37 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -225,20 +225,20 @@ function BuildSolution { /restore \ /v:$verbosity \ /p:Configuration=$bootstrap_config \ - /t:Build + /t:Publish mkdir -p "$bootstrap_dir" - cp $artifacts_dir/bin/fslex/$bootstrap_config/netcoreapp2.1/* $bootstrap_dir - cp $artifacts_dir/bin/fsyacc/$bootstrap_config/netcoreapp2.1/* $bootstrap_dir + cp -pr $artifacts_dir/bin/fslex/$bootstrap_config/netcoreapp2.1/publish $bootstrap_dir/fslex + cp -pr $artifacts_dir/bin/fsyacc/$bootstrap_config/netcoreapp2.1/publish $bootstrap_dir/fsyacc fi if [ ! -f "$bootstrap_dir/fsc.exe" ]; then MSBuild "$repo_root/proto.proj" \ /restore \ /v:$verbosity \ /p:Configuration=$bootstrap_config \ - /t:Build + /t:Publish - cp $artifacts_dir/bin/fsc/$bootstrap_config/netcoreapp2.1/* $bootstrap_dir + cp -pr $artifacts_dir/bin/fsc/$bootstrap_config/netcoreapp2.1/publish $bootstrap_dir/fsc fi # do real build diff --git a/fcs/Directory.Build.props b/fcs/Directory.Build.props index 596b06c0716..4c8aac0a5b6 100644 --- a/fcs/Directory.Build.props +++ b/fcs/Directory.Build.props @@ -20,9 +20,4 @@ $(ArtifactsObjDir)\fcs true - - - - $(ArtifactsBinDir)\FSharp.Build\Proto\net472 - diff --git a/proto.proj b/proto.proj index 84103f6fdf8..b0ee288977f 100644 --- a/proto.proj +++ b/proto.proj @@ -28,6 +28,10 @@ + + + + diff --git a/src/buildtools/buildtools.targets b/src/buildtools/buildtools.targets index 303ab00825d..185fd4d0599 100644 --- a/src/buildtools/buildtools.targets +++ b/src/buildtools/buildtools.targets @@ -20,7 +20,7 @@ BeforeTargets="CoreCompile"> - $(ArtifactsDir)\Bootstrap\fslex.dll + $(ArtifactsDir)\Bootstrap\fslex\fslex.dll @@ -43,7 +43,7 @@ BeforeTargets="CoreCompile"> - $(ArtifactsDir)\Bootstrap\fsyacc.dll + $(ArtifactsDir)\Bootstrap\fsyacc\fsyacc.dll From 688850f47922d2b9134331d7d4d3c2cf5a04a7e7 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 16 Apr 2019 00:13:17 +0100 Subject: [PATCH 65/77] revert test env changes --- FSharpTests.Directory.Build.props | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/FSharpTests.Directory.Build.props b/FSharpTests.Directory.Build.props index 9ad765f036d..7b9242dc0db 100644 --- a/FSharpTests.Directory.Build.props +++ b/FSharpTests.Directory.Build.props @@ -22,19 +22,19 @@ $([System.IO.Path]::GetDirectoryName('$(DOTNET_HOST_PATH)')) dotnet.exe dotnet - $(MSBuildThisFileDirectory)artifacts\bin\fsc\$(Configuration)\netcoreapp2.1\publish\fsc.exe + $(MSBuildThisFileDirectory)artifacts\bin\fsc\$(Configuration)\netcoreapp2.1\fsc.exe $([System.IO.Path]::GetDirectoryName('$(DOTNET_HOST_PATH)')) dotnet.exe dotnet - $(MSBuildThisFileDirectory)artifacts\bin\fsi\$(Configuration)\netcoreapp2.1\publish\fsi.exe + $(MSBuildThisFileDirectory)artifacts\bin\fsi\$(Configuration)\netcoreapp2.1\fsi.exe <_FSharpBuildTargetFramework Condition="'$(MSBuildRuntimeType)'!='Core'">net472 <_FSharpBuildTargetFramework Condition="'$(MSBuildRuntimeType)'=='Core'">netcoreapp2.1 - <_FSharpBuildBinPath>$(MSBuildThisFileDirectory)artifacts\bin\fsc\$(Configuration)\$(_FSharpBuildTargetFramework)\publish + <_FSharpBuildBinPath>$(MSBuildThisFileDirectory)artifacts\bin\fsc\$(Configuration)\$(_FSharpBuildTargetFramework) $(_FSharpBuildBinPath)\FSharp.Build.dll From c2c7213ed66f7d415db2c1a53249a325b74986bf Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 16 Apr 2019 01:27:25 +0100 Subject: [PATCH 66/77] revert testing changes --- FSharpTests.Directory.Build.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FSharpTests.Directory.Build.props b/FSharpTests.Directory.Build.props index 7b9242dc0db..8a7a832a43e 100644 --- a/FSharpTests.Directory.Build.props +++ b/FSharpTests.Directory.Build.props @@ -7,11 +7,11 @@ true - $(MSBuildThisFileDirectory)artifacts\bin\fsc\$(Configuration)\net472\publish + $(MSBuildThisFileDirectory)artifacts\bin\fsc\$(Configuration)\net472 fsc.exe - $(MSBuildThisFileDirectory)artifacts\bin\fsi\$(Configuration)\net472\publish + $(MSBuildThisFileDirectory)artifacts\bin\fsi\$(Configuration)\net472 fsi.exe From ee8b00d6f8c40e3b67a9aee6e23555f7a5fef959 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 16 Apr 2019 11:44:19 +0100 Subject: [PATCH 67/77] fix build --- src/fsharp/IlxGen.fs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 854ceeaa3b2..6d8210af658 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -2900,7 +2900,8 @@ and GenUntupledArgExpr cenv cgbuf eenv m argInfos expr sequel = // Generate calls (try to detect direct calls) //-------------------------------------------------------------------------- -and GenApp cenv cgbuf eenv (f, fty, tyargs, curriedArgs, m) sequel = +and GenApp (cenv: cenv) cgbuf eenv (f, fty, tyargs, curriedArgs, m) sequel = + let g = cenv.g match (f, tyargs, curriedArgs) with // Look for tailcall to turn into branch | (Expr.Val (v, _, _), _, _) when @@ -3215,6 +3216,7 @@ and GenCurriedArgsAndIndirectCall cenv cgbuf eenv (functy, tyargs, curriedArgs, /// Generate an indirect call, converting to an ILX callfunc instruction and GenIndirectCall cenv cgbuf eenv (functy, tyargs, curriedArgs, m) sequel = + let g = cenv.g // Fold in the new types into the environment as we generate the formal types. let ilxClosureApps = @@ -5604,7 +5606,7 @@ and GenParams cenv eenv m (mspec: ILMethodSpec) witnessInfos (argInfos: ArgReprI | None -> match implValOpt with | Some v -> Some v.Id - | None -> None + | None -> None let nmOpt, takenNames = match idOpt with @@ -6168,7 +6170,8 @@ and CommitGetStorageSequel cenv cgbuf eenv m ty localCloInfo fetchSequel = | _, Some (tyargs, args, m, sequel) -> GenCurriedArgsAndIndirectCall cenv cgbuf eenv (ty, tyargs, args, m) sequel -and GenGetStorageAndSequel cenv cgbuf eenv m (ty, ilTy) storage fetchSequel = +and GenGetStorageAndSequel (cenv: cenv) cgbuf eenv m (ty, ilTy) storage fetchSequel = + let g = cenv.g match storage with | Local (idx, _, localCloInfo) -> EmitGetLocal cgbuf ilTy idx @@ -6851,6 +6854,7 @@ and GenAbstractBinding cenv eenv tref (vref: ValRef) = /// Generate a ToString method that calls 'sprintf "%A"' and GenToStringMethod cenv eenv ilThisTy m = + let g = cenv.g [ match (eenv.valsInScope.TryFind cenv.g.sprintf_vref.Deref, eenv.valsInScope.TryFind cenv.g.new_format_vref.Deref) with | Some(Lazy(Method(_, _, sprintfMethSpec, _, _, _, _, _, _, _, _, _))), Some(Lazy(Method(_, _, newFormatMethSpec, _, _, _, _, _, _, _, _, _))) -> From e46dcd5681fdcf52b889c145799dc96a668613ee Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 16 Apr 2019 15:19:09 +0100 Subject: [PATCH 68/77] don't repeat bootstrap --- eng/Build.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Build.ps1 b/eng/Build.ps1 index 30ef852db76..04bee5a40d8 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -128,7 +128,7 @@ function Process-Arguments() { } function Update-Arguments() { - if (-Not (Test-Path "$ArtifactsDir\Bootstrap\fsc.exe")) { + if (-Not (Test-Path "$ArtifactsDir\Bootstrap\fsc\fsc.exe")) { $script:bootstrap = $True } } From de8ff29ccfe3ab019252039f673c3a401a3611fd Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 16 Apr 2019 15:50:30 +0100 Subject: [PATCH 69/77] fix ceiling operator --- eng/Build.ps1 | 2 +- src/fsharp/FSharp.Core/prim-types.fs | 74 +++++++++++++++++++++++----- src/fsharp/TcGlobals.fs | 3 +- 3 files changed, 64 insertions(+), 15 deletions(-) diff --git a/eng/Build.ps1 b/eng/Build.ps1 index 30ef852db76..04bee5a40d8 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -128,7 +128,7 @@ function Process-Arguments() { } function Update-Arguments() { - if (-Not (Test-Path "$ArtifactsDir\Bootstrap\fsc.exe")) { + if (-Not (Test-Path "$ArtifactsDir\Bootstrap\fsc\fsc.exe")) { $script:bootstrap = $True } } diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 42d07e65e54..608273c8051 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -3098,13 +3098,23 @@ namespace Microsoft.FSharp.Core let UnaryDynamicImpl nm : ('T -> 'U) = let aty = typeof<'T> - let minfo = aty.GetRuntimeMethod(nm, [| aty |]) +#if FX_RESHAPED_REFLECTION + let minfo = aty.GetMethod(nm, [| aty |]) +#else + let staticBindingFlags = (# "" 0b111000 : BindingFlags #) // BindingFlags.Static ||| BindingFlags.Public ||| BindingFlags.NonPublic) + let minfo = aty.GetMethod(nm, staticBindingFlags, null, [| aty |], null ) +#endif (fun x -> unboxPrim<_>(minfo.Invoke(null,[| box x|]))) let BinaryDynamicImpl nm : ('T -> 'U -> 'V) = let aty = typeof<'T> let bty = typeof<'U> - let minfo = aty.GetRuntimeMethod(nm,[| aty;bty |]) +#if FX_RESHAPED_REFLECTION + let minfo = aty.GetMethod(nm,[| aty;bty |]) +#else + let staticBindingFlags = (# "" 0b111000 : BindingFlags #) // BindingFlags.Static ||| BindingFlags.Public ||| BindingFlags.NonPublic) + let minfo = aty.GetMethod(nm, staticBindingFlags, null, [| aty; bty |], null ) +#endif (fun x y -> unboxPrim<_>(minfo.Invoke(null,[| box x; box y|]))) // Dynamic implementation of operator resolution, using BuiltInWitnesses as backing data @@ -3115,10 +3125,18 @@ namespace Microsoft.FSharp.Core let bty = typeof<'U> // Find the operator name - //let staticBindingFlags = (BindingFlags.Static ||| BindingFlags.Public ||| BindingFlags.NonPublic) - let opNameMeth = typeof<'OpInfo>.GetRuntimeMethod("get_Name", [| |] (*, staticBindingFlags, [| |], null*) ) +#if FX_RESHAPED_REFLECTION + let opNameMeth = typeof<'OpInfo>.GetMethod("get_Name", [| |]) +#else + let staticBindingFlags = (# "" 0b111000 : BindingFlags #) // BindingFlags.Static ||| BindingFlags.Public ||| BindingFlags.NonPublic) + let opNameMeth = typeof<'OpInfo>.GetMethod("get_Name", staticBindingFlags, null, [| |], null) +#endif let opName = opNameMeth.Invoke(null, [| |]) :?> string - let builtinNameMeth = typeof<'OpInfo>.GetTypeInfo().GetMethod("get_BuiltInName", (* staticBindingFlags, *) [| |] (*, null *) ) +#if FX_RESHAPED_REFLECTION + let builtinNameMeth = typeof<'OpInfo>.GetTypeInfo().GetMethod("get_BuiltInName", [| |]) +#else + let builtinNameMeth = typeof<'OpInfo>.GetMethod("get_BuiltInName", staticBindingFlags, null, [| |], null) +#endif let builtinName = match builtinNameMeth with null -> opName | _ -> builtinNameMeth.Invoke(null, [| |]) :?> string let meth = @@ -3134,11 +3152,19 @@ namespace Microsoft.FSharp.Core res <- meth res else - witnessesTy.GetRuntimeMethod(builtinName, (* , staticBindingFlags *) [| aty |] (* , null *) ) +#if FX_RESHAPED_REFLECTION + witnessesTy.GetMethod(builtinName, [| aty |]) +#else + witnessesTy.GetMethod(builtinName, staticBindingFlags, null, [| aty |], null) +#endif match cmeth with | null -> - let ameth = aty.GetRuntimeMethod(opName, [| aty |]) +#if FX_RESHAPED_REFLECTION + let ameth = aty.GetMethod(opName, [| aty |]) +#else + let ameth = aty.GetMethod(opName, staticBindingFlags, null, [| aty |], null) +#endif match ameth with | null -> raise (NotSupportedException (SR.GetString(SR.dyInvOpAddCoerce))) | res -> res @@ -3155,19 +3181,41 @@ namespace Microsoft.FSharp.Core let bty = typeof<'U> // Find the operator name - //let staticBindingFlags = (BindingFlags.Static ||| BindingFlags.Public ||| BindingFlags.NonPublic) - let opNameMeth = typeof<'OpInfo>.GetRuntimeMethod("get_Name" (* , staticBindingFlags *) , [| |] (*, null *) ) +#if FX_RESHAPED_REFLECTION + let opNameMeth = typeof<'OpInfo>.GetMethod("get_Name", [| |]) +#else + let staticBindingFlags = (# "" 0b111000 : BindingFlags #) // BindingFlags.Static ||| BindingFlags.Public ||| BindingFlags.NonPublic) + let opNameMeth = typeof<'OpInfo>.GetMethod("get_Name", staticBindingFlags, null, [| |], null) +#endif let opName = opNameMeth.Invoke(null, [| |]) :?> string - let builtinNameMeth = typeof<'OpInfo>.GetRuntimeMethod("get_BuiltInName" (*, staticBindingFlags *) , [| |] (*, null *) ) +#if FX_RESHAPED_REFLECTION + let builtinNameMeth = typeof<'OpInfo>.GetMethod("get_BuiltInName", [| |]) +#else + let builtinNameMeth = typeof<'OpInfo>.GetMethod("get_BuiltInName", staticBindingFlags, null, [| |], null) +#endif let builtinName = match builtinNameMeth with null -> opName | _ -> builtinNameMeth.Invoke(null, [| |]) :?> string let meth = let witnessesTy = typeof - let cmeth = witnessesTy.GetRuntimeMethod(builtinName (*, staticBindingFlags *) , [| aty; bty |] (*, null *) ) +#if FX_RESHAPED_REFLECTION + let cmeth = witnessesTy.GetMethod(builtinName, [| aty; bty |]) +#else + let cmeth = witnessesTy.GetMethod(builtinName, staticBindingFlags, null, [| aty; bty |], null) +#endif match cmeth with | null -> - let ameth = aty.GetRuntimeMethod(opName, [| aty; bty |]) - let bmeth = if aty.Equals(bty) then null else bty.GetRuntimeMethod(opName, [| aty; bty |]) +#if FX_RESHAPED_REFLECTION + let ameth = aty.GetMethod(opName, [| aty; bty |]) +#else + let ameth = aty.GetMethod(opName, staticBindingFlags, null, [| aty; bty |], null) +#endif + let bmeth = + if aty.Equals(bty) then null else +#if FX_RESHAPED_REFLECTION + bty.GetMethod(opName, [| aty; bty |]) +#else + bty.GetMethod(opName, staticBindingFlags, null, [| aty; bty |], null) +#endif match ameth, bmeth with | null, null -> raise (NotSupportedException (SR.GetString(SR.dyInvOpAddCoerce))) | m, null | null, m -> m diff --git a/src/fsharp/TcGlobals.fs b/src/fsharp/TcGlobals.fs index 9e7cf1f7a86..62cf3736245 100755 --- a/src/fsharp/TcGlobals.fs +++ b/src/fsharp/TcGlobals.fs @@ -1532,7 +1532,8 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d | ("Abs" | "Sin" | "Cos" | "Tan" | "Sinh" | "Cosh" | "Tanh" | "Atan" | "Acos" | "Asin" | "Exp" | "Ceiling" | "Floor" | "Round" | "Truncate" | "Log10"| "Log"), [aty], _, [_] -> // Call corresponding Operators.* let nm = t.MemberName - let info = makeOtherIntrinsicValRef (fslib_MFOperators_nleref, nm.ToLowerInvariant(), None, Some nm, [vara], ([[varaTy]], varaTy)) + let lower = if nm = "Ceiling" then "ceil" else nm.ToLowerInvariant() + let info = makeOtherIntrinsicValRef (fslib_MFOperators_nleref, lower, None, Some nm, [vara], ([[varaTy]], varaTy)) let tyargs = [aty] Some (info, tyargs, argExprs) | "get_Item", [arrTy; _], Some rty, [_; _] when isArrayTy g arrTy -> From 75e9cc3f7baa083aa3717a0a54bfa61ce0671bfc Mon Sep 17 00:00:00 2001 From: Don Syme Date: Wed, 17 Apr 2019 13:23:04 +0100 Subject: [PATCH 70/77] be systematic about verbosity --- eng/build-utils.ps1 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/eng/build-utils.ps1 b/eng/build-utils.ps1 index c16e31ebfc2..f85a9007296 100644 --- a/eng/build-utils.ps1 +++ b/eng/build-utils.ps1 @@ -178,7 +178,7 @@ function Get-PackageDir([string]$name, [string]$version = "") { return $p } -function Run-MSBuild([string]$projectFilePath, [string]$buildArgs = "", [string]$logFileName = "", [switch]$parallel = $true, [switch]$summary = $true, [switch]$warnAsError = $true, [string]$configuration = $script:configuration) { +function Run-MSBuild([string]$projectFilePath, [string]$buildArgs = "", [string]$logFileName = "", [switch]$parallel = $true, [switch]$summary = $true, [switch]$warnAsError = $true, [string]$configuration = $script:configuration, [string]$verbosity = $script:verbosity) { # Because we override the C#/VB toolset to build against our LKG package, it is important # that we do not reuse MSBuild nodes from other jobs/builds on the machine. Otherwise, # we'll run into issues such as https://github.com/dotnet/roslyn/issues/6211. @@ -190,9 +190,9 @@ function Run-MSBuild([string]$projectFilePath, [string]$buildArgs = "", [string] } if ($summary) { - $args += " /consoleloggerparameters:Verbosity=minimal;summary" + $args += " /consoleloggerparameters:Verbosity=$verbosity;summary" } else { - $args += " /consoleloggerparameters:Verbosity=minimal" + $args += " /consoleloggerparameters:Verbosity=$verbosity" } if ($parallel) { @@ -237,13 +237,13 @@ function Make-BootstrapBuild() { Create-Directory $dir # prepare FsLex and Fsyacc - Run-MSBuild "$RepoRoot\src\buildtools\buildtools.proj" "/restore /t:Publish" -logFileName "BuildTools" -configuration $bootstrapConfiguration + Run-MSBuild "$RepoRoot\src\buildtools\buildtools.proj" "/restore /t:Publish" -logFileName "BuildTools" -configuration $bootstrapConfiguration -verbosity $verbosity Copy-Item "$ArtifactsDir\bin\fslex\$bootstrapConfiguration\netcoreapp2.1\publish" -Destination "$dir\fslex" -Force -Recurse Copy-Item "$ArtifactsDir\bin\fsyacc\$bootstrapConfiguration\netcoreapp2.1\publish" -Destination "$dir\fsyacc" -Force -Recurse # prepare compiler $projectPath = "$RepoRoot\proto.proj" - Run-MSBuild $projectPath "/restore /t:Publish" -logFileName "Bootstrap" -configuration $bootstrapConfiguration + Run-MSBuild $projectPath "/restore /t:Publish" -logFileName "Bootstrap" -configuration $bootstrapConfiguration -verbosity $verbosity Copy-Item "$ArtifactsDir\bin\fsc\$bootstrapConfiguration\$bootstrapTfm\publish" -Destination "$dir\fsc" -Force -Recurse Copy-Item "$ArtifactsDir\bin\fsi\$bootstrapConfiguration\$bootstrapTfm\publish" -Destination "$dir\fsi" -Force -Recurse From 9cd00b160f0d6d93620509a00f5b3d289e8f2643 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 18 Apr 2019 15:16:42 +0100 Subject: [PATCH 71/77] various fixes --- src/fsharp/ConstraintSolver.fs | 2 +- src/fsharp/ConstraintSolver.fsi | 2 +- src/fsharp/FSharp.Core/prim-types.fs | 2 +- src/fsharp/FSharp.Core/prim-types.fsi | 2 +- src/fsharp/IlxGen.fs | 359 ++++++++++++++++---------- src/fsharp/MethodCalls.fs | 12 +- src/fsharp/QuotationTranslator.fs | 7 +- tests/fsharp/core/quotes/test.fsx | 65 +++++ 8 files changed, 301 insertions(+), 150 deletions(-) diff --git a/src/fsharp/ConstraintSolver.fs b/src/fsharp/ConstraintSolver.fs index 553d3ef8c08..30c22a867c8 100644 --- a/src/fsharp/ConstraintSolver.fs +++ b/src/fsharp/ConstraintSolver.fs @@ -2773,7 +2773,7 @@ let CodegenWitnessesForTyparInst tcVal g amap m typars tyargs = trackErrors { let ftps, _renaming, tinst = FreshenTypeInst m typars let cxs = GetTraitConstraintInfosOfTypars g ftps do! SolveTypeEqualsTypeEqns csenv 0 m NoTrace None tinst tyargs - return MethodCalls.GenWitnessArgs amap g m cxs + return MethodCalls.GenNonGenericWitnessArgs amap g m cxs } let ChooseTyparSolutionAndSolve css denv tp = diff --git a/src/fsharp/ConstraintSolver.fsi b/src/fsharp/ConstraintSolver.fsi index b648a29113a..43e96302774 100644 --- a/src/fsharp/ConstraintSolver.fsi +++ b/src/fsharp/ConstraintSolver.fsi @@ -142,7 +142,7 @@ val AddCxTypeIsDelegate : DisplayEnv -> ConstraintSolverSt val CodegenWitnessForTraitConstraint : TcValF -> TcGlobals -> ImportMap -> range -> TraitConstraintInfo -> Expr list -> OperationResult -val CodegenWitnessesForTyparInst : TcValF -> TcGlobals -> ImportMap -> range -> Typars -> TType list -> OperationResult +val CodegenWitnessesForTyparInst : TcValF -> TcGlobals -> ImportMap -> range -> Typars -> TType list -> OperationResult list> val ChooseTyparSolutionAndSolve : ConstraintSolverState -> DisplayEnv -> Typar -> unit diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 608273c8051..9f4a31706bd 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -2943,7 +2943,7 @@ namespace Microsoft.FSharp.Core static member inline op_LessThanOrEqual(x: uint32, y: uint32) = not (# "cgt.un" x y : bool #) static member inline op_LessThanOrEqual(x: uint64, y: uint64) = not (# "cgt.un" x y : bool #) static member inline op_LessThanOrEqual(x: unativeint, y: unativeint) = not (# "cgt.un" x y : bool #) - static member inline op_LessThanOrEqual(x: float, y: unativeint) = not (# "cgt.un" x y : bool #) + static member inline op_LessThanOrEqual(x: float, y: float) = not (# "cgt.un" x y : bool #) static member inline op_LessThanOrEqual(x: float32, y: float32) = not (# "cgt.un" x y : bool #) static member inline op_LessThanOrEqual(x: char, y: char) = not (# "cgt" x y : bool #) static member inline op_LessThanOrEqual(x: decimal, y: decimal) = Decimal.op_LessThanOrEqual (x, y) diff --git a/src/fsharp/FSharp.Core/prim-types.fsi b/src/fsharp/FSharp.Core/prim-types.fsi index ee320825f89..4290c15d693 100644 --- a/src/fsharp/FSharp.Core/prim-types.fsi +++ b/src/fsharp/FSharp.Core/prim-types.fsi @@ -2308,7 +2308,7 @@ namespace Microsoft.FSharp.Core static member inline op_LessThanOrEqual: x: unativeint * y: unativeint -> bool /// A representative witness for traits solved by the F# compiler - static member inline op_LessThanOrEqual: x: float * y: unativeint -> bool + static member inline op_LessThanOrEqual: x: float * y: float -> bool /// A representative witness for traits solved by the F# compiler static member inline op_LessThanOrEqual: x: float32 * y: float32 -> bool diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 6d8210af658..e119353901e 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -685,10 +685,10 @@ type IlxClosureInfo = cloArityInfo: ArityInfo /// The formal return type - cloILFormalRetTy: ILType + ilCloFormalReturnTy: ILType /// An immutable array of free variable descriptions for the closure - cloILFreeVars: IlxClosureFreeVar[] + ilCloAllFreeVars: IlxClosureFreeVar[] /// The ILX specification for the closure cloSpec: IlxClosureSpec @@ -699,9 +699,11 @@ type IlxClosureInfo = /// The generic parameters for the closure, i.e. the type variables it captures cloILGenericParams: IL.ILGenericParameterDefs - /// The free variables for the closure, i.e. the values it captures + /// The captured variables for the closure cloFreeVars: Val list + cloFreeTyvars: Typars + /// ILX view of the lambdas for the closures ilCloLambdas: IlxClosureLambdas @@ -748,7 +750,7 @@ type ValStorage = | Method of ValReprInfo * ValRef * ILMethodSpec * ILMethodSpec * Range.range * Typars * Typars * CurriedArgInfos * ArgReprInfo list * TraitWitnessInfos * TType list * ArgReprInfo /// Indicates the value is stored at the given position in the closure environment accessed via "ldarg 0" - | Env of ILType * int * ILFieldSpec * NamedLocalIlxClosureInfo ref option + | Env of ILType * ILFieldSpec * NamedLocalIlxClosureInfo ref option /// Indicates that the value is an argument of a method being generated | Arg of int @@ -785,11 +787,13 @@ and BranchCallItem = ArityInfo * // Arg infos for compiled form of F# method or value (TType * ArgReprInfo) list list * - // Typars for F# method or value - Tast.Typars * - // Typars for F# method or value + // Typars the F# method or value + Typars * + // num obj args in IL + int * + // num witness args in IL int * - // num obj args + // num actual args in IL int /// Represents a place we can branch to @@ -887,9 +891,9 @@ let AddStorageForLocalVals g vals eenv = List.foldBack (fun (v, s) acc -> AddStorageForVal g (v, notlazy s) acc) vals eenv let AddStorageForLocalWitness eenv (w,s) = - { eenv with witnessesInScope = eenv.witnessesInScope.Add (w, s) } + { eenv with witnessesInScope = eenv.witnessesInScope.SetItem (w, s) } -let AddStorageForLocalWitnesses eenv witnesses = +let AddStorageForLocalWitnesses witnesses eenv = (eenv, witnesses) ||> List.fold AddStorageForLocalWitness //-------------------------------------------------------------------------- @@ -907,6 +911,11 @@ let StorageForVal m v eenv = let StorageForValRef m (v: ValRef) eenv = StorageForVal m v.Deref eenv +let TryStorageForWitness eenv (w: TraitWitnessInfo) = + match eenv.witnessesInScope.TryGetValue w with + | true, storage -> Some storage + | _ -> None // failwithf "no storage for witness %s found in scope" w.MemberName + let IsValRefIsDllImport g (vref: ValRef) = vref.Attribs |> HasFSharpAttributeOpt g g.attrib_DllImportAttribute @@ -1559,7 +1568,7 @@ type AssemblyBuilder(cenv: cenv, anonTypeTable: AnonTypeGenerationTable) as mgbu member mgbuf.GetCurrentFields(tref: ILTypeRef) = gtdefs.FindNestedTypeDefBuilder(tref).GetCurrentFields() - member mgbuf.AddReflectedDefinition(vspec: Tast.Val, expr) = + member mgbuf.AddReflectedDefinition(vspec: Val, expr) = // preserve order by storing index of item let n = reflectedDefinitions.Count reflectedDefinitions.Add(vspec, (vspec.CompiledName, n, expr)) @@ -1781,7 +1790,9 @@ type CodeGenBuffer(m: range, res member cgbuf.mgbuf = mgbuf + member cgbuf.MethodName = methodName + member cgbuf.PreallocatedArgCount = alreadyUsedArgs member cgbuf.AllocLocal(ranges, ty, isFixed) = @@ -1903,10 +1914,10 @@ let discardAndReturnVoid = DiscardThen ReturnVoid // the bodies of methods in a couple of places //------------------------------------------------------------------------- -let CodeGenThen cenv mgbuf (entryPointInfo, methodName, eenv, alreadyUsedArgs, codeGenFunction, m) = +let CodeGenThen cenv mgbuf (tailCallInfo, methodName, eenv, alreadyUsedArgs, codeGenFunction, m) = let cgbuf = new CodeGenBuffer(m, mgbuf, methodName, alreadyUsedArgs) let start = CG.GenerateMark cgbuf "mstart" - let innerVals = entryPointInfo |> List.map (fun (v, kind) -> (v, (kind, start))) + let innerVals = tailCallInfo |> List.map (fun (v, kind) -> (v, (kind, start))) (* Call the given code generator *) codeGenFunction cgbuf {eenv with withinSEH=false @@ -1947,10 +1958,10 @@ let CodeGenThen cenv mgbuf (entryPointInfo, methodName, eenv, alreadyUsedArgs, c localDebugSpecs, hasSequencePoints) -let CodeGenMethod cenv mgbuf (entryPointInfo, methodName, eenv, alreadyUsedArgs, codeGenFunction, m) = +let CodeGenMethod cenv mgbuf (tailCallInfo, methodName, eenv, alreadyUsedArgs, codeGenFunction, m) = let locals, maxStack, lab2pc, instrs, exns, localDebugSpecs, hasSequencePoints = - CodeGenThen cenv mgbuf (entryPointInfo, methodName, eenv, alreadyUsedArgs, codeGenFunction, m) + CodeGenThen cenv mgbuf (tailCallInfo, methodName, eenv, alreadyUsedArgs, codeGenFunction, m) let code = IL.buildILCode methodName lab2pc instrs exns localDebugSpecs @@ -2336,9 +2347,9 @@ let rec GenExpr (cenv: cenv) (cgbuf: CodeGenBuffer) eenv sp expr sequel = and GenExprs cenv cgbuf eenv es = List.iter (fun e -> GenExpr cenv cgbuf eenv SPSuppress e Continue) es -and CodeGenMethodForExpr cenv mgbuf (spReq, entryPointInfo, methodName, eenv, alreadyUsedArgs, expr0, sequel0) = +and CodeGenMethodForExpr cenv mgbuf (spReq, tailCallInfo, methodName, eenv, alreadyUsedArgs, expr0, sequel0) = let _, code = - CodeGenMethod cenv mgbuf (entryPointInfo, methodName, eenv, alreadyUsedArgs, + CodeGenMethod cenv mgbuf (tailCallInfo, methodName, eenv, alreadyUsedArgs, (fun cgbuf eenv -> GenExpr cenv cgbuf eenv spReq expr0 sequel0), expr0.Range) code @@ -2900,6 +2911,28 @@ and GenUntupledArgExpr cenv cgbuf eenv m argInfos expr sequel = // Generate calls (try to detect direct calls) //-------------------------------------------------------------------------- +and GenWitnessArgs cenv cgbuf eenv m tps tyargs = + let g = cenv.g + let inWitnessPassingScope = not eenv.witnessesInScope.IsEmpty + // Witness arguments are only generated in emitted 'inline' code where witness parameters are available. + if g.generateWitnesses && inWitnessPassingScope then + let mwitnesses = + ConstraintSolver.CodegenWitnessesForTyparInst cenv.tcVal g cenv.amap m tps tyargs + |> CommitOperationResult + + for witnessArg in mwitnesses do + match witnessArg with + | Choice1Of2 witnessInfo -> + let storage = TryStorageForWitness eenv witnessInfo + match storage with + | None -> + System.Diagnostics.Debug.Assert(false, "expected storage for witness") + | Some storage -> + let ty = GenWitnessTy g witnessInfo + GenGetStorageAndSequel cenv cgbuf eenv m (ty, GenType cenv.amap m eenv.tyenv ty) storage None + | Choice2Of2 arg -> + GenExpr cenv cgbuf eenv SPSuppress arg Continue + and GenApp (cenv: cenv) cgbuf eenv (f, fty, tyargs, curriedArgs, m) sequel = let g = cenv.g match (f, tyargs, curriedArgs) with @@ -2911,13 +2944,13 @@ and GenApp (cenv: cenv) cgbuf eenv (f, fty, tyargs, curriedArgs, m) sequel = // when branch-calling methods we must have the right type parameters (match kind with | BranchCallClosure _ -> true - | BranchCallMethod (_, _, tps, _, _) -> + | BranchCallMethod (_, _, tps, _, _, _) -> (List.lengthsEqAndForall2 (fun ty tp -> typeEquiv cenv.g ty (mkTyparTy tp)) tyargs tps)) && // must be exact #args, ignoring tupling - we untuple if needed below (let arityInfo = match kind with | BranchCallClosure arityInfo - | BranchCallMethod (arityInfo, _, _, _, _) -> arityInfo + | BranchCallMethod (arityInfo, _, _, _, _, _) -> arityInfo arityInfo.Length = curriedArgs.Length ) && (* no tailcall out of exception handler, etc. *) @@ -2925,26 +2958,51 @@ and GenApp (cenv: cenv) cgbuf eenv (f, fty, tyargs, curriedArgs, m) sequel = | None -> false -> let (kind, mark) = ListAssoc.find g.valRefEq v eenv.innerVals // already checked above in when guard - let ntmargs = - match kind with - | BranchCallClosure arityInfo -> - let ntmargs = List.foldBack (+) arityInfo 0 - GenExprs cenv cgbuf eenv curriedArgs - ntmargs - | BranchCallMethod (arityInfo, curriedArgInfos, _, ntmargs, numObjArgs) -> - assert (curriedArgInfos.Length = arityInfo.Length ) - assert (curriedArgInfos.Length = curriedArgs.Length) - //assert (curriedArgInfos.Length = ntmargs ) - GenUntupledArgsDiscardingLoneUnit cenv cgbuf eenv m numObjArgs curriedArgInfos curriedArgs - if v.IsExtensionMember then - match curriedArgInfos, curriedArgs with - | [[]], [_] when numObjArgs = 0 -> (ntmargs-1) - | [[_];[]], [_;_] when numObjArgs = 1 -> (ntmargs-1) - | _ -> ntmargs - else ntmargs - - for i = ntmargs - 1 downto 0 do - CG.EmitInstrs cgbuf (pop 1) Push0 [ I_starg (uint16 (i+cgbuf.PreallocatedArgCount)) ] + + // Generate the arguments for the direct tail call. + // We push all the arguments on the IL stack then write them back to the argument slots using + // I_starg. This seems a little sloppy, we could generate-then-write for each of the arguments. + // + // The arguments pushed don't include the 'this' argument for a recursive closure call (in PreallocatedArgCount) + // The arguments _do_ include the 'this' argument for instance method calls. The arguments do _not_ include witness arguments. + match kind with + | BranchCallClosure arityInfo -> + GenExprs cenv cgbuf eenv curriedArgs + + let numArgs = List.sum arityInfo + + // TODO: witness argument generation for closures + for i = numArgs - 1 downto 0 do + CG.EmitInstrs cgbuf (pop 1) Push0 [ I_starg (uint16 (cgbuf.PreallocatedArgCount+i)) ] + + | BranchCallMethod (arityInfo, curriedArgInfos, _, numObjArgs, numWitnessArgs, numMethodArgs) -> + assert (curriedArgInfos.Length = arityInfo.Length ) + assert (curriedArgInfos.Length = curriedArgs.Length) + + //assert (curriedArgInfos.Length = numArgs ) + // NOTE: we are not generating the witness arguments here + GenUntupledArgsDiscardingLoneUnit cenv cgbuf eenv m numObjArgs curriedArgInfos curriedArgs + + // Extension methods with empty arguments are evidently not quite in sufficiently normalized form, + // so apply a fixup here. This feels like a mistake associated with BindUnitVars, where that is not triggering + // in this case. + let numArgs = + if v.IsExtensionMember then + match curriedArgInfos, curriedArgs with + // static extension method with empty arguments. + | [[]], [_] when numObjArgs = 0 -> 0 + // instance extension method with empty arguments. + | [[_];[]], [_;_] when numObjArgs = 1 -> 0 + | _ -> numMethodArgs + else numMethodArgs + + for i = numArgs - 1 downto 0 do + CG.EmitInstrs cgbuf (pop 1) Push0 [ I_starg (uint16 (cgbuf.PreallocatedArgCount+numObjArgs+numWitnessArgs+i)) ] + + // Note, we don't reassign the witness arguments as these wont' have changed, because the type parameters aren't identical + + for i = numObjArgs - 1 downto 0 do + CG.EmitInstrs cgbuf (pop 1) Push0 [ I_starg (uint16 (cgbuf.PreallocatedArgCount+i)) ] CG.EmitInstrs cgbuf (pop 0) Push0 [ I_br mark.CodeLabel ] @@ -3024,33 +3082,6 @@ and GenApp (cenv: cenv) cgbuf eenv (f, fty, tyargs, curriedArgs, m) sequel = else mspecW - let witnessArgs = - if not cenv.g.generateWitnesses || cxs.IsEmpty then - [] - else - let _ctyargs, mtyargs = List.splitAt ctps.Length tyargs - - // Witness for enclosing type parameters are not currently allowed, because these can never be 'inline'. - // Regardless, even if they were they must be passed to static members and constructors - // For non-extension instance methods would be stored as fields, if they were permitted. - //let cwitnesses = - // if vref.IsInstanceMember && not vref.IsExtensionMember then - // [] - // else - // ConstraintSolver.CodegenWitnessesForTyparInst cenv.tcVal cenv.g cenv.amap m ctps ctyargs - // |> CommitOperationResult - // |> List.map snd - - // We currently should never have any class-quantified witnesses - //assert cwitnesses.IsEmpty - - let mwitnesses = - ConstraintSolver.CodegenWitnessesForTyparInst cenv.tcVal cenv.g cenv.amap m mtps mtyargs - |> CommitOperationResult - - mwitnesses - - let nowArgs = witnessArgs @ nowArgs let ilTyArgs = GenTypeArgs cenv.amap m eenv.tyenv tyargs @@ -3109,6 +3140,14 @@ and GenApp (cenv: cenv) cgbuf eenv (f, fty, tyargs, curriedArgs, m) sequel = if isSuperInit || isSelfInit then CG.EmitInstrs cgbuf (pop 0) (Push [mspec.DeclaringType ]) [ mkLdarg0 ] + // We currently should never have any class-quantified witnesses + //assert cwitnesses.IsEmpty + if not cenv.g.generateWitnesses || cxs.IsEmpty then + () // not witness args + else + let _ctyargs, mtyargs = List.splitAt ctps.Length tyargs + GenWitnessArgs cenv cgbuf eenv m mtps mtyargs + GenUntupledArgsDiscardingLoneUnit cenv cgbuf eenv m vref.NumObjArgs curriedArgInfos nowArgs // Generate laterArgs (for effects) and save @@ -3811,11 +3850,10 @@ and MakeNotSupportedExnExpr cenv eenv (argExpr, m) = and GenTraitCall (cenv: cenv) cgbuf eenv (traitInfo: TraitConstraintInfo, argExprs, m) expr sequel = let g = cenv.g + let inWitnessPassingScope = not eenv.witnessesInScope.IsEmpty let witness = - if g.generateWitnesses then - match eenv.witnessesInScope.TryGetValue traitInfo.TraitKey with - | true, storage -> Some storage - | _ -> None + if g.generateWitnesses && inWitnessPassingScope then + TryStorageForWitness eenv traitInfo.TraitKey else None @@ -3828,7 +3866,7 @@ and GenTraitCall (cenv: cenv) cgbuf eenv (traitInfo: TraitConstraintInfo, argExp | None -> // If witnesses are available, we should now always find trait witnesses in scope - assert eenv.witnessesInScope.IsEmpty + assert not inWitnessPassingScope let minfoOpt = CommitOperationResult (ConstraintSolver.CodegenWitnessForTraitConstraint cenv.tcVal g cenv.amap m traitInfo argExprs) match minfoOpt with @@ -3868,7 +3906,7 @@ and GenGetValAddr cenv cgbuf eenv (v: ValRef, m) sequel = let ilTy = if ilTy.IsNominal && ilTy.Boxity = ILBoxity.AsValue then ILType.Byref ilTy else ilTy EmitGetStaticFieldAddr cgbuf ilTy fspec - | Env (_, _, ilField, _) -> + | Env (_, ilField, _) -> CG.EmitInstrs cgbuf (pop 0) (Push [ILType.Byref ilTy]) [ mkLdarg0; mkNormalLdflda ilField ] | Local (_, _, Some _) | StaticProperty _ | Method _ | Env _ | Null -> @@ -4117,16 +4155,14 @@ and GenObjectExpr cenv cgbuf eenvouter expr (baseType, baseValOpt, basecall, ove let cloinfo, _, eenvinner = GetIlxClosureInfo cenv m false None eenvouter expr let cloAttribs = cloinfo.cloAttribs - let cloFreeVars = cloinfo.cloFreeVars let ilCloLambdas = cloinfo.ilCloLambdas let cloName = cloinfo.cloName - let ilxCloSpec = cloinfo.cloSpec - let ilCloFreeVars = cloinfo.cloILFreeVars + let ilCloAllFreeVars = cloinfo.ilCloAllFreeVars let ilCloGenericFormals = cloinfo.cloILGenericParams assert (isNil cloinfo.localTypeFuncDirectILGenericParams) let ilCloGenericActuals = cloinfo.cloSpec.GenericArgs - let ilCloRetTy = cloinfo.cloILFormalRetTy + let ilCloRetTy = cloinfo.ilCloFormalReturnTy let ilCloTypeRef = cloinfo.cloSpec.TypeRef let ilTyForOverriding = mkILBoxedTy ilCloTypeRef ilCloGenericActuals @@ -4153,13 +4189,11 @@ and GenObjectExpr cenv cgbuf eenvouter expr (baseType, baseValOpt, basecall, ove let attrs = GenAttrs cenv eenvinner cloAttribs let super = (if isInterfaceTy g baseType then g.ilg.typ_Object else ilCloRetTy) let interfaceTys = interfaceTys @ (if isInterfaceTy g baseType then [ilCloRetTy] else []) - let cloTypeDefs = GenClosureTypeDefs cenv (ilCloTypeRef, ilCloGenericFormals, attrs, ilCloFreeVars, ilCloLambdas, ilCtorBody, mdefs, mimpls, super, interfaceTys) + let cloTypeDefs = GenClosureTypeDefs cenv (ilCloTypeRef, ilCloGenericFormals, attrs, ilCloAllFreeVars, ilCloLambdas, ilCtorBody, mdefs, mimpls, super, interfaceTys) for cloTypeDef in cloTypeDefs do cgbuf.mgbuf.AddTypeDef(ilCloTypeRef, cloTypeDef, false, false, None) - CountClosure() - GenGetLocalVals cenv cgbuf eenvouter m cloFreeVars - CG.EmitInstr cgbuf (pop ilCloFreeVars.Length) (Push [ EraseClosures.mkTyOfLambdas g.ilxPubCloEnv ilCloLambdas]) (I_newobj (ilxCloSpec.Constructor, None)) + GenClosureAlloc cenv cgbuf eenvouter (cloinfo, m) GenSequel cenv eenvouter.cloc cgbuf sequel and GenSequenceExpr @@ -4177,7 +4211,7 @@ and GenSequenceExpr eenvouter |> AddStorageForLocalVals g (stateVars |> List.map (fun v -> v.Deref, Local(0, false, None))) // Get the free variables. Make a lambda to pretend that the 'nextEnumeratorValRef' is bound (it is an argument to GenerateNext) - let (cloAttribs, _, _, cloFreeTyvars, cloFreeVars, ilCloTypeRef: ILTypeRef, ilCloFreeVars, eenvinner) = + let (cloAttribs, _, _, cloFreeTyvars, cloFreeVars, ilCloTypeRef: ILTypeRef, ilCloAllFreeVars, eenvinner) = GetIlxClosureFreeVars cenv m None eenvouter [] (mkLambda m nextEnumeratorValRef.Deref (generateNextExpr, g.int32_ty)) let ilCloSeqElemTy = GenType cenv.amap m eenvinner.tyenv seqElemTy @@ -4192,7 +4226,7 @@ and GenSequenceExpr // Create a new closure class with a single "MoveNext" method that implements the iterator. let ilCloTyInner = mkILFormalBoxedTy ilCloTypeRef ilCloGenericParams let ilCloLambdas = Lambdas_return ilCloRetTyInner - let cloref = IlxClosureRef(ilCloTypeRef, ilCloLambdas, ilCloFreeVars) + let cloref = IlxClosureRef(ilCloTypeRef, ilCloLambdas, ilCloAllFreeVars) let ilxCloSpec = IlxClosureSpec.Create(cloref, GenGenericArgs m eenvouter.tyenv cloFreeTyvars) let formalClospec = IlxClosureSpec.Create(cloref, mkILFormalGenericArgs 0 ilCloGenericParams) @@ -4201,13 +4235,14 @@ and GenSequenceExpr CodeGenMethod cenv cgbuf.mgbuf ([], "GetFreshEnumerator", eenvinner, 1, (fun cgbuf eenv -> + GenWitnessArgs cenv cgbuf eenv m cloFreeTyvars (List.map mkTyparTy cloFreeTyvars) for fv in cloFreeVars do /// State variables always get zero-initialized if stateVarsSet.Contains fv then GenDefaultValue cenv cgbuf eenv (fv.Type, m) else GenGetLocalVal cenv cgbuf eenv m fv None - CG.EmitInstr cgbuf (pop ilCloFreeVars.Length) (Push [ilCloRetTyInner]) (I_newobj (formalClospec.Constructor, None)) + CG.EmitInstr cgbuf (pop ilCloAllFreeVars.Length) (Push [ilCloRetTyInner]) (I_newobj (formalClospec.Constructor, None)) GenSequel cenv eenv.cloc cgbuf Return), m) mkILNonGenericVirtualMethod("GetFreshEnumerator", ILMemberAccess.Public, [], mkILReturn ilCloEnumeratorTy, MethodBody.IL mbody) @@ -4244,13 +4279,14 @@ and GenSequenceExpr mkILSimpleStorageCtor(None, Some ilCloBaseTy.TypeSpec, ilCloTyInner, [], [], ILMemberAccess.Assembly).MethodBody let attrs = GenAttrs cenv eenvinner cloAttribs - let cloTypeDefs = GenClosureTypeDefs cenv (ilCloTypeRef, ilCloGenericParams, attrs, ilCloFreeVars, ilCloLambdas, ilCtorBody, [generateNextMethod;closeMethod;checkCloseMethod;lastGeneratedMethod;getFreshMethod], [], ilCloBaseTy, []) + let cloTypeDefs = GenClosureTypeDefs cenv (ilCloTypeRef, ilCloGenericParams, attrs, ilCloAllFreeVars, ilCloLambdas, ilCtorBody, [generateNextMethod;closeMethod;checkCloseMethod;lastGeneratedMethod;getFreshMethod], [], ilCloBaseTy, []) for cloTypeDef in cloTypeDefs do cgbuf.mgbuf.AddTypeDef(ilCloTypeRef, cloTypeDef, false, false, None) CountClosure() + GenWitnessArgs cenv cgbuf eenvouter m cloFreeTyvars (List.map mkTyparTy cloFreeTyvars) for fv in cloFreeVars do /// State variables always get zero-initialized if stateVarsSet.Contains fv then @@ -4258,16 +4294,16 @@ and GenSequenceExpr else GenGetLocalVal cenv cgbuf eenvouter m fv None - CG.EmitInstr cgbuf (pop ilCloFreeVars.Length) (Push [ilCloRetTyOuter]) (I_newobj (ilxCloSpec.Constructor, None)) + CG.EmitInstr cgbuf (pop ilCloAllFreeVars.Length) (Push [ilCloRetTyOuter]) (I_newobj (ilxCloSpec.Constructor, None)) GenSequel cenv eenvouter.cloc cgbuf sequel /// Generate the class for a closure type definition -and GenClosureTypeDefs cenv (tref: ILTypeRef, ilGenParams, attrs, ilCloFreeVars, ilCloLambdas, ilCtorBody, mdefs, mimpls, ext, ilIntfTys) = +and GenClosureTypeDefs cenv (tref: ILTypeRef, ilGenParams, attrs, ilCloAllFreeVars, ilCloLambdas, ilCtorBody, mdefs, mimpls, ext, ilIntfTys) = let g = cenv.g let cloInfo = - { cloFreeVars=ilCloFreeVars + { cloFreeVars=ilCloAllFreeVars cloStructure=ilCloLambdas cloCode=notlazy ilCtorBody } @@ -4312,12 +4348,12 @@ and GenLambdaClosure cenv (cgbuf: CodeGenBuffer) eenv isLocalTypeFunc selfv expr let cloinfo, body, eenvinner = GetIlxClosureInfo cenv m isLocalTypeFunc selfv eenv expr - let entryPointInfo = + let tailCallInfo = match selfv with | Some v -> [(v, BranchCallClosure (cloinfo.cloArityInfo))] | _ -> [] - let ilCloBody = CodeGenMethodForExpr cenv cgbuf.mgbuf (SPAlways, entryPointInfo, cloinfo.cloName, eenvinner, 1, body, Return) + let ilCloBody = CodeGenMethodForExpr cenv cgbuf.mgbuf (SPAlways, tailCallInfo, cloinfo.cloName, eenvinner, 1, body, Return) let ilCloTypeRef = cloinfo.cloSpec.TypeRef let cloTypeDefs = if isLocalTypeFunc then @@ -4359,12 +4395,12 @@ and GenLambdaClosure cenv (cgbuf: CodeGenBuffer) eenv isLocalTypeFunc selfv expr cgbuf.mgbuf.AddTypeDef(ilContractTypeRef, ilContractTypeDef, false, false, None) let ilCtorBody = mkILMethodBody (true, [], 8, nonBranchingInstrsToCode (mkCallBaseConstructor(ilContractTy, [])), None ) - let cloMethods = [ mkILGenericVirtualMethod("DirectInvoke", ILMemberAccess.Assembly, cloinfo.localTypeFuncDirectILGenericParams, [], mkILReturn (cloinfo.cloILFormalRetTy), MethodBody.IL ilCloBody) ] - let cloTypeDefs = GenClosureTypeDefs cenv (ilCloTypeRef, cloinfo.cloILGenericParams, [], cloinfo.cloILFreeVars, cloinfo.ilCloLambdas, ilCtorBody, cloMethods, [], ilContractTy, []) + let cloMethods = [ mkILGenericVirtualMethod("DirectInvoke", ILMemberAccess.Assembly, cloinfo.localTypeFuncDirectILGenericParams, [], mkILReturn (cloinfo.ilCloFormalReturnTy), MethodBody.IL ilCloBody) ] + let cloTypeDefs = GenClosureTypeDefs cenv (ilCloTypeRef, cloinfo.cloILGenericParams, [], cloinfo.ilCloAllFreeVars, cloinfo.ilCloLambdas, ilCtorBody, cloMethods, [], ilContractTy, []) cloTypeDefs else - GenClosureTypeDefs cenv (ilCloTypeRef, cloinfo.cloILGenericParams, [], cloinfo.cloILFreeVars, cloinfo.ilCloLambdas, ilCloBody, [], [], g.ilg.typ_Object, []) + GenClosureTypeDefs cenv (ilCloTypeRef, cloinfo.cloILGenericParams, [], cloinfo.ilCloAllFreeVars, cloinfo.ilCloLambdas, ilCloBody, [], [], g.ilg.typ_Object, []) CountClosure() for cloTypeDef in cloTypeDefs do cgbuf.mgbuf.AddTypeDef(ilCloTypeRef, cloTypeDef, false, false, None) @@ -4372,17 +4408,19 @@ and GenLambdaClosure cenv (cgbuf: CodeGenBuffer) eenv isLocalTypeFunc selfv expr | _ -> failwith "GenLambda: not a lambda" -and GenLambdaVal cenv (cgbuf: CodeGenBuffer) eenv (cloinfo, m) = +and GenClosureAlloc cenv (cgbuf: CodeGenBuffer) eenv (cloinfo, m) = let g = cenv.g + CountClosure() + GenWitnessArgs cenv cgbuf eenv m cloinfo.cloFreeTyvars (List.map mkTyparTy cloinfo.cloFreeTyvars) GenGetLocalVals cenv cgbuf eenv m cloinfo.cloFreeVars CG.EmitInstr cgbuf - (pop cloinfo.cloILFreeVars.Length) + (pop cloinfo.ilCloAllFreeVars.Length) (Push [EraseClosures.mkTyOfLambdas g.ilxPubCloEnv cloinfo.ilCloLambdas]) (I_newobj (cloinfo.cloSpec.Constructor, None)) and GenLambda cenv cgbuf eenv isLocalTypeFunc selfv expr sequel = let cloinfo, m = GenLambdaClosure cenv cgbuf eenv isLocalTypeFunc selfv expr - GenLambdaVal cenv cgbuf eenv (cloinfo, m) + GenClosureAlloc cenv cgbuf eenv (cloinfo, m) GenSequel cenv eenv.cloc cgbuf sequel and GenTypeOfVal cenv eenv (v: Val) = @@ -4392,7 +4430,7 @@ and GenFreevar cenv m eenvouter tyenvinner (fv: Val) = let g = cenv.g match StorageForVal m fv eenvouter with // Local type functions - | Local(_, _, Some _) | Env(_, _, _, Some _) -> g.ilg.typ_Object + | Local(_, _, Some _) | Env(_, _, Some _) -> g.ilg.typ_Object #if DEBUG // Check for things that should never make it into the free variable set. Only do this in debug for performance reasons | (StaticField _ | StaticProperty _ | Method _ | Null) -> error(InternalError("GenFreevar: compiler error: unexpected unrealized value", fv.Range)) @@ -4470,28 +4508,62 @@ and GetIlxClosureFreeVars cenv m selfv eenvouter takenNames expr = // If generating a named closure, add the closure itself as a var, available via "arg0" . // The latter doesn't apply for the delegate implementation of closures. // Build the environment that is active inside the closure itself - let eenvinner = eenvinner |> AddStorageForLocalVals g (match selfv with | Some v -> [(v.Deref, Arg 0)] | _ -> []) + let selfVars = match selfv with | Some v -> [(v.Deref, Arg 0)] | _ -> [] + let eenvinner = eenvinner |> AddStorageForLocalVals g selfVars + + // Work out if the closure captures any witnesses. + let cloWitnessInfos = + let inWitnessPassingScope = not eenvouter.witnessesInScope.IsEmpty + if g.generateWitnesses && inWitnessPassingScope then + GetTraitWitnessInfosOfTypars g [] cloFreeTyvars + else + [] - let ilCloFreeVars = - let ilCloFreeVarNames = ChooseFreeVarNames takenNames (List.map nameOfVal cloFreeVars) - let ilCloFreeVars = (cloFreeVars, ilCloFreeVarNames) ||> List.map2 (fun fv nm -> mkILFreeVar (nm, fv.IsCompilerGenerated, GenFreevar cenv m eenvouter eenvinner.tyenv fv)) - ilCloFreeVars + let ilCloWitnessFreeVars, ilCloWitnessStorage = + let names = + cloWitnessInfos + |> List.map (fun w -> String.uncapitalize w.MemberName) + |> ChooseFreeVarNames takenNames + (cloWitnessInfos, names) + ||> List.map2 (fun w nm -> + let ty = GenWitnessTy cenv.g w + let ilTy = GenType cenv.amap m eenvinner.tyenv ty + let ilFv = mkILFreeVar (nm, true, ilTy) + let storage = + let ilField = mkILFieldSpecInTy (ilCloTyInner, ilFv.fvName, ilFv.fvType) + Env(ilCloTyInner, ilField, None) + ilFv, (w, storage)) + |> List.unzip + + // Allocate storage in the environment for the witnesses + let eenvinner = eenvinner |> AddStorageForLocalWitnesses ilCloWitnessStorage - let ilCloFreeVarStorage = - (cloFreeVars, ilCloFreeVars) ||> List.mapi2 (fun i v fv -> + let ilCloFreeVars, ilCloFreeVarStorage = + let names = + cloFreeVars + |> List.map nameOfVal + |> ChooseFreeVarNames takenNames + + (cloFreeVars, names) + ||> List.map2 (fun fv nm -> let localCloInfo = - match StorageForVal m v eenvouter with + match StorageForVal m fv eenvouter with | Local(_, _, localCloInfo) - | Env(_, _, _, localCloInfo) -> localCloInfo + | Env(_, _, localCloInfo) -> localCloInfo | _ -> None - let ilField = mkILFieldSpecInTy (ilCloTyInner, fv.fvName, fv.fvType) + let ilFv = mkILFreeVar (nm, fv.IsCompilerGenerated, GenFreevar cenv m eenvouter eenvinner.tyenv fv) + let storage = + let ilField = mkILFieldSpecInTy (ilCloTyInner, ilFv.fvName, ilFv.fvType) + Env(ilCloTyInner, ilField, localCloInfo) + ilFv, (fv, storage)) + |> List.unzip - (v, Env(ilCloTyInner, i, ilField, localCloInfo))) + let ilCloAllFreeVars = Array.ofList (ilCloWitnessFreeVars @ ilCloFreeVars) let eenvinner = eenvinner |> AddStorageForLocalVals g ilCloFreeVarStorage // Return a various results - (cloAttribs, cloInternalFreeTyvars, cloContractFreeTyvars, cloFreeTyvars, cloFreeVars, ilCloTypeRef, Array.ofList ilCloFreeVars, eenvinner) + (cloAttribs, cloInternalFreeTyvars, cloContractFreeTyvars, cloFreeTyvars, cloFreeVars, ilCloTypeRef, ilCloAllFreeVars, eenvinner) and GetIlxClosureInfo cenv m isLocalTypeFunc selfv eenvouter expr = @@ -4521,21 +4593,22 @@ and GetIlxClosureInfo cenv m isLocalTypeFunc selfv eenvouter expr = let takenNames = vs |> List.map (fun v -> v.CompiledName) // Get the free variables and the information about the closure, add the free variables to the environment - let (cloAttribs, cloInternalFreeTyvars, cloContractFreeTyvars, _, cloFreeVars, ilCloTypeRef, ilCloFreeVars, eenvinner) = GetIlxClosureFreeVars cenv m selfv eenvouter takenNames expr + let (cloAttribs, cloInternalFreeTyvars, cloContractFreeTyvars, cloFreeTyvars, cloFreeVars, ilCloTypeRef, ilCloAllFreeVars, eenvinner) = + GetIlxClosureFreeVars cenv m selfv eenvouter takenNames expr // Put the type and value arguments into the environment - let rec getClosureArgs eenv ntmargs tvsl (vs: Val list) = + let rec getClosureArgs eenv numArgs tvsl (vs: Val list) = match tvsl, vs with | tvs :: rest, _ -> let eenv = AddTyparsToEnv tvs eenv - let l, eenv = getClosureArgs eenv ntmargs rest vs + let l, eenv = getClosureArgs eenv numArgs rest vs let lambdas = (tvs, l) ||> List.foldBack (fun tv sofar -> Lambdas_forall(GenGenericParam cenv eenv tv, sofar)) lambdas, eenv | [], v :: rest -> let nm = v.CompiledName let l, eenv = - let eenv = AddStorageForVal g (v, notlazy (Arg ntmargs)) eenv - getClosureArgs eenv (ntmargs+1) [] rest + let eenv = AddStorageForVal g (v, notlazy (Arg numArgs)) eenv + getClosureArgs eenv (numArgs+1) [] rest let lambdas = Lambdas_lambda (mkILParamNamed(nm, GenTypeOfVal cenv eenv v), l) lambdas, eenv | _ -> @@ -4596,7 +4669,7 @@ and GetIlxClosureInfo cenv m isLocalTypeFunc selfv eenvouter expr = let ilCloGenericFormals = ilContractGenericParams @ ilInternalGenericParams let ilCloGenericActuals = ilContractGenericActuals @ ilInternalGenericActuals - let ilDirectGenericParams, ilReturnTy, ilCloLambdas = + let ilDirectGenericParams, ilCloReturnTy, ilCloLambdas = if isLocalTypeFunc then let rec strip lambdas acc = match lambdas with @@ -4608,17 +4681,18 @@ and GetIlxClosureInfo cenv m isLocalTypeFunc selfv eenvouter expr = [], ilReturnTy, ilCloLambdas - let ilxCloSpec = IlxClosureSpec.Create(IlxClosureRef(ilCloTypeRef, ilCloLambdas, ilCloFreeVars), ilCloGenericActuals) + let ilxCloSpec = IlxClosureSpec.Create(IlxClosureRef(ilCloTypeRef, ilCloLambdas, ilCloAllFreeVars), ilCloGenericActuals) let cloinfo = { cloExpr=expr cloName=ilCloTypeRef.Name cloArityInfo =narginfo ilCloLambdas=ilCloLambdas - cloILFreeVars = ilCloFreeVars - cloILFormalRetTy=ilReturnTy + ilCloAllFreeVars = ilCloAllFreeVars + ilCloFormalReturnTy = ilCloReturnTy cloSpec = ilxCloSpec cloILGenericParams = ilCloGenericFormals cloFreeVars=cloFreeVars + cloFreeTyvars=cloFreeTyvars cloAttribs=cloAttribs localTypeFuncContractFreeTypars = cloContractFreeTyvars localTypeFuncInternalFreeTypars = cloInternalFreeTyvars @@ -4678,7 +4752,9 @@ and GenDelegateExpr cenv cgbuf eenvouter expr (TObjExprMethod((TSlotSig(_, deleg // Work out the free type variables for the morphing thunk let takenNames = List.map nameOfVal tmvs - let (cloAttribs, _, _, cloFreeTyvars, cloFreeVars, ilDelegeeTypeRef, ilCloFreeVars, eenvinner) = GetIlxClosureFreeVars cenv m None eenvouter takenNames expr + let (cloAttribs, _, _, cloFreeTyvars, cloFreeVars, ilDelegeeTypeRef, ilCloAllFreeVars, eenvinner) = + GetIlxClosureFreeVars cenv m None eenvouter takenNames expr + let ilDelegeeGenericParams = GenGenericParams cenv eenvinner cloFreeTyvars let ilDelegeeGenericActualsInner = mkILFormalGenericArgs 0 ilDelegeeGenericParams @@ -4708,15 +4784,18 @@ and GenDelegateExpr cenv cgbuf eenvouter expr (TObjExprMethod((TSlotSig(_, deleg let ilCloLambdas = Lambdas_return ilCtxtDelTy let ilAttribs = GenAttrs cenv eenvinner cloAttribs - let cloTypeDefs = GenClosureTypeDefs cenv (ilDelegeeTypeRef, ilDelegeeGenericParams, ilAttribs, ilCloFreeVars, ilCloLambdas, ilCtorBody, [delegeeInvokeMeth], [], g.ilg.typ_Object, []) + let cloTypeDefs = GenClosureTypeDefs cenv (ilDelegeeTypeRef, ilDelegeeGenericParams, ilAttribs, ilCloAllFreeVars, ilCloLambdas, ilCtorBody, [delegeeInvokeMeth], [], g.ilg.typ_Object, []) for cloTypeDef in cloTypeDefs do cgbuf.mgbuf.AddTypeDef(ilDelegeeTypeRef, cloTypeDef, false, false, None) CountClosure() let ctxtGenericArgsForDelegee = GenGenericArgs m eenvouter.tyenv cloFreeTyvars - let ilxCloSpec = IlxClosureSpec.Create(IlxClosureRef(ilDelegeeTypeRef, ilCloLambdas, ilCloFreeVars), ctxtGenericArgsForDelegee) + let ilxCloSpec = IlxClosureSpec.Create(IlxClosureRef(ilDelegeeTypeRef, ilCloLambdas, ilCloAllFreeVars), ctxtGenericArgsForDelegee) + + GenWitnessArgs cenv cgbuf eenvouter m cloFreeTyvars (List.map mkTyparTy cloFreeTyvars) GenGetLocalVals cenv cgbuf eenvouter m cloFreeVars - CG.EmitInstr cgbuf (pop ilCloFreeVars.Length) (Push [EraseClosures.mkTyOfLambdas g.ilxPubCloEnv ilCloLambdas]) (I_newobj (ilxCloSpec.Constructor, None)) + + CG.EmitInstr cgbuf (pop ilCloAllFreeVars.Length) (Push [EraseClosures.mkTyOfLambdas g.ilxPubCloEnv ilCloLambdas]) (I_newobj (ilxCloSpec.Constructor, None)) let ilDelegeeTyOuter = mkILBoxedTy ilDelegeeTypeRef ctxtGenericArgsForDelegee let ilDelegeeInvokeMethOuter = mkILNonGenericInstanceMethSpecInTy (ilDelegeeTyOuter, "Invoke", typesOfILParams ilDelegeeParams, ilDelegeeRet.Type) @@ -4739,11 +4818,11 @@ and GenStaticOptimization cenv cgbuf eenv (constraints, e2, e3, _m) sequel = // ... // when ^T : ^T = ((^T or ^U): (static member (*) : ^T * ^U -> ^V) (x,y)) // - // When witnesses are available we use the dynamic implementation. + // When witnesses are not available we use the dynamic implementation. let e = - let haveWitnesses = not eenv.witnessesInScope.IsEmpty - if DecideStaticOptimizations cenv.g constraints haveWitnesses = StaticOptimizationAnswer.Yes then + let inWitnessPassingScope = not eenv.witnessesInScope.IsEmpty + if DecideStaticOptimizations cenv.g constraints inWitnessPassingScope = StaticOptimizationAnswer.Yes then e2 else e3 @@ -5183,7 +5262,7 @@ and GenLetRecBindings cenv (cgbuf: CodeGenBuffer) eenv (allBinds: Bindings, m) = clo.cloFreeVars |> List.iter (fun fv -> if Zset.contains fv forwardReferenceSet then match StorageForVal m fv eenvclo with - | Env (_, _, ilField, _) -> fixups := (boundv, fv, (fun () -> GenLetRecFixup cenv cgbuf eenv (clo.cloSpec, access, ilField, exprForVal m fv, m))) :: !fixups + | Env (_, ilField, _) -> fixups := (boundv, fv, (fun () -> GenLetRecFixup cenv cgbuf eenv (clo.cloSpec, access, ilField, exprForVal m fv, m))) :: !fixups | _ -> error (InternalError("GenLetRec: " + fv.LogicalName + " was not in the environment", m)) ) | Expr.Val (vref, _, _) -> @@ -5770,7 +5849,6 @@ and GenMethodForBinding | _ -> [], methLambdaVars, false let nonUnitNonSelfMethodVars, body = BindUnitVars cenv.g (nonSelfMethodVars, paramInfos, methLambdaBody) - let nonUnitMethodVars = selfMethodVars@nonUnitNonSelfMethodVars let eenv = bindBaseOrThisVarOpt cenv eenv ctorThisValOpt let eenv = bindBaseOrThisVarOpt cenv eenv baseValOpt @@ -5797,17 +5875,17 @@ and GenMethodForBinding let eenvForMeth = let eenvForMeth = eenvUnderMethLambdaTypars - let numImplicitArgs = if isCtor then 1 else 0 - let eenvForMeth = - if hasWitnessArgs then - AddStorageForLocalWitnesses eenvForMeth (methLambdaWitnessInfos |> List.mapi (fun i w -> (w, Arg (numImplicitArgs+i)))) - else - eenvForMeth - let numImplicitArgs = numImplicitArgs + (if hasWitnessArgs then List.length witnessInfos else 0) - let eenvForMeth = AddStorageForLocalVals cenv.g (List.mapi (fun i v -> (v, Arg (numImplicitArgs+i))) nonUnitMethodVars) eenvForMeth + let numArgsUsed = 0 + let numArgsUsed = numArgsUsed + (if isCtor then 1 else 0) + let eenvForMeth = eenvForMeth |> AddStorageForLocalVals cenv.g (selfMethodVars |> List.mapi (fun i v -> (v, Arg (numArgsUsed+i)))) + let numArgsUsed = numArgsUsed + selfMethodVars.Length + let eenvForMeth = eenvForMeth |> AddStorageForLocalWitnesses (methLambdaWitnessInfos |> List.mapi (fun i w -> (w, Arg (numArgsUsed+i)))) + let numArgsUsed = numArgsUsed + methLambdaWitnessInfos.Length + let eenvForMeth = eenvForMeth |> AddStorageForLocalVals cenv.g (List.mapi (fun i v -> (v, Arg (numArgsUsed+i))) nonUnitNonSelfMethodVars) eenvForMeth - let tailCallInfo = [(mkLocalValRef v, BranchCallMethod (topValInfo.AritiesOfArgs, curriedArgInfos, methLambdaTypars, nonUnitMethodVars.Length, v.NumObjArgs))] + let tailCallInfo = + [(mkLocalValRef v, BranchCallMethod (topValInfo.AritiesOfArgs, curriedArgInfos, methLambdaTypars, selfMethodVars.Length, methLambdaWitnessInfos.Length, nonUnitNonSelfMethodVars.Length))] // Discard the result on a 'void' return type. For a constructor just return 'void' let sequel = @@ -5876,7 +5954,7 @@ and GenMethodForBinding yield! GenCompilationArgumentCountsAttr cenv v ] let ilTypars = GenGenericParams cenv eenvUnderMethLambdaTypars methLambdaTypars - let ilParams = GenParams cenv eenvUnderMethTypeTypars m mspec witnessInfos paramInfos argTys (Some(nonUnitNonSelfMethodVars)) + let ilParams = GenParams cenv eenvUnderMethTypeTypars m mspec witnessInfos paramInfos argTys (Some nonUnitNonSelfMethodVars) let ilReturn = GenReturnInfo cenv eenvUnderMethTypeTypars mspec.FormalReturnType retInfo let methName = mspec.Name let tref = mspec.MethodRef.DeclaringTypeRef @@ -6071,7 +6149,7 @@ and GenBindings cenv cgbuf eenv binds = List.iter (GenBinding cenv cgbuf eenv) b and GenSetVal cenv cgbuf eenv (vref, e, m) sequel = let storage = StorageForValRef m vref eenv match storage with - | Env (ilCloTy, _, _, _) -> + | Env (ilCloTy, _, _) -> CG.EmitInstr cgbuf (pop 0) (Push [ilCloTy]) mkLdarg0 | _ -> () @@ -6149,7 +6227,7 @@ and GenSetStorage m cgbuf storage = | Arg _ -> error(Error(FSComp.SR.ilMutableVariablesCannotEscapeMethod(), m)) - | Env (_, _, ilField, _) -> + | Env (_, ilField, _) -> // Note: ldarg0 has already been emitted in GenSetVal CG.EmitInstr cgbuf (pop 2) Push0 (mkNormalStfld ilField) @@ -6217,7 +6295,7 @@ and GenGetStorageAndSequel (cenv: cenv) cgbuf eenv m (ty, ilTy) storage fetchSeq CG.EmitInstr cgbuf (pop 0) (Push [ilTy]) (mkLdarg (uint16 i)) CommitGetStorageSequel cenv cgbuf eenv m ty None fetchSequel - | Env (_, _, ilField, localCloInfo) -> + | Env (_, ilField, localCloInfo) -> // Note: ldarg 0 is emitted in 'cu_erase' erasure of the ldenv instruction CG.EmitInstrs cgbuf (pop 0) (Push [ilTy]) [ mkLdarg0; mkNormalLdfld ilField ] CommitGetStorageSequel cenv cgbuf eenv m ty localCloInfo fetchSequel @@ -6286,7 +6364,7 @@ and AllocStorageForBinds cenv cgbuf scopeMarks eenv binds = | Some repr -> match repr with | Local(_, _, Some g) - | Env(_, _, _, Some g) -> + | Env(_, _, Some g) -> match !g with | NamedLocalIlxClosureInfoGenerator f -> g := NamedLocalIlxClosureInfoGenerated (f eenv) | NamedLocalIlxClosureInfoGenerated _ -> () @@ -7685,6 +7763,7 @@ let GenerateCode (cenv, anonTypeTable, eenv, TypedAssemblyAfterOptimization file match reflectedDefinitions with | [] -> [] | _ -> + // TODO: generate witness parameters for reflected definitions let qscope = QuotationTranslator.QuotationGenerationScope.Create (cenv.g, cenv.amap, cenv.viewCcu, cenv.tcVal, QuotationTranslator.IsReflectedDefinition.Yes) let defns = reflectedDefinitions |> List.choose (fun ((methName, v), e) -> diff --git a/src/fsharp/MethodCalls.fs b/src/fsharp/MethodCalls.fs index 99116c445c3..60c0465edb1 100644 --- a/src/fsharp/MethodCalls.fs +++ b/src/fsharp/MethodCalls.fs @@ -1435,15 +1435,17 @@ let GenWitnessExpr amap g m (traitInfo: TraitConstraintInfo) argExprs = tryMkCallBuiltInWitness g traitInfo argExprs m let GenWitnessExprLambda amap g m (traitInfo: TraitConstraintInfo) = - let argtysl = GenWitnessArgTys g traitInfo.TraitKey + let witnessInfo = traitInfo.TraitKey + let argtysl = GenWitnessArgTys g witnessInfo let vse = argtysl |> List.mapiSquared (fun i j ty -> mkCompGenLocal m ("arg" + string i + "_" + string j) ty) let vsl = List.mapSquared fst vse match GenWitnessExpr amap g m traitInfo (List.concat (List.mapSquared snd vse)) with | Some expr -> - mkMemberLambdas m [] None None vsl (expr, tyOfExpr g expr) + Choice2Of2 (mkMemberLambdas m [] None None vsl (expr, tyOfExpr g expr)) | None -> - assert ("A constraint witness could not be found for a built-in constraint solution" |> ignore; false) - mkOne g m + Choice1Of2 witnessInfo + //assert ("A constraint witness could not be found for a built-in constraint solution" |> ignore; false) + //mkOne g m -let GenWitnessArgs amap g m (traitInfos: TraitConstraintInfo list) = +let GenNonGenericWitnessArgs amap g m (traitInfos: TraitConstraintInfo list) = [ for traitInfo in traitInfos -> GenWitnessExprLambda amap g m traitInfo ] diff --git a/src/fsharp/QuotationTranslator.fs b/src/fsharp/QuotationTranslator.fs index bd8f4e22ebd..d6f443e532d 100644 --- a/src/fsharp/QuotationTranslator.fs +++ b/src/fsharp/QuotationTranslator.fs @@ -693,7 +693,12 @@ and ConvLValueArgs cenv env args = | [] -> [] and ConvWitnessArgs cenv env witnessArgs = - ConvExprs cenv { env with isWitness = true } witnessArgs + let env = { env with isWitness = true } + witnessArgs |> List.map (fun arg -> + match arg with + | Choice1Of2 _witnessInfo -> failwith "TODO: ReflectedDefinition of 'let inline' quotations that utilise witnesses" + | Choice2Of2 arg -> ConvExpr cenv env arg + ) and ConvLValueExpr cenv env expr = EmitDebugInfoIfNecessary cenv env expr.Range (ConvLValueExprCore cenv env expr) diff --git a/tests/fsharp/core/quotes/test.fsx b/tests/fsharp/core/quotes/test.fsx index 0d1fe46f517..85393ff87a0 100644 --- a/tests/fsharp/core/quotes/test.fsx +++ b/tests/fsharp/core/quotes/test.fsx @@ -3583,6 +3583,71 @@ module WitnessTests = true | _ -> false)) +module MoreWitnessTests = + + open System.Runtime.CompilerServices + open System.IO + + // TODO - ths fails + //[] + module Tests = + let inline f0 (x: 'T) : (unit -> 'T) list = + [] + + let inline f (x: 'T) : (unit -> 'T) list = + [(fun () -> x + x)] + + type C() = + member inline __.F(x: 'T) = x + x + + [] + module M = + + type C with + member inline __.F2(x: 'T) = x + x + static member inline F2Static(x: 'T) = x + x + + [] + type FileExt = + [] + static member CreateDirectory(fileInfo: FileInfo) = + Directory.CreateDirectory fileInfo.Directory.FullName + + [] + static member inline F3(s: string, x: 'T) = + x + x + + [] + static member inline F4(s: string, x1: 'T, x2: 'T) = + x1 + x2 + + + [] + module Usage = + let q0 = <@ f0 3 @> + let q1 = <@ f 3 @> + let q2 = <@ C().F(3) @> + let q3 = <@ C().F2(3) @> + let q4 = <@ C.F2Static(3) @> + let q5 = <@ "".F3(3) @> + let q6 = <@ "".F4(3, 4) @> + + check "wekncjeck1" (q0.ToString()) "Call (None, f0, [Value (3)])" + check "wekncjeck2" (q1.ToString()) "Call (None, f, [Value (3)])" + check "wekncjeck3" (q2.ToString()) "Call (Some (NewObject (C)), F, [Value (3)])" + check "wekncjeck4" (q3.ToString()) "Call (None, C.F2, [NewObject (C), Value (3)])" + check "wekncjeck5" (q4.ToString()) "Call (None, C.F2Static.Static, [Value (3)])" + check "wekncjeck6" (q5.ToString()) "Call (None, F3, [Value (\"\"), Value (3)])" + check "wekncjeck7" (q6.ToString()) "Call (None, F4, [Value (\"\"), Value (3), Value (4)])" + + check "ewlknweknl1" (FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.EvaluateQuotation q0) (box ([] : (unit -> int) list)) + check "ewlknweknl2" (match FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.EvaluateQuotation q1 with :? ((unit -> int) list) as x -> x.[0] ()) 6 + check "ewlknweknl3" (match FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.EvaluateQuotation q2 with :? int as x -> x) 6 + check "ewlknweknl4" (match FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.EvaluateQuotation q3 with :? int as x -> x) 6 + check "ewlknweknl5" (match FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.EvaluateQuotation q4 with :? int as x -> x) 6 + check "ewlknweknl6" (match FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.EvaluateQuotation q5 with :? int as x -> x) 6 + check "ewlknweknl7" (match FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.EvaluateQuotation q6 with :? int as x -> x) 7 + #if !FX_RESHAPED_REFLECTION module TestAssemblyAttributes = let attributes = System.Reflection.Assembly.GetExecutingAssembly().GetCustomAttributes(false) From 5fddb5856410f2f6788c4654405ce1d4255caccb Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 18 Apr 2019 15:46:36 +0100 Subject: [PATCH 72/77] Revert "do not try to build latest FSHarp.Core as part of proto build" This reverts commit 6a27e0274adf747e32816ad8f6ec9143c8d4568b. --- eng/build-utils.ps1 | 2 +- src/fsharp/FSharp.Build/FSharp.Build.fsproj | 2 +- .../FSharp.Compiler.Interactive.Settings.fsproj | 2 +- .../FSharp.Compiler.Private.fsproj | 2 +- .../FSharp.Compiler.Server.Shared.fsproj | 2 +- src/fsharp/FSharp.Core.nuget/FSharp.Core.nuget.csproj | 2 +- src/fsharp/fsc/fsc.fsproj | 7 +------ src/fsharp/fsi/fsi.fsproj | 11 ++++------- src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj | 11 ++++------- 9 files changed, 15 insertions(+), 26 deletions(-) diff --git a/eng/build-utils.ps1 b/eng/build-utils.ps1 index a1e16a5f7ec..d1e5dd85d55 100644 --- a/eng/build-utils.ps1 +++ b/eng/build-utils.ps1 @@ -249,7 +249,7 @@ function Make-BootstrapBuild() { $projectPath = "$RepoRoot\proto.proj" Run-MSBuild $projectPath "/restore /t:Build" -logFileName "Bootstrap" -configuration $bootstrapConfiguration Copy-Item "$ArtifactsDir\bin\fsc\$bootstrapConfiguration\$bootstrapTfm\*" -Destination $dir - Copy-Item "$ArtifactsDir\bin\fsi\$bootstrapConfiguration\$bootstrapTfm\*" -Destination $dir -Force + Copy-Item "$ArtifactsDir\bin\fsi\$bootstrapConfiguration\$bootstrapTfm\*" -Destination $dir return $dir } diff --git a/src/fsharp/FSharp.Build/FSharp.Build.fsproj b/src/fsharp/FSharp.Build/FSharp.Build.fsproj index 38a1ffa90bc..7bab41796bd 100644 --- a/src/fsharp/FSharp.Build/FSharp.Build.fsproj +++ b/src/fsharp/FSharp.Build/FSharp.Build.fsproj @@ -33,7 +33,7 @@ - + diff --git a/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj b/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj index 51c4017d67d..799fda75246 100644 --- a/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj +++ b/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj @@ -28,7 +28,7 @@ - + diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj index f7d8f20440a..bed8c55e91e 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj @@ -675,7 +675,7 @@ - + diff --git a/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj b/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj index faab0f8cc3b..39ba868aeee 100644 --- a/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj +++ b/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj @@ -21,7 +21,7 @@ - + diff --git a/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuget.csproj b/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuget.csproj index e304369556b..fd2d5162c75 100644 --- a/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuget.csproj +++ b/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuget.csproj @@ -10,7 +10,7 @@ - + false diff --git a/src/fsharp/fsc/fsc.fsproj b/src/fsharp/fsc/fsc.fsproj index 8ea9e6d8b07..4b812970716 100644 --- a/src/fsharp/fsc/fsc.fsproj +++ b/src/fsharp/fsc/fsc.fsproj @@ -29,16 +29,11 @@ + - - - - - - diff --git a/src/fsharp/fsi/fsi.fsproj b/src/fsharp/fsi/fsi.fsproj index d088ca69384..43e95426220 100644 --- a/src/fsharp/fsi/fsi.fsproj +++ b/src/fsharp/fsi/fsi.fsproj @@ -26,17 +26,14 @@ + - - - - - - + + - + diff --git a/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj b/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj index 96117f719f4..fd6c5b7ef3e 100644 --- a/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj +++ b/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj @@ -26,15 +26,12 @@ + - - - - - - - + + + From 745d2e91d6cbb590d7d7297b1397f344c57b0935 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 18 Apr 2019 15:46:37 +0100 Subject: [PATCH 73/77] Revert "do not try to build latest FSHarp.Core as part of proto build" This reverts commit 6fae5c43b23e072e2dbe75afe631a035d7256733. --- src/fsharp/FSharp.Core/FSharp.Core.fsproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/FSharp.Core.fsproj b/src/fsharp/FSharp.Core/FSharp.Core.fsproj index b3ed7590476..440850ed55c 100644 --- a/src/fsharp/FSharp.Core/FSharp.Core.fsproj +++ b/src/fsharp/FSharp.Core/FSharp.Core.fsproj @@ -232,7 +232,7 @@ - + From 6e85682cd321903d21ad8f47316d9473f2140cdc Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 18 Apr 2019 15:47:08 +0100 Subject: [PATCH 74/77] Revert "do not try to build latest FSHarp.Core as part of proto build" This reverts commit 366ed83dc631ef0d758479d927b0f2d03a98d071. --- FSharpBuild.Directory.Build.props | 1 - src/fsharp/FSharp.Build/FSharp.Build.fsproj | 4 +--- .../FSharp.Compiler.Interactive.Settings.fsproj | 4 +--- .../FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj | 4 +--- .../FSharp.Compiler.Server.Shared.fsproj | 4 +--- src/fsharp/fsc/fsc.fsproj | 6 +++--- src/fsharp/fsi/fsi.fsproj | 4 +--- src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj | 4 +--- 8 files changed, 9 insertions(+), 22 deletions(-) diff --git a/FSharpBuild.Directory.Build.props b/FSharpBuild.Directory.Build.props index 95036cb5ae1..a1ba7ab156d 100644 --- a/FSharpBuild.Directory.Build.props +++ b/FSharpBuild.Directory.Build.props @@ -92,7 +92,6 @@ fs false true - 4.6.2 diff --git a/src/fsharp/FSharp.Build/FSharp.Build.fsproj b/src/fsharp/FSharp.Build/FSharp.Build.fsproj index 7bab41796bd..0dad55058b0 100644 --- a/src/fsharp/FSharp.Build/FSharp.Build.fsproj +++ b/src/fsharp/FSharp.Build/FSharp.Build.fsproj @@ -33,9 +33,7 @@ - - - + diff --git a/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj b/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj index 799fda75246..6307f17baf3 100644 --- a/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj +++ b/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj @@ -28,9 +28,7 @@ - - - + diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj index bed8c55e91e..9fef6d27589 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj @@ -675,9 +675,7 @@ - - - + diff --git a/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj b/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj index 39ba868aeee..75a7353bb96 100644 --- a/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj +++ b/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj @@ -21,9 +21,7 @@ - - - + diff --git a/src/fsharp/fsc/fsc.fsproj b/src/fsharp/fsc/fsc.fsproj index 4b812970716..8ddb082c56a 100644 --- a/src/fsharp/fsc/fsc.fsproj +++ b/src/fsharp/fsc/fsc.fsproj @@ -29,9 +29,9 @@ - - - + + + diff --git a/src/fsharp/fsi/fsi.fsproj b/src/fsharp/fsi/fsi.fsproj index 43e95426220..a7bafddfded 100644 --- a/src/fsharp/fsi/fsi.fsproj +++ b/src/fsharp/fsi/fsi.fsproj @@ -26,9 +26,7 @@ - - - + diff --git a/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj b/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj index fd6c5b7ef3e..dbe31f6ec2a 100644 --- a/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj +++ b/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj @@ -26,9 +26,7 @@ - - - + From 0b0bc1a916e149cd630fa1f88e3609387e673131 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 18 Apr 2019 15:56:20 +0100 Subject: [PATCH 75/77] fix build --- .../FSharp.Compiler.Interactive.Settings.fsproj | 2 -- .../FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj | 2 -- .../FSharp.Compiler.Server.Shared.fsproj | 2 -- src/fsharp/FSharp.Core/prim-types.fs | 1 + src/fsharp/fsc/fsc.fsproj | 6 ------ src/fsharp/fsi/fsi.fsproj | 6 ------ src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj | 6 ------ 7 files changed, 1 insertion(+), 24 deletions(-) diff --git a/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj b/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj index ee2ef9c1e32..5bc96e7ed2d 100644 --- a/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj +++ b/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj @@ -29,8 +29,6 @@ - - diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj index 6ea8232388c..b7ba0a23cd8 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj @@ -676,8 +676,6 @@ - - diff --git a/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj b/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj index 4c491d1b74b..8bd027a0623 100644 --- a/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj +++ b/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj @@ -22,8 +22,6 @@ - - diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 9f4a31706bd..210c0c3765e 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -2687,6 +2687,7 @@ namespace Microsoft.FSharp.Core static member inline op_LogicalNot(value: nativeint) = (# "not" value : nativeint #) static member inline op_LogicalNot(value: unativeint) = (# "not" value : unativeint #) +#if !BUILD_FROM_SOURCE static member inline op_Explicit(value: sbyte) : byte = (# "conv.u1" value : byte #) static member inline op_Explicit(value: byte) : byte = (# "conv.u1" value : byte #) static member inline op_Explicit(value: int16) : byte = (# "conv.u1" value : byte #) diff --git a/src/fsharp/fsc/fsc.fsproj b/src/fsharp/fsc/fsc.fsproj index de174d1904e..8ddb082c56a 100644 --- a/src/fsharp/fsc/fsc.fsproj +++ b/src/fsharp/fsc/fsc.fsproj @@ -28,12 +28,6 @@ - - - - - - diff --git a/src/fsharp/fsi/fsi.fsproj b/src/fsharp/fsi/fsi.fsproj index 14e7847574d..a7bafddfded 100644 --- a/src/fsharp/fsi/fsi.fsproj +++ b/src/fsharp/fsi/fsi.fsproj @@ -25,12 +25,6 @@ - - - - - - diff --git a/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj b/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj index cd7221b90a7..dbe31f6ec2a 100644 --- a/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj +++ b/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj @@ -25,12 +25,6 @@ - - - - - - From 95492fdab99387c06d728e1bd4fe9fd6dea5a770 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 18 Apr 2019 16:49:35 +0100 Subject: [PATCH 76/77] upd --- src/fsharp/FSharp.Core/prim-types.fs | 11 +++++++---- src/fsharp/FSharp.Core/prim-types.fsi | 12 +++++++----- src/fsharp/IlxGen.fs | 2 +- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 210c0c3765e..e048af1e72d 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -2491,6 +2491,9 @@ namespace Microsoft.FSharp.Core let inline ParseSingle (s:string) = Single.Parse(removeUnderscores s,NumberStyles.Float, CultureInfo.InvariantCulture) type BuiltInWitnesses = +#if BUILDING_WITH_LKG + static member NoUseOfWitnessesAllowedInProto() = () +#else static member inline op_Addition(x: int32, y: int32) = (# "add" x y : int32 #) static member inline op_Addition(x: float, y: float) = (# "add" x y : float #) static member inline op_Addition(x: float32, y: float32) = (# "add" x y : float32 #) @@ -2687,7 +2690,6 @@ namespace Microsoft.FSharp.Core static member inline op_LogicalNot(value: nativeint) = (# "not" value : nativeint #) static member inline op_LogicalNot(value: unativeint) = (# "not" value : unativeint #) -#if !BUILD_FROM_SOURCE static member inline op_Explicit(value: sbyte) : byte = (# "conv.u1" value : byte #) static member inline op_Explicit(value: byte) : byte = (# "conv.u1" value : byte #) static member inline op_Explicit(value: int16) : byte = (# "conv.u1" value : byte #) @@ -3004,6 +3006,7 @@ namespace Microsoft.FSharp.Core static member inline DivideByInt (x: decimal, n: int) = Decimal.Divide(x, Convert.ToDecimal(n)) static member inline DivideByInt (x: float, n: int) = (# "div" x ((# "conv.r8" n : float #)) : float #) static member inline DivideByInt (x: float32, n:int) = (# "div" x ((# "conv.r4" n : float32 #)) : float32 #) +#endif type GenericZeroDynamicImplTable<'T>() = static let result : 'T = @@ -3308,9 +3311,9 @@ namespace Microsoft.FSharp.Core let inline DivideByInt< ^T when ^T : (static member DivideByInt : ^T * int -> ^T) > (x: ^T) (y: int) : ^T = DivideByIntDynamic<'T> x y - when ^T : float = BuiltInWitnesses.DivideByInt ((retype x: float), y) - when ^T : float32 = BuiltInWitnesses.DivideByInt ((retype x: float32), y) - when ^T : decimal = BuiltInWitnesses.DivideByInt ((retype x: decimal), y) + when ^T : float = (# "div" x ((# "conv.r8" y : float #)) : float #) + when ^T : float32 = (# "div" x ((# "conv.r4" y : float32 #)) : float32 #) + when ^T : decimal = Decimal.Divide((# "" x : decimal #), Convert.ToDecimal(y)) when ^T : ^T = (^T : (static member DivideByInt : ^T * int -> ^T) (x, y)) namespace Microsoft.FSharp.Core diff --git a/src/fsharp/FSharp.Core/prim-types.fsi b/src/fsharp/FSharp.Core/prim-types.fsi index 4290c15d693..85b7dc12e25 100644 --- a/src/fsharp/FSharp.Core/prim-types.fsi +++ b/src/fsharp/FSharp.Core/prim-types.fsi @@ -803,7 +803,7 @@ namespace Microsoft.FSharp.Core type int64<[] 'Measure> = int64 /// Represents a managed pointer in F# code. -#if BUILDING_WITH_LKG || BUILD_FROM_SOURCE +#if BUILDING_WITH_LKG [] #else [] @@ -814,7 +814,7 @@ namespace Microsoft.FSharp.Core type byref<'T> = (# "!0&" #) /// Represents the types of byrefs in F# 4.5+ -#if BUILDING_WITH_LKG || BUILD_FROM_SOURCE +#if BUILDING_WITH_LKG [] #else [] @@ -822,7 +822,7 @@ namespace Microsoft.FSharp.Core module ByRefKinds = /// Represents a byref that can be written -#if BUILDING_WITH_LKG || BUILD_FROM_SOURCE +#if BUILDING_WITH_LKG [] #else [] @@ -830,7 +830,7 @@ namespace Microsoft.FSharp.Core type Out /// Represents a byref that can be read -#if BUILDING_WITH_LKG || BUILD_FROM_SOURCE +#if BUILDING_WITH_LKG [] #else [] @@ -838,7 +838,7 @@ namespace Microsoft.FSharp.Core type In /// Represents a byref that can be both read and written -#if BUILDING_WITH_LKG || BUILD_FROM_SOURCE +#if BUILDING_WITH_LKG [] #else [] @@ -1175,6 +1175,7 @@ namespace Microsoft.FSharp.Core /// The division result. val inline DivideByInt< ^T > : x:^T -> y:int -> ^T when ^T : (static member DivideByInt : ^T * int -> ^T) +#if !BUILDING_WITH_LKG [] /// Representative witnesses for traits solved by the F# compiler type BuiltInWitnesses = @@ -2474,6 +2475,7 @@ namespace Microsoft.FSharp.Core /// A representative witness for traits solved by the F# compiler static member inline DivideByInt: x: decimal * y: int -> decimal +#endif /// For compiler use only module (* internal *) ErrorStrings = diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index e119353901e..13b93dd933a 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -4563,7 +4563,7 @@ and GetIlxClosureFreeVars cenv m selfv eenvouter takenNames expr = let eenvinner = eenvinner |> AddStorageForLocalVals g ilCloFreeVarStorage // Return a various results - (cloAttribs, cloInternalFreeTyvars, cloContractFreeTyvars, cloFreeTyvars, cloFreeVars, ilCloTypeRef, ilCloAllFreeVars, eenvinner) + (cloAttribs, cloInternalFreeTyvars, cloContractFreeTyvars, cloWitnessInfos, cloFreeTyvars, cloFreeVars, ilCloTypeRef, ilCloAllFreeVars, eenvinner) and GetIlxClosureInfo cenv m isLocalTypeFunc selfv eenvouter expr = From 6ade1899b6d907963b5e10a4250048023f354271 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 18 Apr 2019 17:14:41 +0100 Subject: [PATCH 77/77] fix build --- src/fsharp/IlxGen.fs | 47 +++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 13b93dd933a..6e0f4dec0b3 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -704,6 +704,8 @@ type IlxClosureInfo = cloFreeTyvars: Typars + cloWitnessInfos: TraitWitnessInfos + /// ILX view of the lambdas for the closures ilCloLambdas: IlxClosureLambdas @@ -2911,6 +2913,24 @@ and GenUntupledArgExpr cenv cgbuf eenv m argInfos expr sequel = // Generate calls (try to detect direct calls) //-------------------------------------------------------------------------- +and GenWitnessArgFromInfo cenv cgbuf eenv m witnessInfo = + let g = cenv.g + let storage = TryStorageForWitness eenv witnessInfo + match storage with + | None -> + System.Diagnostics.Debug.Assert(false, "expected storage for witness") + | Some storage -> + let ty = GenWitnessTy g witnessInfo + GenGetStorageAndSequel cenv cgbuf eenv m (ty, GenType cenv.amap m eenv.tyenv ty) storage None + +and GenWitnessArgsFromInfos cenv cgbuf eenv m witnessInfos = + let g = cenv.g + let inWitnessPassingScope = not eenv.witnessesInScope.IsEmpty + // Witness arguments are only generated in emitted 'inline' code where witness parameters are available. + if g.generateWitnesses && inWitnessPassingScope then + for witnessInfo in witnessInfos do + GenWitnessArgFromInfo cenv cgbuf eenv m witnessInfo + and GenWitnessArgs cenv cgbuf eenv m tps tyargs = let g = cenv.g let inWitnessPassingScope = not eenv.witnessesInScope.IsEmpty @@ -2923,13 +2943,7 @@ and GenWitnessArgs cenv cgbuf eenv m tps tyargs = for witnessArg in mwitnesses do match witnessArg with | Choice1Of2 witnessInfo -> - let storage = TryStorageForWitness eenv witnessInfo - match storage with - | None -> - System.Diagnostics.Debug.Assert(false, "expected storage for witness") - | Some storage -> - let ty = GenWitnessTy g witnessInfo - GenGetStorageAndSequel cenv cgbuf eenv m (ty, GenType cenv.amap m eenv.tyenv ty) storage None + GenWitnessArgFromInfo cenv cgbuf eenv m witnessInfo | Choice2Of2 arg -> GenExpr cenv cgbuf eenv SPSuppress arg Continue @@ -4211,7 +4225,7 @@ and GenSequenceExpr eenvouter |> AddStorageForLocalVals g (stateVars |> List.map (fun v -> v.Deref, Local(0, false, None))) // Get the free variables. Make a lambda to pretend that the 'nextEnumeratorValRef' is bound (it is an argument to GenerateNext) - let (cloAttribs, _, _, cloFreeTyvars, cloFreeVars, ilCloTypeRef: ILTypeRef, ilCloAllFreeVars, eenvinner) = + let (cloAttribs, _, _, cloFreeTyvars, cloWitnessInfos, cloFreeVars, ilCloTypeRef: ILTypeRef, ilCloAllFreeVars, eenvinner) = GetIlxClosureFreeVars cenv m None eenvouter [] (mkLambda m nextEnumeratorValRef.Deref (generateNextExpr, g.int32_ty)) let ilCloSeqElemTy = GenType cenv.amap m eenvinner.tyenv seqElemTy @@ -4235,9 +4249,9 @@ and GenSequenceExpr CodeGenMethod cenv cgbuf.mgbuf ([], "GetFreshEnumerator", eenvinner, 1, (fun cgbuf eenv -> - GenWitnessArgs cenv cgbuf eenv m cloFreeTyvars (List.map mkTyparTy cloFreeTyvars) + GenWitnessArgsFromInfos cenv cgbuf eenv m cloWitnessInfos for fv in cloFreeVars do - /// State variables always get zero-initialized + // State variables always get zero-initialized if stateVarsSet.Contains fv then GenDefaultValue cenv cgbuf eenv (fv.Type, m) else @@ -4286,7 +4300,7 @@ and GenSequenceExpr CountClosure() - GenWitnessArgs cenv cgbuf eenvouter m cloFreeTyvars (List.map mkTyparTy cloFreeTyvars) + GenWitnessArgsFromInfos cenv cgbuf eenvouter m cloWitnessInfos for fv in cloFreeVars do /// State variables always get zero-initialized if stateVarsSet.Contains fv then @@ -4411,7 +4425,7 @@ and GenLambdaClosure cenv (cgbuf: CodeGenBuffer) eenv isLocalTypeFunc selfv expr and GenClosureAlloc cenv (cgbuf: CodeGenBuffer) eenv (cloinfo, m) = let g = cenv.g CountClosure() - GenWitnessArgs cenv cgbuf eenv m cloinfo.cloFreeTyvars (List.map mkTyparTy cloinfo.cloFreeTyvars) + GenWitnessArgsFromInfos cenv cgbuf eenv m cloinfo.cloWitnessInfos GenGetLocalVals cenv cgbuf eenv m cloinfo.cloFreeVars CG.EmitInstr cgbuf (pop cloinfo.ilCloAllFreeVars.Length) @@ -4563,7 +4577,7 @@ and GetIlxClosureFreeVars cenv m selfv eenvouter takenNames expr = let eenvinner = eenvinner |> AddStorageForLocalVals g ilCloFreeVarStorage // Return a various results - (cloAttribs, cloInternalFreeTyvars, cloContractFreeTyvars, cloWitnessInfos, cloFreeTyvars, cloFreeVars, ilCloTypeRef, ilCloAllFreeVars, eenvinner) + (cloAttribs, cloInternalFreeTyvars, cloContractFreeTyvars, cloFreeTyvars, cloWitnessInfos, cloFreeVars, ilCloTypeRef, ilCloAllFreeVars, eenvinner) and GetIlxClosureInfo cenv m isLocalTypeFunc selfv eenvouter expr = @@ -4593,7 +4607,7 @@ and GetIlxClosureInfo cenv m isLocalTypeFunc selfv eenvouter expr = let takenNames = vs |> List.map (fun v -> v.CompiledName) // Get the free variables and the information about the closure, add the free variables to the environment - let (cloAttribs, cloInternalFreeTyvars, cloContractFreeTyvars, cloFreeTyvars, cloFreeVars, ilCloTypeRef, ilCloAllFreeVars, eenvinner) = + let (cloAttribs, cloInternalFreeTyvars, cloContractFreeTyvars, cloFreeTyvars, cloWitnessInfos, cloFreeVars, ilCloTypeRef, ilCloAllFreeVars, eenvinner) = GetIlxClosureFreeVars cenv m selfv eenvouter takenNames expr // Put the type and value arguments into the environment @@ -4693,6 +4707,7 @@ and GetIlxClosureInfo cenv m isLocalTypeFunc selfv eenvouter expr = cloILGenericParams = ilCloGenericFormals cloFreeVars=cloFreeVars cloFreeTyvars=cloFreeTyvars + cloWitnessInfos = cloWitnessInfos cloAttribs=cloAttribs localTypeFuncContractFreeTypars = cloContractFreeTyvars localTypeFuncInternalFreeTypars = cloInternalFreeTyvars @@ -4752,7 +4767,7 @@ and GenDelegateExpr cenv cgbuf eenvouter expr (TObjExprMethod((TSlotSig(_, deleg // Work out the free type variables for the morphing thunk let takenNames = List.map nameOfVal tmvs - let (cloAttribs, _, _, cloFreeTyvars, cloFreeVars, ilDelegeeTypeRef, ilCloAllFreeVars, eenvinner) = + let (cloAttribs, _, _, cloFreeTyvars, cloWitnessInfos, cloFreeVars, ilDelegeeTypeRef, ilCloAllFreeVars, eenvinner) = GetIlxClosureFreeVars cenv m None eenvouter takenNames expr let ilDelegeeGenericParams = GenGenericParams cenv eenvinner cloFreeTyvars @@ -4792,7 +4807,7 @@ and GenDelegateExpr cenv cgbuf eenvouter expr (TObjExprMethod((TSlotSig(_, deleg let ctxtGenericArgsForDelegee = GenGenericArgs m eenvouter.tyenv cloFreeTyvars let ilxCloSpec = IlxClosureSpec.Create(IlxClosureRef(ilDelegeeTypeRef, ilCloLambdas, ilCloAllFreeVars), ctxtGenericArgsForDelegee) - GenWitnessArgs cenv cgbuf eenvouter m cloFreeTyvars (List.map mkTyparTy cloFreeTyvars) + GenWitnessArgsFromInfos cenv cgbuf eenvouter m cloWitnessInfos GenGetLocalVals cenv cgbuf eenvouter m cloFreeVars CG.EmitInstr cgbuf (pop ilCloAllFreeVars.Length) (Push [EraseClosures.mkTyOfLambdas g.ilxPubCloEnv ilCloLambdas]) (I_newobj (ilxCloSpec.Constructor, None))