From 402e1d3f2451bfe1795839b1684dc9965eedc4c7 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Tue, 18 May 2021 15:50:32 -0700 Subject: [PATCH 01/12] fix #10151 - Compiler doesn't build using dotnet on windows (#11582) * fix #10151 - Compiler doesn't build using dotnet on windows * fix #10151 - Compiler doesn't build using dotnet on windows --- FSharpBuild.Directory.Build.props | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/FSharpBuild.Directory.Build.props b/FSharpBuild.Directory.Build.props index 080077bc21e..767e0da6ebc 100644 --- a/FSharpBuild.Directory.Build.props +++ b/FSharpBuild.Directory.Build.props @@ -8,6 +8,11 @@ + + + true + + $(RepoRoot)src $(RepoRoot)tests @@ -16,7 +21,7 @@ 4.4.0 1182;0025;$(WarningsAsErrors) $(OtherFlags) --nowarn:3384 - + From 7f22a41c003511b8b5028da48d0330843f93baaf Mon Sep 17 00:00:00 2001 From: Will Smith Date: Thu, 20 May 2021 16:32:57 -0700 Subject: [PATCH 02/12] Use logical file name stamps to calculate logical project time stamp (#11590) --- src/fsharp/service/IncrementalBuild.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/service/IncrementalBuild.fs b/src/fsharp/service/IncrementalBuild.fs index 9eff18d0b67..27ef3b9fabc 100644 --- a/src/fsharp/service/IncrementalBuild.fs +++ b/src/fsharp/service/IncrementalBuild.fs @@ -1274,7 +1274,7 @@ type IncrementalBuilder(tcGlobals, let state = computeStampedFileNames state cache let state = computeStampedReferencedAssemblies state cache let t1 = MaxTimeStampInDependencies state.stampedReferencedAssemblies - let t2 = MaxTimeStampInDependencies state.stampedFileNames + let t2 = MaxTimeStampInDependencies state.logicalStampedFileNames max t1 t2 member _.TryGetSlotOfFileName(filename: string) = From c10a91f9840cc93cd0c2dceafb0e131b6231d439 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Sat, 22 May 2021 07:56:12 -0700 Subject: [PATCH 03/12] Added `FSharpReferencedProject.CreateFromILModuleReader` (#11593) * Added FSharpReferencedProject.CreateFromILModuleReader * Allowing to pass a DateTime and ILModuleReader function evaluation for ReferencedProject --- src/fsharp/service/FSharpCheckerResults.fs | 9 ++++++++- src/fsharp/service/FSharpCheckerResults.fsi | 4 ++++ src/fsharp/service/service.fs | 12 ++++++++++++ .../SurfaceArea.netstandard.fs | 1 + 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/fsharp/service/FSharpCheckerResults.fs b/src/fsharp/service/FSharpCheckerResults.fs index c888d9a109c..2f2778021bf 100644 --- a/src/fsharp/service/FSharpCheckerResults.fs +++ b/src/fsharp/service/FSharpCheckerResults.fs @@ -113,11 +113,13 @@ type internal DelayedILModuleReader = type FSharpReferencedProject = | FSharpReference of projectFileName: string * options: FSharpProjectOptions | PEReference of projectFileName: string * stamp: DateTime * delayedReader: DelayedILModuleReader + | ILModuleReference of projectFileName: string * getStamp: (unit -> DateTime) * getReader: (unit -> ILModuleReader) member this.FileName = match this with | FSharpReference(projectFileName=projectFileName) - | PEReference(projectFileName=projectFileName) -> projectFileName + | PEReference(projectFileName=projectFileName) + | ILModuleReference(projectFileName=projectFileName) -> projectFileName static member CreateFSharp(projectFileName, options) = FSharpReference(projectFileName, options) @@ -125,6 +127,9 @@ type FSharpReferencedProject = static member CreatePortableExecutable(projectFileName, stamp, getStream) = PEReference(projectFileName, stamp, DelayedILModuleReader(projectFileName, getStream)) + static member CreateFromILModuleReader(projectFileName, getStamp, getReader) = + ILModuleReference(projectFileName, getStamp, getReader) + override this.Equals(o) = match o with | :? FSharpReferencedProject as o -> @@ -133,6 +138,8 @@ type FSharpReferencedProject = projectFileName1 = projectFileName2 && options1 = options2 | PEReference(projectFileName1, stamp1, _), PEReference(projectFileName2, stamp2, _) -> projectFileName1 = projectFileName2 && stamp1 = stamp2 + | ILModuleReference(projectFileName1, getStamp1, _), ILModuleReference(projectFileName2, getStamp2, _) -> + projectFileName1 = projectFileName2 && (getStamp1()) = (getStamp2()) | _ -> false | _ -> diff --git a/src/fsharp/service/FSharpCheckerResults.fsi b/src/fsharp/service/FSharpCheckerResults.fsi index 3414d35536a..4ad0867d00f 100644 --- a/src/fsharp/service/FSharpCheckerResults.fsi +++ b/src/fsharp/service/FSharpCheckerResults.fsi @@ -98,6 +98,7 @@ and [] public FSharpReferencedProject = internal | FSharpReference of projectFileName: string * options: FSharpProjectOptions | PEReference of projectFileName: string * stamp: DateTime * delayedReader: DelayedILModuleReader + | ILModuleReference of projectFileName: string * getStamp: (unit -> DateTime) * getReader: (unit -> ILModuleReader) member FileName : string @@ -110,6 +111,9 @@ and [] public FSharpReferencedProject = /// If the stream evaluation throws an exception, it will be automatically handled. static member CreatePortableExecutable : projectFileName: string * stamp: DateTime * getStream: (CancellationToken -> Stream option) -> FSharpReferencedProject + /// Creates a reference from an ILModuleReader. + static member CreateFromILModuleReader : projectFileName: string * getStamp: (unit -> DateTime) * getReader: (unit -> ILModuleReader) -> FSharpReferencedProject + /// Represents the use of an F# symbol from F# source code [] type public FSharpSymbolUse = diff --git a/src/fsharp/service/service.fs b/src/fsharp/service/service.fs index 2734108809e..d3b4d8043e5 100644 --- a/src/fsharp/service/service.fs +++ b/src/fsharp/service/service.fs @@ -279,6 +279,18 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC } member x.TryGetLogicalTimeStamp(_) = stamp |> Some member x.FileName = nm } + + | FSharpReferencedProject.ILModuleReference(nm,getStamp,getReader) -> + yield + { new IProjectReference with + member x.EvaluateRawContents(_) = + cancellable { + let ilReader = getReader() + let ilModuleDef, ilAsmRefs = ilReader.ILModuleDef, ilReader.ILAssemblyRefs + return RawFSharpAssemblyData(ilModuleDef, ilAsmRefs) :> IRawFSharpAssemblyData |> Some + } + member x.TryGetLogicalTimeStamp(_) = getStamp() |> Some + member x.FileName = nm } ] let loadClosure = scriptClosureCache.TryGet(AnyCallerThread, options) diff --git a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs index f8fffc54366..a20e0a8ce41 100644 --- a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs +++ b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs @@ -2126,6 +2126,7 @@ FSharp.Compiler.CodeAnalysis.FSharpProjectOptions: Void .ctor(System.String, Mic FSharp.Compiler.CodeAnalysis.FSharpReferencedProject FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: Boolean Equals(System.Object) FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: FSharp.Compiler.CodeAnalysis.FSharpReferencedProject CreateFSharp(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions) +FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: FSharp.Compiler.CodeAnalysis.FSharpReferencedProject CreateFromILModuleReader(System.String, Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,System.DateTime], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,FSharp.Compiler.AbstractIL.ILBinaryReader+ILModuleReader]) FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: FSharp.Compiler.CodeAnalysis.FSharpReferencedProject CreatePortableExecutable(System.String, System.DateTime, Microsoft.FSharp.Core.FSharpFunc`2[System.Threading.CancellationToken,Microsoft.FSharp.Core.FSharpOption`1[System.IO.Stream]]) FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: Int32 GetHashCode() FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: System.String FileName From d8c5e3e4cde44da61789888bc0f1555dd3bd1462 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Sat, 22 May 2021 07:56:29 -0700 Subject: [PATCH 04/12] Removing global IlxSettings (#11594) * Removing global IlxSettings * More cleanup * Fixing build * Added DummyFSharpCoreScopeRef * Updated comment --- src/fsharp/CompilerImports.fs | 44 +++++++------------ src/fsharp/CompilerOptions.fs | 3 +- .../FSharp.Compiler.Service.fsproj | 3 -- src/fsharp/TcGlobals.fs | 2 +- src/fsharp/TypedTreeOps.fs | 4 +- src/fsharp/absil/il.fs | 25 ++++++++--- src/fsharp/absil/il.fsi | 4 +- src/fsharp/ilx/EraseClosures.fs | 17 ++++--- src/fsharp/ilx/ilxsettings.fs | 38 ---------------- 9 files changed, 52 insertions(+), 88 deletions(-) delete mode 100644 src/fsharp/ilx/ilxsettings.fs diff --git a/src/fsharp/CompilerImports.fs b/src/fsharp/CompilerImports.fs index a989420947a..9dac4466b29 100644 --- a/src/fsharp/CompilerImports.fs +++ b/src/fsharp/CompilerImports.fs @@ -1830,28 +1830,10 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse else None) - let ilGlobals = mkILGlobals (primaryScopeRef, assembliesThatForwardToPrimaryAssembly) - frameworkTcImports.SetILGlobals ilGlobals - - // Load the rest of the framework DLLs all at once (they may be mutually recursive) - let! _assemblies = frameworkTcImports.RegisterAndImportReferencedAssemblies (ctok, resolvedAssemblies) - - // These are the DLLs we can search for well-known types - let sysCcus = - [| for ccu in frameworkTcImports.GetCcusInDeclOrder() do - //printfn "found sys ccu %s" ccu.AssemblyName - yield ccu |] - - //for ccu in nonFrameworkDLLs do - // printfn "found non-sys ccu %s" ccu.resolvedPath - - let tryFindSysTypeCcu path typeName = - sysCcus |> Array.tryFind (fun ccu -> ccuHasType ccu path typeName) - - let fslibCcu = + let fslibCcu, fsharpCoreAssemblyScopeRef = if tcConfig.compilingFslib then // When compiling FSharp.Core.dll, the fslibCcu reference to FSharp.Core.dll is a delayed ccu thunk fixed up during type checking - CcuThunk.CreateDelayed getFSharpCoreLibraryName + CcuThunk.CreateDelayed getFSharpCoreLibraryName, ILScopeRef.Local else let fslibCcuInfo = let coreLibraryReference = tcConfig.CoreLibraryDllReference() @@ -1873,13 +1855,21 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse error(InternalError("BuildFrameworkTcImports: no successful import of "+coreLibraryResolution.resolvedPath, coreLibraryResolution.originalReference.Range)) | None -> error(InternalError(sprintf "BuildFrameworkTcImports: no resolution of '%s'" coreLibraryReference.Text, rangeStartup)) - IlxSettings.ilxFsharpCoreLibAssemRef <- - (let scoref = fslibCcuInfo.ILScopeRef - match scoref with - | ILScopeRef.Assembly aref -> Some aref - | ILScopeRef.Local | ILScopeRef.Module _ | ILScopeRef.PrimaryAssembly -> - error(InternalError("not ILScopeRef.Assembly", rangeStartup))) - fslibCcuInfo.FSharpViewOfMetadata + fslibCcuInfo.FSharpViewOfMetadata, fslibCcuInfo.ILScopeRef + + // Load the rest of the framework DLLs all at once (they may be mutually recursive) + let! _assemblies = frameworkTcImports.RegisterAndImportReferencedAssemblies (ctok, resolvedAssemblies) + + // These are the DLLs we can search for well-known types + let sysCcus = + [| for ccu in frameworkTcImports.GetCcusInDeclOrder() do + yield ccu |] + + let tryFindSysTypeCcu path typeName = + sysCcus |> Array.tryFind (fun ccu -> ccuHasType ccu path typeName) + + let ilGlobals = mkILGlobals (primaryScopeRef, assembliesThatForwardToPrimaryAssembly, fsharpCoreAssemblyScopeRef) + frameworkTcImports.SetILGlobals ilGlobals // OK, now we have both mscorlib.dll and FSharp.Core.dll we can create TcGlobals let tcGlobals = TcGlobals(tcConfig.compilingFslib, ilGlobals, fslibCcu, diff --git a/src/fsharp/CompilerOptions.fs b/src/fsharp/CompilerOptions.fs index c40cbf50a07..0c064437043 100644 --- a/src/fsharp/CompilerOptions.fs +++ b/src/fsharp/CompilerOptions.fs @@ -1264,8 +1264,7 @@ let compilingFsLibFlag (tcConfigB: TcConfigBuilder) = OptionUnit (fun () -> tcConfigB.compilingFslib <- true tcConfigB.TurnWarningOff(rangeStartup, "42") - ErrorLogger.reportLibraryOnlyFeatures <- false - IlxSettings.ilxCompilingFSharpCoreLib <- true), + ErrorLogger.reportLibraryOnlyFeatures <- false), Some(InternalCommandLineOption("--compiling-fslib", rangeCmdArgs)), None) let compilingFsLib20Flag = diff --git a/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj b/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj index 6f63ba25673..8d22cba56df 100644 --- a/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj +++ b/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj @@ -373,9 +373,6 @@ PrettyNaming\PrettyNaming.fs - - ILXErase\ilxsettings.fs - ILXErase\EraseClosures.fsi diff --git a/src/fsharp/TcGlobals.fs b/src/fsharp/TcGlobals.fs index dd4bf222c0d..9d03fc448f7 100755 --- a/src/fsharp/TcGlobals.fs +++ b/src/fsharp/TcGlobals.fs @@ -552,7 +552,7 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d | None -> TType_app(tcref, l) let mk_MFCore_attrib nm : BuiltinAttribInfo = - AttribInfo(mkILTyRef(IlxSettings.ilxFsharpCoreLibScopeRef (), FSharpLib.Core + "." + nm), mk_MFCore_tcref fslibCcu nm) + AttribInfo(mkILTyRef(ilg.fsharpCoreAssemblyScopeRef, FSharpLib.Core + "." + nm), mk_MFCore_tcref fslibCcu nm) let mk_doc filename = ILSourceDocument.Create(language=None, vendor=None, documentType=None, file=filename) // Build the memoization table for files diff --git a/src/fsharp/TypedTreeOps.fs b/src/fsharp/TypedTreeOps.fs index 12a2b46abef..3f6d2f3d327 100644 --- a/src/fsharp/TypedTreeOps.fs +++ b/src/fsharp/TypedTreeOps.fs @@ -7396,11 +7396,11 @@ let tname_SignatureDataVersionAttr = FSharpLib.Core + ".FSharpInterfaceDataVersi let tnames_SignatureDataVersionAttr = splitILTypeName tname_SignatureDataVersionAttr -let tref_SignatureDataVersionAttr () = mkILTyRef(IlxSettings.ilxFsharpCoreLibScopeRef (), tname_SignatureDataVersionAttr) +let tref_SignatureDataVersionAttr fsharpCoreAssemblyScopeRef = mkILTyRef(fsharpCoreAssemblyScopeRef, tname_SignatureDataVersionAttr) let mkSignatureDataVersionAttr (g: TcGlobals) (version: ILVersionInfo) = mkILCustomAttribute g.ilg - (tref_SignatureDataVersionAttr(), + (tref_SignatureDataVersionAttr g.ilg.fsharpCoreAssemblyScopeRef, [g.ilg.typ_Int32;g.ilg.typ_Int32;g.ilg.typ_Int32], [ILAttribElem.Int32 (int32 version.Major) ILAttribElem.Int32 (int32 version.Minor) diff --git a/src/fsharp/absil/il.fs b/src/fsharp/absil/il.fs index a2e1f0ee3ec..da31dd9d2c8 100644 --- a/src/fsharp/absil/il.fs +++ b/src/fsharp/absil/il.fs @@ -2633,7 +2633,7 @@ let tname_UIntPtr = "System.UIntPtr" let tname_TypedReference = "System.TypedReference" [] -type ILGlobals(primaryScopeRef: ILScopeRef, assembliesThatForwardToPrimaryAssembly: ILAssemblyRef list) = +type ILGlobals(primaryScopeRef: ILScopeRef, assembliesThatForwardToPrimaryAssembly: ILAssemblyRef list, fsharpCoreAssemblyScopeRef: ILScopeRef) = let assembliesThatForwardToPrimaryAssembly = Array.ofList assembliesThatForwardToPrimaryAssembly @@ -2666,6 +2666,8 @@ type ILGlobals(primaryScopeRef: ILScopeRef, assembliesThatForwardToPrimaryAssemb member val typ_UIntPtr = ILType.Value (mkILNonGenericTySpec (mkSysILTypeRef tname_UIntPtr)) member val typ_TypedReference = ILType.Value (mkILNonGenericTySpec (mkSysILTypeRef tname_TypedReference)) + member _.fsharpCoreAssemblyScopeRef = fsharpCoreAssemblyScopeRef + member x.IsPossiblePrimaryAssemblyRef(aref: ILAssemblyRef) = aref.EqualsIgnoringVersion x.primaryAssemblyRef || assembliesThatForwardToPrimaryAssembly @@ -2677,7 +2679,7 @@ type ILGlobals(primaryScopeRef: ILScopeRef, assembliesThatForwardToPrimaryAssemb override x.ToString() = "" -let mkILGlobals (primaryScopeRef, assembliesThatForwardToPrimaryAssembly) = ILGlobals (primaryScopeRef, assembliesThatForwardToPrimaryAssembly) +let mkILGlobals (primaryScopeRef, assembliesThatForwardToPrimaryAssembly, fsharpCoreAssemblyScopeRef) = ILGlobals (primaryScopeRef, assembliesThatForwardToPrimaryAssembly, fsharpCoreAssemblyScopeRef) let mkNormalCall mspec = I_call (Normalcall, mspec, None) @@ -3747,11 +3749,6 @@ let getCustomAttrData (ilg: ILGlobals) cattr = | ILAttribute.Decoded (mspec, fixedArgs, namedArgs) -> encodeCustomAttrArgs ilg mspec fixedArgs namedArgs -let MscorlibScopeRef = ILScopeRef.Assembly (ILAssemblyRef.Create ("mscorlib", None, Some ecmaPublicKey, true, None, None)) - -let EcmaMscorlibILGlobals = mkILGlobals (MscorlibScopeRef, []) -let PrimaryAssemblyILGlobals = mkILGlobals (ILScopeRef.PrimaryAssembly, []) - // ILSecurityDecl is a 'blob' having the following format: // - A byte containing a period (.). // - A compressed int32 containing the number of attributes encoded in the blob. @@ -4363,6 +4360,20 @@ let resolveILMethodRef td mref = resolveILMethodRefWithRescope id td mref let mkRefToILModule m = ILModuleRef.Create (m.Name, true, None) +let MscorlibScopeRef = ILScopeRef.Assembly (ILAssemblyRef.Create ("mscorlib", None, Some ecmaPublicKey, true, None, None)) + +let DummyFSharpCoreScopeRef = + let asmRef = + // The exact public key token and version used here don't actually matter, or shouldn't. + ILAssemblyRef.Create("FSharp.Core", None, + Some (PublicKeyToken(Bytes.ofInt32Array [| 0xb0; 0x3f; 0x5f; 0x7f; 0x11; 0xd5; 0x0a; 0x3a |])), + false, + Some (parseILVersion "0.0.0.0"), None) + ILScopeRef.Assembly asmRef + +let EcmaMscorlibILGlobals = mkILGlobals (MscorlibScopeRef, [], DummyFSharpCoreScopeRef) +let PrimaryAssemblyILGlobals = mkILGlobals (ILScopeRef.PrimaryAssembly, [], DummyFSharpCoreScopeRef) + type ILEventRef = { erA: ILTypeRef erB: string } diff --git a/src/fsharp/absil/il.fsi b/src/fsharp/absil/il.fsi index 14ce112b1d6..3528e62f60f 100644 --- a/src/fsharp/absil/il.fsi +++ b/src/fsharp/absil/il.fsi @@ -1643,6 +1643,8 @@ type internal ILGlobals = member typ_Char: ILType member typ_TypedReference: ILType + member fsharpCoreAssemblyScopeRef: ILScopeRef + /// Is the given assembly possibly a primary assembly? /// In practice, a primary assembly is an assembly that contains the System.Object type definition /// and has no referenced assemblies. @@ -1654,7 +1656,7 @@ type internal ILGlobals = member IsPossiblePrimaryAssemblyRef: ILAssemblyRef -> bool /// Build the table of commonly used references given functions to find types in system assemblies -val internal mkILGlobals: primaryScopeRef: ILScopeRef * assembliesThatForwardToPrimaryAssembly: ILAssemblyRef list -> ILGlobals +val internal mkILGlobals: primaryScopeRef: ILScopeRef * assembliesThatForwardToPrimaryAssembly: ILAssemblyRef list * fsharpCoreAssemblyScopeRef: ILScopeRef -> ILGlobals val internal EcmaMscorlibILGlobals: ILGlobals val internal PrimaryAssemblyILGlobals: ILGlobals diff --git a/src/fsharp/ilx/EraseClosures.fs b/src/fsharp/ilx/EraseClosures.fs index 6d6165de949..8f87eac097d 100644 --- a/src/fsharp/ilx/EraseClosures.fs +++ b/src/fsharp/ilx/EraseClosures.fs @@ -104,10 +104,13 @@ let isSupportedDirectCall apps = // for more refined types later. // -------------------------------------------------------------------- -let mkFuncTypeRef n = - if n = 1 then mkILTyRef (IlxSettings.ilxFsharpCoreLibScopeRef (), IlxSettings.ilxNamespace () + ".FSharpFunc`2") - else mkILNestedTyRef (IlxSettings.ilxFsharpCoreLibScopeRef (), - [IlxSettings.ilxNamespace () + ".OptimizedClosures"], +[] +let fsharpCoreNamespace = "Microsoft.FSharp.Core" + +let mkFuncTypeRef fsharpCoreAssemblyScopeRef n = + if n = 1 then mkILTyRef (fsharpCoreAssemblyScopeRef, fsharpCoreNamespace + ".FSharpFunc`2") + else mkILNestedTyRef (fsharpCoreAssemblyScopeRef, + [fsharpCoreNamespace + ".OptimizedClosures"], "FSharpFunc`"+ string (n + 1)) type cenv = { @@ -132,8 +135,8 @@ let addMethodGeneratedAttrsToTypeDef cenv (tdef: ILTypeDef) = let newIlxPubCloEnv(ilg, addMethodGeneratedAttrs, addFieldGeneratedAttrs, addFieldNeverAttrs) = { ilg = ilg - tref_Func = Array.init 10 (fun i -> mkFuncTypeRef(i+1)) - mkILTyFuncTy = ILType.Boxed (mkILNonGenericTySpec (mkILTyRef (IlxSettings.ilxFsharpCoreLibScopeRef (), IlxSettings.ilxNamespace () + ".FSharpTypeFunc"))) + tref_Func = Array.init 10 (fun i -> mkFuncTypeRef ilg.fsharpCoreAssemblyScopeRef (i+1)) + mkILTyFuncTy = ILType.Boxed (mkILNonGenericTySpec (mkILTyRef (ilg.fsharpCoreAssemblyScopeRef, fsharpCoreNamespace + ".FSharpTypeFunc"))) addMethodGeneratedAttrs = addMethodGeneratedAttrs addFieldGeneratedAttrs = addFieldGeneratedAttrs addFieldNeverAttrs = addFieldNeverAttrs } @@ -144,7 +147,7 @@ let mkILCurriedFuncTy cenv dtys rty = List.foldBack (mkILFuncTy cenv) dtys rty let typ_Func cenv (dtys: ILType list) rty = let n = dtys.Length - let tref = if n <= 10 then cenv.tref_Func.[n-1] else mkFuncTypeRef n + let tref = if n <= 10 then cenv.tref_Func.[n-1] else mkFuncTypeRef cenv.ilg.fsharpCoreAssemblyScopeRef n mkILBoxedTy tref (dtys @ [rty]) let rec mkTyOfApps cenv apps = diff --git a/src/fsharp/ilx/ilxsettings.fs b/src/fsharp/ilx/ilxsettings.fs deleted file mode 100644 index 9817505fca0..00000000000 --- a/src/fsharp/ilx/ilxsettings.fs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -module internal FSharp.Compiler.AbstractIL.ILX.IlxSettings - -open FSharp.Compiler.AbstractIL -open FSharp.Compiler.AbstractIL.IL -open FSharp.Compiler.IO -open Internal.Utilities - -type IlxCallImplementation = - | VirtEntriesVirtCode - -//++GLOBAL MUTABLE STATE (concurrency-safe because assigned only during F# library compilation) -let mutable ilxCompilingFSharpCoreLib = false - -//++GLOBAL MUTABLE STATE (concurrency-safe because assigned only during F# library compilation) -let mutable ilxFsharpCoreLibAssemRef = None : ILAssemblyRef option - -/// Scope references for FSharp.Core.dll -let ilxFsharpCoreLibScopeRef () = - if ilxCompilingFSharpCoreLib then - ILScopeRef.Local - else - let assemblyRef = - match ilxFsharpCoreLibAssemRef with - | Some o -> o - | None -> - // The exact public key token and version used here don't actually matter, or shouldn't. - // ilxFsharpCoreLibAssemRef is only 'None' for startup code paths such as - // IsSignatureDataVersionAttr, where matching is done by assembly name strings - // rather then versions and tokens. - ILAssemblyRef.Create("FSharp.Core", None, - Some (PublicKeyToken(Bytes.ofInt32Array [| 0xb0; 0x3f; 0x5f; 0x7f; 0x11; 0xd5; 0x0a; 0x3a |])), - false, - Some (IL.parseILVersion "0.0.0.0"), None) - ILScopeRef.Assembly assemblyRef - -let ilxNamespace () = "Microsoft.FSharp.Core" \ No newline at end of file From a70f3beacfe46bcd653cc6d525bd79497e6dd58e Mon Sep 17 00:00:00 2001 From: Will Smith Date: Sun, 23 May 2021 02:05:01 -0700 Subject: [PATCH 05/12] Removed 'reportLibraryOnlyFeatures' global mutable value (#11595) --- src/fsharp/CompilerOptions.fs | 3 +-- src/fsharp/ErrorLogger.fs | 7 ++----- src/fsharp/ErrorLogger.fsi | 2 -- src/fsharp/ParseAndCheckInputs.fs | 2 +- src/fsharp/ParseHelpers.fs | 8 +++---- src/fsharp/ParseHelpers.fsi | 4 ++-- src/fsharp/ScriptClosure.fs | 2 +- src/fsharp/UnicodeLexing.fs | 16 +++++++------- src/fsharp/UnicodeLexing.fsi | 8 +++---- src/fsharp/fsi/fsi.fs | 10 ++++----- src/fsharp/lex.fsl | 6 +++--- src/fsharp/pars.fsy | 15 ++++++------- src/fsharp/service/FSharpCheckerResults.fs | 2 +- src/fsharp/service/ServiceLexing.fs | 16 +++++++------- src/fsharp/utils/prim-lexing.fs | 21 ++++++++++--------- src/fsharp/utils/prim-lexing.fsi | 9 +++++--- .../HashIfExpression.fs | 2 +- 17 files changed, 67 insertions(+), 66 deletions(-) diff --git a/src/fsharp/CompilerOptions.fs b/src/fsharp/CompilerOptions.fs index 0c064437043..9d0c7dc6662 100644 --- a/src/fsharp/CompilerOptions.fs +++ b/src/fsharp/CompilerOptions.fs @@ -1263,8 +1263,7 @@ let compilingFsLibFlag (tcConfigB: TcConfigBuilder) = ("compiling-fslib", tagNone, OptionUnit (fun () -> tcConfigB.compilingFslib <- true - tcConfigB.TurnWarningOff(rangeStartup, "42") - ErrorLogger.reportLibraryOnlyFeatures <- false), + tcConfigB.TurnWarningOff(rangeStartup, "42")), Some(InternalCommandLineOption("--compiling-fslib", rangeCmdArgs)), None) let compilingFsLib20Flag = diff --git a/src/fsharp/ErrorLogger.fs b/src/fsharp/ErrorLogger.fs index c2dc29eb27c..a81e048c8ce 100644 --- a/src/fsharp/ErrorLogger.fs +++ b/src/fsharp/ErrorLogger.fs @@ -488,12 +488,9 @@ let report f = let deprecatedWithError s m = errorR(Deprecated(s, m)) -// Note: global state, but only for compiling FSharp.Core.dll -let mutable reportLibraryOnlyFeatures = true +let libraryOnlyError m = errorR(LibraryUseOnly m) -let libraryOnlyError m = if reportLibraryOnlyFeatures then errorR(LibraryUseOnly m) - -let libraryOnlyWarning m = if reportLibraryOnlyFeatures then warning(LibraryUseOnly m) +let libraryOnlyWarning m = warning(LibraryUseOnly m) let deprecatedOperator m = deprecatedWithError (FSComp.SR.elDeprecatedOperator()) m diff --git a/src/fsharp/ErrorLogger.fsi b/src/fsharp/ErrorLogger.fsi index a1e933fd9f0..bded498a198 100644 --- a/src/fsharp/ErrorLogger.fsi +++ b/src/fsharp/ErrorLogger.fsi @@ -222,8 +222,6 @@ val report: f:(unit -> 'a) -> 'a val deprecatedWithError: s:string -> m:range -> unit -val mutable reportLibraryOnlyFeatures: bool - val libraryOnlyError: m:range -> unit val libraryOnlyWarning: m:range -> unit diff --git a/src/fsharp/ParseAndCheckInputs.fs b/src/fsharp/ParseAndCheckInputs.fs index 3fa2ae15aac..64d0419cecb 100644 --- a/src/fsharp/ParseAndCheckInputs.fs +++ b/src/fsharp/ParseAndCheckInputs.fs @@ -408,7 +408,7 @@ let parseInputFileAux (tcConfig: TcConfig, lexResourceManager, conditionalCompil use reader = fileStream.GetReader(tcConfig.inputCodePage, retryLocked) // Set up the LexBuffer for the file - let lexbuf = UnicodeLexing.StreamReaderAsLexbuf(tcConfig.langVersion.SupportsFeature, reader) + let lexbuf = UnicodeLexing.StreamReaderAsLexbuf(not tcConfig.compilingFslib, tcConfig.langVersion.SupportsFeature, reader) // Parse the file drawing tokens from the lexbuf ParseOneInputLexbuf(tcConfig, lexResourceManager, conditionalCompilationDefines, lexbuf, filename, isLastCompiland, errorLogger) diff --git a/src/fsharp/ParseHelpers.fs b/src/fsharp/ParseHelpers.fs index e9c841b7fbc..3bcfe0938d6 100644 --- a/src/fsharp/ParseHelpers.fs +++ b/src/fsharp/ParseHelpers.fs @@ -220,7 +220,7 @@ and LexCont = LexerContinuation // Parse IL assembly code //------------------------------------------------------------------------ -let ParseAssemblyCodeInstructions s (isFeatureSupported: LanguageFeature -> bool) m : IL.ILInstr[] = +let ParseAssemblyCodeInstructions s reportLibraryOnlyFeatures (isFeatureSupported: LanguageFeature -> bool) m : IL.ILInstr[] = #if NO_INLINE_IL_PARSER ignore s ignore isFeatureSupported @@ -231,12 +231,12 @@ let ParseAssemblyCodeInstructions s (isFeatureSupported: LanguageFeature -> bool try FSharp.Compiler.AbstractIL.AsciiParser.ilInstrs FSharp.Compiler.AbstractIL.AsciiLexer.token - (UnicodeLexing.StringAsLexbuf(isFeatureSupported, s)) + (UnicodeLexing.StringAsLexbuf(reportLibraryOnlyFeatures, isFeatureSupported, s)) with _ -> errorR(Error(FSComp.SR.astParseEmbeddedILError(), m)); [||] #endif -let ParseAssemblyCodeType s (isFeatureSupported: Features.LanguageFeature -> bool) m = +let ParseAssemblyCodeType s reportLibraryOnlyFeatures (isFeatureSupported: Features.LanguageFeature -> bool) m = ignore s ignore isFeatureSupported @@ -248,7 +248,7 @@ let ParseAssemblyCodeType s (isFeatureSupported: Features.LanguageFeature -> boo try FSharp.Compiler.AbstractIL.AsciiParser.ilType FSharp.Compiler.AbstractIL.AsciiLexer.token - (UnicodeLexing.StringAsLexbuf(isFeatureSupported, s)) + (UnicodeLexing.StringAsLexbuf(reportLibraryOnlyFeatures, isFeatureSupported, s)) with RecoverableParseError -> errorR(Error(FSComp.SR.astParseEmbeddedILTypeError(), m)); IL.EcmaMscorlibILGlobals.typ_Object diff --git a/src/fsharp/ParseHelpers.fsi b/src/fsharp/ParseHelpers.fsi index c643552c9cc..716246338a2 100644 --- a/src/fsharp/ParseHelpers.fsi +++ b/src/fsharp/ParseHelpers.fsi @@ -108,6 +108,6 @@ type LexerContinuation = and LexCont = LexerContinuation -val ParseAssemblyCodeInstructions: s:string -> isFeatureSupported:(Features.LanguageFeature -> bool) -> m:range -> ILInstr[] +val ParseAssemblyCodeInstructions: s:string -> reportLibraryOnlyFeatures: bool -> isFeatureSupported:(Features.LanguageFeature -> bool) -> m:range -> ILInstr[] -val ParseAssemblyCodeType: s:string -> isFeatureSupported:(Features.LanguageFeature -> bool) -> m:range -> ILType +val ParseAssemblyCodeType: s:string -> reportLibraryOnlyFeatures: bool -> isFeatureSupported:(Features.LanguageFeature -> bool) -> m:range -> ILType diff --git a/src/fsharp/ScriptClosure.fs b/src/fsharp/ScriptClosure.fs index 03498b92067..46b1b368d2f 100644 --- a/src/fsharp/ScriptClosure.fs +++ b/src/fsharp/ScriptClosure.fs @@ -111,7 +111,7 @@ module ScriptPreprocessClosure = | CodeContext.Editing -> "EDITING" :: (if IsScript filename then ["INTERACTIVE"] else ["COMPILED"]) let isFeatureSupported featureId = tcConfig.langVersion.SupportsFeature featureId - let lexbuf = UnicodeLexing.SourceTextAsLexbuf(isFeatureSupported, sourceText) + let lexbuf = UnicodeLexing.SourceTextAsLexbuf(true, isFeatureSupported, sourceText) let isLastCompiland = (IsScript filename), tcConfig.target.IsExe // The root compiland is last in the list of compilands. ParseOneInputLexbuf (tcConfig, lexResourceManager, defines, lexbuf, filename, isLastCompiland, errorLogger) diff --git a/src/fsharp/UnicodeLexing.fs b/src/fsharp/UnicodeLexing.fs index 7b7f631fc50..99ee27ff721 100644 --- a/src/fsharp/UnicodeLexing.fs +++ b/src/fsharp/UnicodeLexing.fs @@ -8,18 +8,18 @@ open Internal.Utilities.Text.Lexing type Lexbuf = LexBuffer -let StringAsLexbuf (supportsFeature, s: string) = - LexBuffer.FromChars (supportsFeature, s.ToCharArray()) +let StringAsLexbuf (reportLibraryOnlyFeatures, supportsFeature, s: string) = + LexBuffer.FromChars (reportLibraryOnlyFeatures, supportsFeature, s.ToCharArray()) -let FunctionAsLexbuf (supportsFeature, bufferFiller) = - LexBuffer.FromFunction(supportsFeature, bufferFiller) +let FunctionAsLexbuf (reportLibraryOnlyFeatures, supportsFeature, bufferFiller) = + LexBuffer.FromFunction(reportLibraryOnlyFeatures, supportsFeature, bufferFiller) -let SourceTextAsLexbuf (supportsFeature, sourceText) = - LexBuffer.FromSourceText(supportsFeature, sourceText) +let SourceTextAsLexbuf (reportLibraryOnlyFeatures, supportsFeature, sourceText) = + LexBuffer.FromSourceText(reportLibraryOnlyFeatures, supportsFeature, sourceText) -let StreamReaderAsLexbuf (supportsFeature, reader: StreamReader) = +let StreamReaderAsLexbuf (reportLibraryOnlyFeatures, supportsFeature, reader: StreamReader) = let mutable isFinished = false - FunctionAsLexbuf (supportsFeature, fun (chars, start, length) -> + FunctionAsLexbuf (reportLibraryOnlyFeatures, supportsFeature, fun (chars, start, length) -> if isFinished then 0 else let nBytesRead = reader.Read(chars, start, length) diff --git a/src/fsharp/UnicodeLexing.fsi b/src/fsharp/UnicodeLexing.fsi index 7b27e829d14..838b96a6a11 100644 --- a/src/fsharp/UnicodeLexing.fsi +++ b/src/fsharp/UnicodeLexing.fsi @@ -9,11 +9,11 @@ open Internal.Utilities.Text.Lexing type Lexbuf = LexBuffer -val internal StringAsLexbuf: (LanguageFeature -> bool) * string -> Lexbuf +val internal StringAsLexbuf: reportLibraryOnlyFeatures: bool * (LanguageFeature -> bool) * string -> Lexbuf -val public FunctionAsLexbuf: (LanguageFeature -> bool) * (char [] * int * int -> int) -> Lexbuf +val public FunctionAsLexbuf: reportLibraryOnlyFeatures: bool * (LanguageFeature -> bool) * (char [] * int * int -> int) -> Lexbuf -val public SourceTextAsLexbuf: (LanguageFeature -> bool) * ISourceText -> Lexbuf +val public SourceTextAsLexbuf: reportLibraryOnlyFeatures: bool * (LanguageFeature -> bool) * ISourceText -> Lexbuf /// Will not dispose of the stream reader. -val public StreamReaderAsLexbuf: (LanguageFeature -> bool) * StreamReader -> Lexbuf +val public StreamReaderAsLexbuf: reportLibraryOnlyFeatures: bool * (LanguageFeature -> bool) * StreamReader -> Lexbuf diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index 50b896385f5..f463f938857 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -2005,7 +2005,7 @@ type internal FsiStdinLexerProvider let LexbufFromLineReader (fsiStdinSyphon: FsiStdinSyphon) readF = UnicodeLexing.FunctionAsLexbuf - (isFeatureSupported, (fun (buf: char[], start, len) -> + (true, isFeatureSupported, (fun (buf: char[], start, len) -> //fprintf fsiConsoleOutput.Out "Calling ReadLine\n" let inputOption = try Some(readF()) with :? EndOfStreamException -> None inputOption |> Option.iter (fun t -> fsiStdinSyphon.Add (t + "\n")) @@ -2061,12 +2061,12 @@ type internal FsiStdinLexerProvider // Create a new lexer to read an "included" script file member _.CreateIncludedScriptLexer (sourceFileName, reader, errorLogger) = - let lexbuf = UnicodeLexing.StreamReaderAsLexbuf(isFeatureSupported, reader) + let lexbuf = UnicodeLexing.StreamReaderAsLexbuf(true, isFeatureSupported, reader) CreateLexerForLexBuffer (sourceFileName, lexbuf, errorLogger) // Create a new lexer to read a string member this.CreateStringLexer (sourceFileName, source, errorLogger) = - let lexbuf = UnicodeLexing.StringAsLexbuf(isFeatureSupported, source) + let lexbuf = UnicodeLexing.StringAsLexbuf(true, isFeatureSupported, source) CreateLexerForLexBuffer (sourceFileName, lexbuf, errorLogger) member _.ConsoleInput = fsiConsoleInput @@ -2536,7 +2536,7 @@ type internal FsiInteractionProcessor use _unwind1 = ErrorLogger.PushThreadBuildPhaseUntilUnwind(ErrorLogger.BuildPhase.Interactive) use _unwind2 = ErrorLogger.PushErrorLoggerPhaseUntilUnwind(fun _ -> errorLogger) use _scope = SetCurrentUICultureForThread fsiOptions.FsiLCID - let lexbuf = UnicodeLexing.StringAsLexbuf(isFeatureSupported, sourceText) + let lexbuf = UnicodeLexing.StringAsLexbuf(true, isFeatureSupported, sourceText) let tokenizer = fsiStdinLexerProvider.CreateBufferLexer(scriptFileName, lexbuf, errorLogger) currState |> InteractiveCatch errorLogger (fun istate -> @@ -2553,7 +2553,7 @@ type internal FsiInteractionProcessor use _unwind1 = ErrorLogger.PushThreadBuildPhaseUntilUnwind(ErrorLogger.BuildPhase.Interactive) use _unwind2 = ErrorLogger.PushErrorLoggerPhaseUntilUnwind(fun _ -> errorLogger) use _scope = SetCurrentUICultureForThread fsiOptions.FsiLCID - let lexbuf = UnicodeLexing.StringAsLexbuf(isFeatureSupported, sourceText) + let lexbuf = UnicodeLexing.StringAsLexbuf(true, isFeatureSupported, sourceText) let tokenizer = fsiStdinLexerProvider.CreateBufferLexer(scriptFileName, lexbuf, errorLogger) currState |> InteractiveCatch errorLogger (fun istate -> diff --git a/src/fsharp/lex.fsl b/src/fsharp/lex.fsl index 02b5621adc6..0aa3bc11ce3 100644 --- a/src/fsharp/lex.fsl +++ b/src/fsharp/lex.fsl @@ -208,8 +208,8 @@ let shouldStartFile args lexbuf (m:range) err tok = if (m.StartColumn <> 0 || m.StartLine <> 1) then fail args lexbuf err tok else tok -let evalIfDefExpression startPos isFeatureSupported args (lookup:string->bool) (lexed:string) = - let lexbuf = LexBuffer.FromChars (isFeatureSupported, lexed.ToCharArray ()) +let evalIfDefExpression startPos reportLibraryOnlyFeatures isFeatureSupported args (lookup:string->bool) (lexed:string) = + let lexbuf = LexBuffer.FromChars (reportLibraryOnlyFeatures, isFeatureSupported, lexed.ToCharArray ()) lexbuf.StartPos <- startPos lexbuf.EndPos <- startPos let tokenStream = FSharp.Compiler.PPLexer.tokenstream args @@ -934,7 +934,7 @@ rule token args skip = parse { let m = lexbuf.LexemeRange let lookup id = List.contains id args.defines let lexed = lexeme lexbuf - let isTrue = evalIfDefExpression lexbuf.StartPos lexbuf.SupportsFeature args lookup lexed + let isTrue = evalIfDefExpression lexbuf.StartPos lexbuf.ReportLibraryOnlyFeatures lexbuf.SupportsFeature args lookup lexed args.ifdefStack <- (IfDefIf,m) :: args.ifdefStack // Get the token; make sure it starts at zero position & return diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index 480063f79e4..06921be7304 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -2227,10 +2227,10 @@ tyconDefnOrSpfnSimpleRepr: | opt_attributes opt_declVisibility LPAREN HASH string HASH rparen { if not (isNil $1) then errorR(Error(FSComp.SR.parsAttributesIllegalHere(), rhs parseState 1)) let lhsm = lhs parseState - libraryOnlyError lhsm + if parseState.LexBuffer.ReportLibraryOnlyFeatures then libraryOnlyError lhsm if Option.isSome $2 then errorR(Error(FSComp.SR.parsInlineAssemblyCannotHaveVisibilityDeclarations(), rhs parseState 2)) let s, _ = $5 - let ilType = ParseAssemblyCodeType s parseState.LexBuffer.SupportsFeature (rhs parseState 5) + let ilType = ParseAssemblyCodeType s parseState.LexBuffer.ReportLibraryOnlyFeatures parseState.LexBuffer.SupportsFeature (rhs parseState 5) SynTypeDefnSimpleRepr.LibraryOnlyILAssembly (box ilType, lhsm) } @@ -2361,7 +2361,8 @@ typeConstraints: /* See the F# specification "Lexical analysis of type applications and type parameter definitions" */ typeConstraint: | DEFAULT typar COLON typ - { libraryOnlyError (lhs parseState); SynTypeConstraint.WhereTyparDefaultsToType($2, $4, lhs parseState) } + { if parseState.LexBuffer.ReportLibraryOnlyFeatures then libraryOnlyError (lhs parseState) + SynTypeConstraint.WhereTyparDefaultsToType($2, $4, lhs parseState) } | typar COLON_GREATER typ { SynTypeConstraint.WhereTyparSubtypeOfType($1, $3, lhs parseState) } @@ -2451,7 +2452,7 @@ attrUnionCaseDecl: | opt_attributes opt_access unionCaseName COLON topType { if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(), rhs parseState 2)) - libraryOnlyWarning(lhs parseState) + if parseState.LexBuffer.ReportLibraryOnlyFeatures then libraryOnlyWarning(lhs parseState) let mDecl = rhs2 parseState 1 5 (fun xmlDoc -> Choice2Of2 (SynUnionCase ( $1, $3, SynUnionCaseKind.FullType $5, xmlDoc, None, mDecl))) } @@ -4187,7 +4188,7 @@ atomicExprQualification: SynExpr.DiscardAfterMissingQualificationAfterDot (e, fixedLhsm)) } | LPAREN COLON_COLON rparen DOT INT32 { (fun e lhsm dotm -> - libraryOnlyError(lhs parseState) + if parseState.LexBuffer.ReportLibraryOnlyFeatures then libraryOnlyError(lhs parseState) SynExpr.LibraryOnlyUnionCaseFieldGet (e, mkSynCaseName lhsm opNameCons, (fst $5), lhsm)) } | LPAREN typedSeqExpr rparen @@ -4534,10 +4535,10 @@ forLoopDirection: inlineAssemblyExpr: | HASH string opt_inlineAssemblyTypeArg optCurriedArgExprs optInlineAssemblyReturnTypes HASH - { libraryOnlyWarning (lhs parseState) + { if parseState.LexBuffer.ReportLibraryOnlyFeatures then libraryOnlyWarning (lhs parseState) let (s, _), sm = $2, rhs parseState 2 (fun m -> - let ilInstrs = ParseAssemblyCodeInstructions s parseState.LexBuffer.SupportsFeature sm + let ilInstrs = ParseAssemblyCodeInstructions s parseState.LexBuffer.ReportLibraryOnlyFeatures parseState.LexBuffer.SupportsFeature sm SynExpr.LibraryOnlyILAssembly (box ilInstrs, $3, List.rev $4, $5, m)) } optCurriedArgExprs: diff --git a/src/fsharp/service/FSharpCheckerResults.fs b/src/fsharp/service/FSharpCheckerResults.fs index 2f2778021bf..e602a7d94ff 100644 --- a/src/fsharp/service/FSharpCheckerResults.fs +++ b/src/fsharp/service/FSharpCheckerResults.fs @@ -1640,7 +1640,7 @@ module internal ParseAndCheckFile = let isFeatureSupported (_featureId:LanguageFeature) = true let createLexbuf sourceText = - UnicodeLexing.SourceTextAsLexbuf(isFeatureSupported, sourceText) + UnicodeLexing.SourceTextAsLexbuf(true, isFeatureSupported, sourceText) let matchBraces(sourceText: ISourceText, fileName, options: FSharpParsingOptions, userOpName: string, suggestNamesForErrors: bool) = let delayedLogger = CapturingErrorLogger("matchBraces") diff --git a/src/fsharp/service/ServiceLexing.fs b/src/fsharp/service/ServiceLexing.fs index fffb5caadf8..f84b53343fc 100644 --- a/src/fsharp/service/ServiceLexing.fs +++ b/src/fsharp/service/ServiceLexing.fs @@ -924,17 +924,18 @@ type FSharpSourceTokenizer(conditionalDefines: string list, filename: string opt // Public callers are unable to answer LanguageVersion feature support questions. // External Tools including the VS IDE will enable the default LanguageVersion let isFeatureSupported (_featureId:LanguageFeature) = true + let reportLibraryOnlyFeatures = true let lexResourceManager = new Lexhelp.LexResourceManager() let lexargs = mkLexargs(conditionalDefines, LightSyntaxStatus(true, false), lexResourceManager, [], DiscardErrorsLogger, PathMap.empty) member _.CreateLineTokenizer(lineText: string) = - let lexbuf = UnicodeLexing.StringAsLexbuf(isFeatureSupported, lineText) + let lexbuf = UnicodeLexing.StringAsLexbuf(reportLibraryOnlyFeatures, isFeatureSupported, lineText) FSharpLineTokenizer(lexbuf, Some lineText.Length, filename, lexargs) member _.CreateBufferTokenizer bufferFiller = - let lexbuf = UnicodeLexing.FunctionAsLexbuf(isFeatureSupported, bufferFiller) + let lexbuf = UnicodeLexing.FunctionAsLexbuf(reportLibraryOnlyFeatures, isFeatureSupported, bufferFiller) FSharpLineTokenizer(lexbuf, None, filename, lexargs) module FSharpKeywords = @@ -1513,14 +1514,14 @@ type FSharpToken = [] module FSharpLexerImpl = - let lexWithErrorLogger (text: ISourceText) conditionalCompilationDefines (flags: FSharpLexerFlags) supportsFeature errorLogger onToken pathMap (ct: CancellationToken) = + let lexWithErrorLogger (text: ISourceText) conditionalCompilationDefines (flags: FSharpLexerFlags) reportLibraryOnlyFeatures supportsFeature errorLogger onToken pathMap (ct: CancellationToken) = let canSkipTrivia = (flags &&& FSharpLexerFlags.SkipTrivia) = FSharpLexerFlags.SkipTrivia let isLightSyntaxOn = (flags &&& FSharpLexerFlags.LightSyntaxOn) = FSharpLexerFlags.LightSyntaxOn let isCompiling = (flags &&& FSharpLexerFlags.Compiling) = FSharpLexerFlags.Compiling let isCompilingFSharpCore = (flags &&& FSharpLexerFlags.CompilingFSharpCore) = FSharpLexerFlags.CompilingFSharpCore let canUseLexFilter = (flags &&& FSharpLexerFlags.UseLexFilter) = FSharpLexerFlags.UseLexFilter - let lexbuf = UnicodeLexing.SourceTextAsLexbuf(supportsFeature, text) + let lexbuf = UnicodeLexing.SourceTextAsLexbuf(reportLibraryOnlyFeatures, supportsFeature, text) let lightStatus = LightSyntaxStatus(isLightSyntaxOn, true) let lexargs = mkLexargs (conditionalCompilationDefines, lightStatus, Lexhelp.LexResourceManager(0), [], errorLogger, pathMap) let lexargs = { lexargs with applyLineDirectives = isCompiling } @@ -1542,9 +1543,9 @@ module FSharpLexerImpl = ct.ThrowIfCancellationRequested () onToken (getNextToken lexbuf) lexbuf.LexemeRange - let lex text conditionalCompilationDefines flags supportsFeature lexCallback pathMap ct = + let lex text conditionalCompilationDefines flags reportLibraryOnlyFeatures supportsFeature lexCallback pathMap ct = let errorLogger = CompilationErrorLogger("Lexer", FSharpDiagnosticOptions.Default) - lexWithErrorLogger text conditionalCompilationDefines flags supportsFeature errorLogger lexCallback pathMap ct + lexWithErrorLogger text conditionalCompilationDefines flags reportLibraryOnlyFeatures supportsFeature errorLogger lexCallback pathMap ct [] type FSharpLexer = @@ -1569,4 +1570,5 @@ type FSharpLexer = | FSharpTokenKind.None -> () | _ -> tokenCallback fsTok - lex text conditionalCompilationDefines flags supportsFeature onToken pathMap ct + let reportLibraryOnlyFeatures = true + lex text conditionalCompilationDefines flags reportLibraryOnlyFeatures supportsFeature onToken pathMap ct diff --git a/src/fsharp/utils/prim-lexing.fs b/src/fsharp/utils/prim-lexing.fs index 6a691af3cba..f5d4edee585 100644 --- a/src/fsharp/utils/prim-lexing.fs +++ b/src/fsharp/utils/prim-lexing.fs @@ -177,7 +177,7 @@ namespace Internal.Utilities.Text.Lexing type internal LexBufferFiller<'Char> = (LexBuffer<'Char> -> unit) and [] - internal LexBuffer<'Char>(filler: LexBufferFiller<'Char>, supportsFeature:LanguageFeature -> bool) = + internal LexBuffer<'Char>(filler: LexBufferFiller<'Char>, reportLibraryOnlyFeatures: bool, supportsFeature:LanguageFeature -> bool) = let context = new Dictionary(1) let mutable buffer = [||] /// number of valid characters beyond bufferScanStart. @@ -247,35 +247,36 @@ namespace Internal.Utilities.Text.Lexing Array.blit buffer bufferScanStart repl bufferScanStart bufferScanLength buffer <- repl + member _.ReportLibraryOnlyFeatures = reportLibraryOnlyFeatures member _.SupportsFeature featureId = supportsFeature featureId - static member FromFunction (supportsFeature:LanguageFeature -> bool, f : 'Char[] * int * int -> int) : LexBuffer<'Char> = + static member FromFunction (reportLibraryOnlyFeatures, supportsFeature:LanguageFeature -> bool, f : 'Char[] * int * int -> int) : LexBuffer<'Char> = let extension= Array.zeroCreate 4096 let filler (lexBuffer: LexBuffer<'Char>) = let n = f (extension,0,extension.Length) lexBuffer.EnsureBufferSize n Array.blit extension 0 lexBuffer.Buffer lexBuffer.BufferScanPos n lexBuffer.BufferMaxScanLength <- lexBuffer.BufferScanLength + n - new LexBuffer<'Char>(filler, supportsFeature) + new LexBuffer<'Char>(filler, reportLibraryOnlyFeatures, supportsFeature) // Important: This method takes ownership of the array - static member FromArrayNoCopy (supportsFeature:LanguageFeature -> bool, buffer: 'Char[]) : LexBuffer<'Char> = - let lexBuffer = new LexBuffer<'Char>((fun _ -> ()), supportsFeature) + static member FromArrayNoCopy (reportLibraryOnlyFeatures, supportsFeature:LanguageFeature -> bool, buffer: 'Char[]) : LexBuffer<'Char> = + let lexBuffer = new LexBuffer<'Char>((fun _ -> ()), reportLibraryOnlyFeatures, supportsFeature) lexBuffer.Buffer <- buffer lexBuffer.BufferMaxScanLength <- buffer.Length lexBuffer // Important: this method does copy the array - static member FromArray (supportsFeature: LanguageFeature -> bool, s: 'Char[]) : LexBuffer<'Char> = + static member FromArray (reportLibraryOnlyFeatures, supportsFeature: LanguageFeature -> bool, s: 'Char[]) : LexBuffer<'Char> = let buffer = Array.copy s - LexBuffer<'Char>.FromArrayNoCopy(supportsFeature, buffer) + LexBuffer<'Char>.FromArrayNoCopy(reportLibraryOnlyFeatures, supportsFeature, buffer) // Important: This method takes ownership of the array - static member FromChars (supportsFeature:LanguageFeature -> bool, arr:char[]) = LexBuffer.FromArrayNoCopy (supportsFeature, arr) + static member FromChars (reportLibraryOnlyFeatures, supportsFeature:LanguageFeature -> bool, arr:char[]) = LexBuffer.FromArrayNoCopy (reportLibraryOnlyFeatures, supportsFeature, arr) - static member FromSourceText (supportsFeature: LanguageFeature -> bool, sourceText: ISourceText) = + static member FromSourceText (reportLibraryOnlyFeatures, supportsFeature: LanguageFeature -> bool, sourceText: ISourceText) = let mutable currentSourceIndex = 0 - LexBuffer.FromFunction(supportsFeature, fun (chars, start, length) -> + LexBuffer.FromFunction(reportLibraryOnlyFeatures, supportsFeature, fun (chars, start, length) -> let lengthToCopy = if currentSourceIndex + length <= sourceText.Length then length diff --git a/src/fsharp/utils/prim-lexing.fsi b/src/fsharp/utils/prim-lexing.fsi index 5c55267e7c1..d8023a76f6d 100644 --- a/src/fsharp/utils/prim-lexing.fsi +++ b/src/fsharp/utils/prim-lexing.fsi @@ -124,18 +124,21 @@ type internal LexBuffer<'Char> = /// True if the refill of the buffer ever failed , or if explicitly set to True. member IsPastEndOfStream: bool with get,set + /// Determines if the parser can report FSharpCore library-only features. + member ReportLibraryOnlyFeatures: bool + /// True if the refill of the buffer ever failed , or if explicitly set to True. member SupportsFeature:LanguageFeature -> bool /// Create a lex buffer suitable for Unicode lexing that reads characters from the given array. /// Important: does take ownership of the array. - static member FromChars: (LanguageFeature -> bool) * char[] -> LexBuffer + static member FromChars: reportLibraryOnlyFeatures: bool * (LanguageFeature -> bool) * char[] -> LexBuffer /// Create a lex buffer that reads character or byte inputs by using the given function. - static member FromFunction: (LanguageFeature -> bool) * ('Char[] * int * int -> int) -> LexBuffer<'Char> + static member FromFunction: reportLibraryOnlyFeatures: bool * (LanguageFeature -> bool) * ('Char[] * int * int -> int) -> LexBuffer<'Char> /// Create a lex buffer backed by source text. - static member FromSourceText: (LanguageFeature -> bool) * ISourceText -> LexBuffer + static member FromSourceText: reportLibraryOnlyFeatures: bool * (LanguageFeature -> bool) * ISourceText -> LexBuffer /// The type of tables for an unicode lexer generated by fslex.exe. [] diff --git a/tests/FSharp.Compiler.UnitTests/HashIfExpression.fs b/tests/FSharp.Compiler.UnitTests/HashIfExpression.fs index 6bb73161192..201c3291902 100644 --- a/tests/FSharp.Compiler.UnitTests/HashIfExpression.fs +++ b/tests/FSharp.Compiler.UnitTests/HashIfExpression.fs @@ -70,7 +70,7 @@ type public HashIfExpression() = let parser (s : string) = let isFeatureSupported (_featureId:LanguageFeature) = true - let lexbuf = LexBuffer.FromChars (isFeatureSupported, s.ToCharArray ()) + let lexbuf = LexBuffer.FromChars (true, isFeatureSupported, s.ToCharArray ()) lexbuf.StartPos <- startPos lexbuf.EndPos <- startPos let tokenStream = PPLexer.tokenstream args From 4f15bc4c7924fc03d7784157ef9336967b49e966 Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Mon, 24 May 2021 17:53:23 -0600 Subject: [PATCH 06/12] Merge pull request #11587 from dotnet/flaky-tests skip flaky tests --- .../Microsoft.FSharp.Control/AsyncModule.fs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/AsyncModule.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/AsyncModule.fs index ca1d1917067..303df51ecb8 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/AsyncModule.fs +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/AsyncModule.fs @@ -272,8 +272,9 @@ type AsyncModule() = | e -> Assert.Fail(sprintf "Unexpected error %A" e) } Async.RunSynchronously test - - [] + + // test is flaky: https://github.com/dotnet/fsharp/issues/11586 + //[] member this.``OnCancel.RaceBetweenCancellationHandlerAndDisposingHandlerRegistration``() = let test() = use flag = new ManualResetEvent(false) @@ -296,7 +297,8 @@ type AsyncModule() = for _i = 1 to 300 do test() - [] + // test is flaky: https://github.com/dotnet/fsharp/issues/11586 + //[] member this.``OnCancel.RaceBetweenCancellationAndDispose``() = let flag = ref 0 let cts = new System.Threading.CancellationTokenSource() @@ -314,7 +316,8 @@ type AsyncModule() = :? System.OperationCanceledException -> () Assert.AreEqual(1, !flag) - [] + // test is flaky: https://github.com/dotnet/fsharp/issues/11586 + //[] member this.``OnCancel.CancelThatWasSignalledBeforeRunningTheComputation``() = let test() = let cts = new System.Threading.CancellationTokenSource() From c2b0c768c76ce5b32b8de8cffe96c4f7f78015fc Mon Sep 17 00:00:00 2001 From: Will Smith Date: Tue, 25 May 2021 09:06:37 -0700 Subject: [PATCH 07/12] Removed ILGlobals dependency on encoding/decoding attributes (#11597) * Removed ILGlobals dependency on encoding/decoding attributes * Removed EcmaMscorlibILGlobals global --- src/fsharp/AttributeChecking.fs | 14 +- src/fsharp/CheckExpressions.fs | 2 +- src/fsharp/CompilerConfig.fs | 6 +- src/fsharp/CompilerConfig.fsi | 6 +- src/fsharp/CompilerImports.fs | 58 +++----- src/fsharp/CompilerImports.fsi | 1 - src/fsharp/CreateILModule.fs | 2 +- src/fsharp/IlxGen.fs | 10 +- src/fsharp/ParseHelpers.fs | 4 +- src/fsharp/StaticLinking.fs | 6 +- src/fsharp/TcGlobals.fs | 18 +-- src/fsharp/TypedTreeOps.fs | 34 ++--- src/fsharp/TypedTreeOps.fsi | 10 +- src/fsharp/absil/il.fs | 193 ++++++++++++------------- src/fsharp/absil/il.fsi | 12 +- src/fsharp/absil/ilmorph.fs | 92 ++++++------ src/fsharp/absil/ilmorph.fsi | 4 +- src/fsharp/absil/ilprint.fs | 38 ++--- src/fsharp/absil/ilreflect.fs | 4 +- src/fsharp/absil/ilwrite.fs | 2 +- src/fsharp/fsc.fs | 4 +- src/fsharp/fsi/fsi.fs | 4 +- src/fsharp/infos.fs | 2 +- src/fsharp/service/IncrementalBuild.fs | 8 +- src/fsharp/symbols/Symbols.fs | 2 +- 25 files changed, 258 insertions(+), 278 deletions(-) diff --git a/src/fsharp/AttributeChecking.fs b/src/fsharp/AttributeChecking.fs index 1f6f9eac191..f8a3f4f34dd 100644 --- a/src/fsharp/AttributeChecking.fs +++ b/src/fsharp/AttributeChecking.fs @@ -98,8 +98,8 @@ type AttribInfo = let ty = tyOfExpr g origExpr let obj = evalFSharpAttribArg g evaluatedExpr ty, obj) - | ILAttribInfo (g, amap, scoref, cattr, m) -> - let parms, _args = decodeILAttribData g.ilg cattr + | ILAttribInfo (_g, amap, scoref, cattr, m) -> + let parms, _args = decodeILAttribData cattr [ for (argty, argval) in Seq.zip cattr.Method.FormalArgTypes parms -> let ty = ImportILType scoref amap m [] argty let obj = evalILAttribElem argval @@ -113,8 +113,8 @@ type AttribInfo = let ty = tyOfExpr g origExpr let obj = evalFSharpAttribArg g evaluatedExpr ty, nm, isField, obj) - | ILAttribInfo (g, amap, scoref, cattr, m) -> - let _parms, namedArgs = decodeILAttribData g.ilg cattr + | ILAttribInfo (_g, amap, scoref, cattr, m) -> + let _parms, namedArgs = decodeILAttribData cattr [ for (nm, argty, isProp, argval) in namedArgs -> let ty = ImportILType scoref amap m [] argty let obj = evalILAttribElem argval @@ -198,7 +198,7 @@ let TryBindMethInfoAttribute g (m: range) (AttribInfo(atref, _) as attribSpec) m ignore f3 #endif BindMethInfoAttributes m minfo - (fun ilAttribs -> TryDecodeILAttribute g atref ilAttribs |> Option.bind f1) + (fun ilAttribs -> TryDecodeILAttribute atref ilAttribs |> Option.bind f1) (fun fsAttribs -> TryFindFSharpAttribute g attribSpec fsAttribs |> Option.bind f2) #if !NO_EXTENSIONTYPING (fun provAttribs -> @@ -230,7 +230,7 @@ let MethInfoHasAttribute g m attribSpec minfo = /// Check IL attributes for 'ObsoleteAttribute', returning errors and warnings as data let private CheckILAttributes (g: TcGlobals) isByrefLikeTyconRef cattrs m = let (AttribInfo(tref,_)) = g.attrib_SystemObsolete - match TryDecodeILAttribute g tref cattrs with + match TryDecodeILAttribute tref cattrs with | Some ([ILAttribElem.String (Some msg) ], _) when not isByrefLikeTyconRef -> WarnD(ObsoleteWarning(msg, m)) | Some ([ILAttribElem.String (Some msg); ILAttribElem.Bool isError ], _) when not isByrefLikeTyconRef -> @@ -329,7 +329,7 @@ let private CheckProvidedAttributes (g: TcGlobals) m (provAttribs: Tainted let inherited = match List.tryPick (function ("Inherited", _, _, ILAttribElem.Bool res) -> Some res | _ -> None) named with diff --git a/src/fsharp/CompilerConfig.fs b/src/fsharp/CompilerConfig.fs index 7617b082bd2..2417eae3dd6 100644 --- a/src/fsharp/CompilerConfig.fs +++ b/src/fsharp/CompilerConfig.fs @@ -148,10 +148,10 @@ type VersionFlag = /// reference backed by information generated by the the compiler service. type IRawFSharpAssemblyData = /// The raw list AutoOpenAttribute attributes in the assembly - abstract GetAutoOpenAttributes: ILGlobals -> string list + abstract GetAutoOpenAttributes: unit -> string list /// The raw list InternalsVisibleToAttribute attributes in the assembly - abstract GetInternalsVisibleToAttributes: ILGlobals -> string list + abstract GetInternalsVisibleToAttributes: unit -> string list /// The raw IL module definition in the assembly, if any. This is not present for cross-project references /// in the language service @@ -175,7 +175,7 @@ type IRawFSharpAssemblyData = abstract HasAnyFSharpSignatureDataAttribute: bool - abstract HasMatchingFSharpSignatureDataAttribute: ILGlobals -> bool + abstract HasMatchingFSharpSignatureDataAttribute: bool /// Cache of time stamps as we traverse a project description type TimeStampCache(defaultTimeStamp: DateTime) = diff --git a/src/fsharp/CompilerConfig.fsi b/src/fsharp/CompilerConfig.fsi index a11a464ad87..1bb1ffb47bb 100644 --- a/src/fsharp/CompilerConfig.fsi +++ b/src/fsharp/CompilerConfig.fsi @@ -28,10 +28,10 @@ exception LoadedSourceNotFoundIgnoring of (*filename*) string * range type IRawFSharpAssemblyData = /// The raw list AutoOpenAttribute attributes in the assembly - abstract GetAutoOpenAttributes: ILGlobals -> string list + abstract GetAutoOpenAttributes: unit -> string list /// The raw list InternalsVisibleToAttribute attributes in the assembly - abstract GetInternalsVisibleToAttributes: ILGlobals -> string list + abstract GetInternalsVisibleToAttributes: unit -> string list /// The raw IL module definition in the assembly, if any. This is not present for cross-project references /// in the language service @@ -39,7 +39,7 @@ type IRawFSharpAssemblyData = abstract HasAnyFSharpSignatureDataAttribute: bool - abstract HasMatchingFSharpSignatureDataAttribute: ILGlobals -> bool + abstract HasMatchingFSharpSignatureDataAttribute: bool /// The raw F# signature data in the assembly, if any abstract GetRawFSharpSignatureData: range * ilShortAssemName: string * fileName: string -> (string * (unit -> ReadOnlyByteMemory)) list diff --git a/src/fsharp/CompilerImports.fs b/src/fsharp/CompilerImports.fs index 9dac4466b29..6c0e2b0222a 100644 --- a/src/fsharp/CompilerImports.fs +++ b/src/fsharp/CompilerImports.fs @@ -661,19 +661,19 @@ let MakeScopeRefForILModule (ilModule: ILModuleDef) = let GetCustomAttributesOfILModule (ilModule: ILModuleDef) = (match ilModule.Manifest with Some m -> m.CustomAttrs | None -> ilModule.CustomAttrs).AsList -let GetAutoOpenAttributes ilg ilModule = - ilModule |> GetCustomAttributesOfILModule |> List.choose (TryFindAutoOpenAttr ilg) +let GetAutoOpenAttributes ilModule = + ilModule |> GetCustomAttributesOfILModule |> List.choose TryFindAutoOpenAttr -let GetInternalsVisibleToAttributes ilg ilModule = - ilModule |> GetCustomAttributesOfILModule |> List.choose (TryFindInternalsVisibleToAttr ilg) +let GetInternalsVisibleToAttributes ilModule = + ilModule |> GetCustomAttributesOfILModule |> List.choose TryFindInternalsVisibleToAttr type RawFSharpAssemblyDataBackedByFileOnDisk (ilModule: ILModuleDef, ilAssemblyRefs) = let externalSigAndOptData = ["FSharp.Core"] interface IRawFSharpAssemblyData with - member _.GetAutoOpenAttributes ilg = GetAutoOpenAttributes ilg ilModule + member _.GetAutoOpenAttributes() = GetAutoOpenAttributes ilModule - member _.GetInternalsVisibleToAttributes ilg = GetInternalsVisibleToAttributes ilg ilModule + member _.GetInternalsVisibleToAttributes() = GetInternalsVisibleToAttributes ilModule member _.TryGetILModuleDef() = Some ilModule @@ -726,18 +726,18 @@ type RawFSharpAssemblyDataBackedByFileOnDisk (ilModule: ILModuleDef, ilAssemblyR let attrs = GetCustomAttributesOfILModule ilModule List.exists IsSignatureDataVersionAttr attrs - member _.HasMatchingFSharpSignatureDataAttribute ilg = + member _.HasMatchingFSharpSignatureDataAttribute = let attrs = GetCustomAttributesOfILModule ilModule - List.exists (IsMatchingSignatureDataVersionAttr ilg (parseILVersion Internal.Utilities.FSharpEnvironment.FSharpBinaryMetadataFormatRevision)) attrs + List.exists (IsMatchingSignatureDataVersionAttr (parseILVersion Internal.Utilities.FSharpEnvironment.FSharpBinaryMetadataFormatRevision)) attrs [] type RawFSharpAssemblyData (ilModule: ILModuleDef, ilAssemblyRefs) = interface IRawFSharpAssemblyData with - member _.GetAutoOpenAttributes ilg = GetAutoOpenAttributes ilg ilModule + member _.GetAutoOpenAttributes() = GetAutoOpenAttributes ilModule - member _.GetInternalsVisibleToAttributes ilg = GetInternalsVisibleToAttributes ilg ilModule + member _.GetInternalsVisibleToAttributes() = GetInternalsVisibleToAttributes ilModule member _.TryGetILModuleDef() = Some ilModule @@ -767,9 +767,9 @@ type RawFSharpAssemblyData (ilModule: ILModuleDef, ilAssemblyRefs) = let attrs = GetCustomAttributesOfILModule ilModule List.exists IsSignatureDataVersionAttr attrs - member _.HasMatchingFSharpSignatureDataAttribute ilg = + member _.HasMatchingFSharpSignatureDataAttribute = let attrs = GetCustomAttributesOfILModule ilModule - List.exists (IsMatchingSignatureDataVersionAttr ilg (parseILVersion Internal.Utilities.FSharpEnvironment.FSharpBinaryMetadataFormatRevision)) attrs + List.exists (IsMatchingSignatureDataVersionAttr (parseILVersion Internal.Utilities.FSharpEnvironment.FSharpBinaryMetadataFormatRevision)) attrs //---------------------------------------------------------------------------- // TcImports @@ -834,8 +834,7 @@ and TcImportsWeakHack (tcImports: WeakReference) = /// Represents a table of imported assemblies with their resolutions. /// Is a disposable object, but it is recommended not to explicitly call Dispose unless you absolutely know nothing will be using its contents after the disposal. /// Otherwise, simply allow the GC to collect this and it will properly call Dispose from the finalizer. -and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAssemblyResolutions, importsBase: TcImports option, - ilGlobalsOpt, dependencyProviderOpt: DependencyProvider option) +and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAssemblyResolutions, importsBase: TcImports option, dependencyProviderOpt: DependencyProvider option) #if !NO_EXTENSIONTYPING as this #endif @@ -856,7 +855,6 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse let disposeActions = ResizeArray() let mutable disposed = false - let mutable ilGlobalsOpt = ilGlobalsOpt let mutable tcGlobals = None let disposeTypeProviderActions = ResizeArray() #if !NO_EXTENSIONTYPING @@ -1234,10 +1232,6 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse | Some b -> b.GetTcGlobals() | None -> failwith "unreachable: GetGlobals - are the references to mscorlib.dll and FSharp.Core.dll valid?" - member private tcImports.SetILGlobals ilg = - CheckDisposed() - ilGlobalsOpt <- Some ilg - member private tcImports.SetTcGlobals g = CheckDisposed() tcGlobals <- Some g @@ -1305,7 +1299,7 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse // have class which implement ITypeProvider and which have TypeProviderAttribute on them. let designTimeAssemblyNames = runtimeAssemblyAttributes - |> List.choose (TryDecodeTypeProviderAssemblyAttr (defaultArg ilGlobalsOpt EcmaMscorlibILGlobals)) + |> List.choose (TryDecodeTypeProviderAssemblyAttr) // If no design-time assembly is specified, use the runtime assembly |> List.map (function null -> fileNameOfRuntimeAssembly | s -> s) // For each simple name of a design-time assembly, we take the first matching one in the order they are @@ -1463,13 +1457,11 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse let invalidateCcu = new Event<_>() let ccu = Import.ImportILAssembly(tcImports.GetImportMap, m, auxModuleLoader, tcConfig.xmlDocInfoLoader, ilScopeRef, tcConfig.implicitIncludeDir, Some filename, ilModule, invalidateCcu.Publish) - let ilg = defaultArg ilGlobalsOpt EcmaMscorlibILGlobals - let ccuinfo = { FSharpViewOfMetadata=ccu ILScopeRef = ilScopeRef - AssemblyAutoOpenAttributes = GetAutoOpenAttributes ilg ilModule - AssemblyInternalsVisibleToAttributes = GetInternalsVisibleToAttributes ilg ilModule + AssemblyAutoOpenAttributes = GetAutoOpenAttributes ilModule + AssemblyInternalsVisibleToAttributes = GetInternalsVisibleToAttributes ilModule #if !NO_EXTENSIONTYPING IsProviderGenerated = false TypeProviders = [] @@ -1553,12 +1545,10 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse if verbose then dprintf "found optimization data for CCU %s\n" ccuName Some (fixupThunk ())) - let ilg = defaultArg ilGlobalsOpt EcmaMscorlibILGlobals - let ccuinfo = { FSharpViewOfMetadata=ccu - AssemblyAutoOpenAttributes = ilModule.GetAutoOpenAttributes ilg - AssemblyInternalsVisibleToAttributes = ilModule.GetInternalsVisibleToAttributes ilg + AssemblyAutoOpenAttributes = ilModule.GetAutoOpenAttributes() + AssemblyInternalsVisibleToAttributes = ilModule.GetInternalsVisibleToAttributes() FSharpOptimizationData=optdata #if !NO_EXTENSIONTYPING IsProviderGenerated = false @@ -1642,10 +1632,9 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse ILScopeRef = ilScopeRef ILAssemblyRefs = assemblyData.ILAssemblyRefs } tcImports.RegisterDll dllinfo - let ilg = defaultArg ilGlobalsOpt EcmaMscorlibILGlobals let phase2 = if assemblyData.HasAnyFSharpSignatureDataAttribute then - if not (assemblyData.HasMatchingFSharpSignatureDataAttribute ilg) then + if not assemblyData.HasMatchingFSharpSignatureDataAttribute then errorR(Error(FSComp.SR.buildDifferentVersionMustRecompile filename, m)) tcImports.PrepareToImportReferencedILAssembly (ctok, m, filename, dllinfo) else @@ -1777,7 +1766,7 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse let tcResolutions = TcAssemblyResolutions.BuildFromPriorResolutions(ctok, tcConfig, frameworkDLLs, []) let tcAltResolutions = TcAssemblyResolutions.BuildFromPriorResolutions(ctok, tcConfig, nonFrameworkDLLs, []) - let frameworkTcImports = new TcImports(tcConfigP, tcResolutions, None, None, None) + let frameworkTcImports = new TcImports(tcConfigP, tcResolutions, None, None) // Fetch the primaryAssembly from the referenced assemblies otherwise let primaryAssemblyReference = @@ -1869,7 +1858,6 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse sysCcus |> Array.tryFind (fun ccu -> ccuHasType ccu path typeName) let ilGlobals = mkILGlobals (primaryScopeRef, assembliesThatForwardToPrimaryAssembly, fsharpCoreAssemblyScopeRef) - frameworkTcImports.SetILGlobals ilGlobals // OK, now we have both mscorlib.dll and FSharp.Core.dll we can create TcGlobals let tcGlobals = TcGlobals(tcConfig.compilingFslib, ilGlobals, fslibCcu, @@ -1894,14 +1882,14 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse |> List.iter reportAssemblyNotResolved static member BuildNonFrameworkTcImports - (ctok, tcConfigP: TcConfigProvider, tcGlobals: TcGlobals, baseTcImports, + (ctok, tcConfigP: TcConfigProvider, baseTcImports, nonFrameworkReferences, knownUnresolved, dependencyProvider) = cancellable { let tcConfig = tcConfigP.Get ctok let tcResolutions = TcAssemblyResolutions.BuildFromPriorResolutions(ctok, tcConfig, nonFrameworkReferences, knownUnresolved) let references = tcResolutions.GetAssemblyResolutions() - let tcImports = new TcImports(tcConfigP, tcResolutions, Some baseTcImports, Some tcGlobals.ilg, Some dependencyProvider) + let tcImports = new TcImports(tcConfigP, tcResolutions, Some baseTcImports, Some dependencyProvider) let! _assemblies = tcImports.RegisterAndImportReferencedAssemblies(ctok, references) tcImports.ReportUnresolvedAssemblyReferences knownUnresolved return tcImports @@ -1913,7 +1901,7 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse //let foundationalTcImports, tcGlobals = TcImports.BuildFoundationalTcImports tcConfigP let frameworkDLLs, nonFrameworkReferences, knownUnresolved = TcAssemblyResolutions.SplitNonFoundationalResolutions(ctok, tcConfig) let! tcGlobals, frameworkTcImports = TcImports.BuildFrameworkTcImports (ctok, tcConfigP, frameworkDLLs, nonFrameworkReferences) - let! tcImports = TcImports.BuildNonFrameworkTcImports(ctok, tcConfigP, tcGlobals, frameworkTcImports, nonFrameworkReferences, knownUnresolved, dependencyProvider) + let! tcImports = TcImports.BuildNonFrameworkTcImports(ctok, tcConfigP, frameworkTcImports, nonFrameworkReferences, knownUnresolved, dependencyProvider) return tcGlobals, tcImports } diff --git a/src/fsharp/CompilerImports.fsi b/src/fsharp/CompilerImports.fsi index 5f6782057ab..2538857e1fa 100644 --- a/src/fsharp/CompilerImports.fsi +++ b/src/fsharp/CompilerImports.fsi @@ -199,7 +199,6 @@ type TcImports = static member BuildNonFrameworkTcImports: CompilationThreadToken * TcConfigProvider * - TcGlobals * TcImports * AssemblyResolution list * UnresolvedAssemblyReference list * diff --git a/src/fsharp/CreateILModule.fs b/src/fsharp/CreateILModule.fs index 07374a37b30..c08b7d6b813 100644 --- a/src/fsharp/CreateILModule.fs +++ b/src/fsharp/CreateILModule.fs @@ -298,7 +298,7 @@ module MainModuleBuilder = let manifestAttrs = mkILCustomAttrs [ if not tcConfig.internConstantStrings then - yield mkILCustomAttribute tcGlobals.ilg + yield mkILCustomAttribute (tcGlobals.FindSysILTypeRef "System.Runtime.CompilerServices.CompilationRelaxationsAttribute", [tcGlobals.ilg.typ_Int32], [ILAttribElem.Int32( 8)], []) yield! sigDataAttributes diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index ab3f72dfb15..72e742b4312 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -460,7 +460,7 @@ type PtrsOK = let GenReadOnlyAttributeIfNecessary (g: TcGlobals) ty = let add = isInByrefTy g ty && g.attrib_IsReadOnlyAttribute.TyconRef.CanDeref if add then - let attr = mkILCustomAttribute g.ilg (g.attrib_IsReadOnlyAttribute.TypeRef, [], [], []) + let attr = mkILCustomAttribute (g.attrib_IsReadOnlyAttribute.TypeRef, [], [], []) Some attr else None @@ -6841,7 +6841,7 @@ and GenAttr amap g eenv (Attrib(_, k, args, props, _, _, _)) = 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) + mkILCustomAttribMethRef (mspec, ilArgs, props) and GenAttrs cenv eenv attrs = List.map (GenAttr cenv.amap cenv.g eenv) attrs @@ -6865,11 +6865,11 @@ and CreatePermissionSets cenv eenv (securityAttributes: Attrib list) = let tref = tcref.CompiledRepresentationForNamedType let ilattr = GenAttr cenv.amap g eenv attr let _, ilNamedArgs = - match TryDecodeILAttribute g tref (mkILCustomAttrs [ilattr]) with + match TryDecodeILAttribute tref (mkILCustomAttrs [ilattr]) with | Some(ae, na) -> ae, na | _ -> [], [] let setArgs = ilNamedArgs |> List.map (fun (n, ilt, _, ilae) -> (n, ilt, ilae)) - yield IL.mkPermissionSet g.ilg (secaction, [(tref, setArgs)])] + yield IL.mkPermissionSet (secaction, [(tref, setArgs)])] //-------------------------------------------------------------------------- // Generate the set of modules for an assembly, and the declarations in each module @@ -7387,7 +7387,7 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon: Tycon) = | Some memberInfo -> match name, memberInfo.MemberFlags.MemberKind with | ("Item" | "op_IndexedLookup"), (SynMemberKind.PropertyGet | SynMemberKind.PropertySet) when not (isNil (ArgInfosOfPropertyVal g vref.Deref)) -> - Some( mkILCustomAttribute g.ilg (g.FindSysILTypeRef "System.Reflection.DefaultMemberAttribute", [g.ilg.typ_String], [ILAttribElem.String(Some name)], []) ) + Some( mkILCustomAttribute (g.FindSysILTypeRef "System.Reflection.DefaultMemberAttribute", [g.ilg.typ_String], [ILAttribElem.String(Some name)], []) ) | _ -> None) |> Option.toList diff --git a/src/fsharp/ParseHelpers.fs b/src/fsharp/ParseHelpers.fs index 3bcfe0938d6..35a10a0b1f9 100644 --- a/src/fsharp/ParseHelpers.fs +++ b/src/fsharp/ParseHelpers.fs @@ -242,7 +242,7 @@ let ParseAssemblyCodeType s reportLibraryOnlyFeatures (isFeatureSupported: Featu #if NO_INLINE_IL_PARSER errorR(Error((193, "Inline IL not valid in a hosted environment"), m)) - IL.EcmaMscorlibILGlobals.typ_Object + IL.PrimaryAssemblyILGlobals.typ_Object #else let isFeatureSupported (_featureId:LanguageFeature) = true try @@ -251,6 +251,6 @@ let ParseAssemblyCodeType s reportLibraryOnlyFeatures (isFeatureSupported: Featu (UnicodeLexing.StringAsLexbuf(reportLibraryOnlyFeatures, isFeatureSupported, s)) with RecoverableParseError -> errorR(Error(FSComp.SR.astParseEmbeddedILTypeError(), m)); - IL.EcmaMscorlibILGlobals.typ_Object + IL.PrimaryAssemblyILGlobals.typ_Object #endif diff --git a/src/fsharp/StaticLinking.fs b/src/fsharp/StaticLinking.fs index ebeb18469cc..01d04f49936 100644 --- a/src/fsharp/StaticLinking.fs +++ b/src/fsharp/StaticLinking.fs @@ -191,7 +191,7 @@ let StaticLinkILModules (tcConfig:TcConfig, ilGlobals, tcImports, ilxMainModule, TypeDefs = mkILTypeDefs (topTypeDef :: List.concat normalTypeDefs) Resources = mkILResources (savedResources @ ilxMainModule.Resources.AsList) NativeResources = savedNativeResources } - Morphs.morphILTypeRefsInILModuleMemoized ilGlobals typeForwarding.TypeForwardILTypeRef main + Morphs.morphILTypeRefsInILModuleMemoized typeForwarding.TypeForwardILTypeRef main ilxMainModule, rewriteExternalRefsToLocalRefs @@ -379,7 +379,7 @@ let StaticLink (ctok, tcConfig: TcConfig, tcImports: TcImports, ilGlobals: ILGlo yield (ILTypeRef.Create(ILScopeRef.Local, k.Enclosing, k.Name), v) ] let ilModule = - ilModule |> Morphs.morphILTypeRefsInILModuleMemoized ilGlobals (fun tref -> + ilModule |> Morphs.morphILTypeRefsInILModuleMemoized (fun tref -> if debugStaticLinking then printfn "deciding whether to rewrite type ref %A" tref.QualifiedName let ok, v = ilAssemStaticLinkMap.TryGetValue tref if ok then @@ -512,6 +512,6 @@ let StaticLink (ctok, tcConfig: TcConfig, tcImports: TcImports, ilGlobals: ILGlo error (Error(FSComp.SR.fscStaticLinkingNoProfileMismatches(), rangeCmdArgs)) scopeRef let rewriteAssemblyRefsToMatchLibraries = NormalizeAssemblyRefs (ctok, ilGlobals, tcImports) - Morphs.morphILTypeRefsInILModuleMemoized ilGlobals (Morphs.morphILScopeRefsInILTypeRef (validateTargetPlatform >> rewriteExternalRefsToLocalRefs >> rewriteAssemblyRefsToMatchLibraries)) ilxMainModule + Morphs.morphILTypeRefsInILModuleMemoized (Morphs.morphILScopeRefsInILTypeRef (validateTargetPlatform >> rewriteExternalRefsToLocalRefs >> rewriteAssemblyRefsToMatchLibraries)) ilxMainModule ilxMainModule) diff --git a/src/fsharp/TcGlobals.fs b/src/fsharp/TcGlobals.fs index 9d03fc448f7..3cb9441cb4d 100755 --- a/src/fsharp/TcGlobals.fs +++ b/src/fsharp/TcGlobals.fs @@ -761,8 +761,8 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d let mutable generatedAttribsCache = [] let mutable debuggerBrowsableNeverAttributeCache = None - let mkDebuggerNonUserCodeAttribute() = mkILCustomAttribute ilg (findSysILTypeRef tname_DebuggerNonUserCodeAttribute, [], [], []) - let mkCompilerGeneratedAttribute () = mkILCustomAttribute ilg (tref_CompilerGeneratedAttribute, [], [], []) + let mkDebuggerNonUserCodeAttribute() = mkILCustomAttribute (findSysILTypeRef tname_DebuggerNonUserCodeAttribute, [], [], []) + let mkCompilerGeneratedAttribute () = mkILCustomAttribute (tref_CompilerGeneratedAttribute, [], [], []) let compilerGlobalState = CompilerGlobalState() // Requests attributes to be added to compiler generated methods. @@ -786,7 +786,7 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d let typ_DebuggerBrowsableState = let tref = findSysILTypeRef tname_DebuggerBrowsableState ILType.Value (mkILNonGenericTySpec tref) - mkILCustomAttribute ilg (findSysILTypeRef tname_DebuggerBrowsableAttribute, [typ_DebuggerBrowsableState], [ILAttribElem.Int32 n], []) + mkILCustomAttribute (findSysILTypeRef tname_DebuggerBrowsableAttribute, [typ_DebuggerBrowsableState], [ILAttribElem.Int32 n], []) let mkDebuggerBrowsableNeverAttribute() = match debuggerBrowsableNeverAttributeCache with @@ -799,7 +799,7 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d let addNeverAttrs (attrs: ILAttributes) = mkILCustomAttrs (attrs.AsList @ [mkDebuggerBrowsableNeverAttribute()]) let addPropertyNeverAttrs (pdef:ILPropertyDef) = pdef.With(customAttrs = addNeverAttrs pdef.CustomAttrs) let addFieldNeverAttrs (fdef:ILFieldDef) = fdef.With(customAttrs = addNeverAttrs fdef.CustomAttrs) - let mkDebuggerTypeProxyAttribute (ty : ILType) = mkILCustomAttribute ilg (findSysILTypeRef tname_DebuggerTypeProxyAttribute, [ilg.typ_Type], [ILAttribElem.TypeRef (Some ty.TypeRef)], []) + let mkDebuggerTypeProxyAttribute (ty : ILType) = mkILCustomAttribute (findSysILTypeRef tname_DebuggerTypeProxyAttribute, [ilg.typ_Type], [ILAttribElem.TypeRef (Some ty.TypeRef)], []) let betterTyconEntries = [| "Int32" , v_int_tcr @@ -1529,17 +1529,17 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d member _.AddFieldNeverAttrs mdef = addFieldNeverAttrs mdef - member _.mkDebuggerHiddenAttribute() = mkILCustomAttribute ilg (findSysILTypeRef tname_DebuggerHiddenAttribute, [], [], []) + member _.mkDebuggerHiddenAttribute() = mkILCustomAttribute (findSysILTypeRef tname_DebuggerHiddenAttribute, [], [], []) - member _.mkDebuggerDisplayAttribute s = mkILCustomAttribute ilg (findSysILTypeRef tname_DebuggerDisplayAttribute, [ilg.typ_String], [ILAttribElem.String (Some s)], []) + member _.mkDebuggerDisplayAttribute s = mkILCustomAttribute (findSysILTypeRef tname_DebuggerDisplayAttribute, [ilg.typ_String], [ILAttribElem.String (Some s)], []) member _.DebuggerBrowsableNeverAttribute = mkDebuggerBrowsableNeverAttribute() member _.mkDebuggerStepThroughAttribute() = - mkILCustomAttribute ilg (findSysILTypeRef tname_DebuggerStepThroughAttribute, [], [], []) + mkILCustomAttribute (findSysILTypeRef tname_DebuggerStepThroughAttribute, [], [], []) member _.mkDebuggableAttribute (jitOptimizerDisabled) = - mkILCustomAttribute ilg (tref_DebuggableAttribute, [ilg.typ_Bool; ilg.typ_Bool], [ILAttribElem.Bool false; ILAttribElem.Bool jitOptimizerDisabled], []) + mkILCustomAttribute (tref_DebuggableAttribute, [ilg.typ_Bool; ilg.typ_Bool], [ILAttribElem.Bool false; ILAttribElem.Bool jitOptimizerDisabled], []) member _.mkDebuggableAttributeV2(jitTracking, ignoreSymbolStoreSequencePoints, jitOptimizerDisabled, enableEnC) = let debuggingMode = @@ -1548,7 +1548,7 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d (if ignoreSymbolStoreSequencePoints then 2 else 0) ||| (if enableEnC then 4 else 0) let tref_DebuggableAttribute_DebuggingModes = mkILTyRefInTyRef (tref_DebuggableAttribute, tname_DebuggableAttribute_DebuggingModes) - mkILCustomAttribute ilg + mkILCustomAttribute (tref_DebuggableAttribute, [mkILNonGenericValueTy tref_DebuggableAttribute_DebuggingModes], (* See System.Diagnostics.DebuggableAttribute.DebuggingModes *) [ILAttribElem.Int32( debuggingMode )], []) diff --git a/src/fsharp/TypedTreeOps.fs b/src/fsharp/TypedTreeOps.fs index 3f6d2f3d327..b7bd07a1835 100644 --- a/src/fsharp/TypedTreeOps.fs +++ b/src/fsharp/TypedTreeOps.fs @@ -3051,8 +3051,8 @@ let isILAttrib (tref: ILTypeRef) (attr: ILAttribute) = let HasILAttribute tref (attrs: ILAttributes) = attrs.AsArray |> Array.exists (isILAttrib tref) -let TryDecodeILAttribute (g: TcGlobals) tref (attrs: ILAttributes) = - attrs.AsArray |> Array.tryPick (fun x -> if isILAttrib tref x then Some(decodeILAttribData g.ilg x) else None) +let TryDecodeILAttribute tref (attrs: ILAttributes) = + attrs.AsArray |> Array.tryPick (fun x -> if isILAttrib tref x then Some(decodeILAttribData x) else None) // F# view of attributes (these get converted to AbsIL attributes in ilxgen) let IsMatchingFSharpAttribute g (AttribInfo(_, tcref)) (Attrib(tcref2, _, _, _, _, _, _)) = tyconRefEq g tcref tcref2 @@ -3114,7 +3114,7 @@ let TryBindTyconRefAttribute g (m: range) (AttribInfo (atref, _) as args) (tcref | None -> None #endif | ILTypeMetadata (TILObjectReprData(_, _, tdef)) -> - match TryDecodeILAttribute g atref tdef.CustomAttrs with + match TryDecodeILAttribute atref tdef.CustomAttrs with | Some attr -> f1 attr | _ -> None | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> @@ -7339,7 +7339,7 @@ let tref_CompilationSourceNameAttr (g: TcGlobals) = mkILTyRef (g.fslibCcu.ILScop let tref_SourceConstructFlags (g: TcGlobals) = mkILTyRef (g.fslibCcu.ILScopeRef, tnameSourceConstructFlags) let mkCompilationMappingAttrPrim (g: TcGlobals) k nums = - mkILCustomAttribute g.ilg (tref_CompilationMappingAttr g, + mkILCustomAttribute (tref_CompilationMappingAttr g, ((mkILNonGenericValueTy (tref_SourceConstructFlags g)) :: (nums |> List.map (fun _ -> g.ilg.typ_Int32))), ((k :: nums) |> List.map (fun n -> ILAttribElem.Int32 n)), []) @@ -7351,17 +7351,17 @@ let mkCompilationMappingAttrWithSeqNum g kind seqNum = mkCompilationMappingAttrP let mkCompilationMappingAttrWithVariantNumAndSeqNum g kind varNum seqNum = mkCompilationMappingAttrPrim g kind [varNum;seqNum] let mkCompilationArgumentCountsAttr (g: TcGlobals) nums = - mkILCustomAttribute g.ilg (tref_CompilationArgumentCountsAttr g, [ mkILArr1DTy g.ilg.typ_Int32 ], + mkILCustomAttribute (tref_CompilationArgumentCountsAttr g, [ mkILArr1DTy g.ilg.typ_Int32 ], [ILAttribElem.Array (g.ilg.typ_Int32, List.map (fun n -> ILAttribElem.Int32 n) nums)], []) let mkCompilationSourceNameAttr (g: TcGlobals) n = - mkILCustomAttribute g.ilg (tref_CompilationSourceNameAttr g, [ g.ilg.typ_String ], + mkILCustomAttribute (tref_CompilationSourceNameAttr g, [ g.ilg.typ_String ], [ILAttribElem.String(Some n)], []) let mkCompilationMappingAttrForQuotationResource (g: TcGlobals) (nm, tys: ILTypeRef list) = - mkILCustomAttribute g.ilg (tref_CompilationMappingAttr g, + mkILCustomAttribute (tref_CompilationMappingAttr g, [ g.ilg.typ_String; mkILArr1DTy g.ilg.typ_Type ], [ ILAttribElem.String (Some nm); ILAttribElem.Array (g.ilg.typ_Type, [ for ty in tys -> ILAttribElem.TypeRef (Some ty) ]) ], []) @@ -7375,9 +7375,9 @@ let mkCompilationMappingAttrForQuotationResource (g: TcGlobals) (nm, tys: ILType let isTypeProviderAssemblyAttr (cattr: ILAttribute) = cattr.Method.DeclaringType.BasicQualifiedName = typeof.FullName -let TryDecodeTypeProviderAssemblyAttr ilg (cattr: ILAttribute) = +let TryDecodeTypeProviderAssemblyAttr (cattr: ILAttribute) = if isTypeProviderAssemblyAttr cattr then - let parms, _args = decodeILAttribData ilg cattr + let parms, _args = decodeILAttribData cattr match parms with // The first parameter to the attribute is the name of the assembly with the compiler extensions. | (ILAttribElem.String (Some assemblyName)) :: _ -> Some assemblyName | (ILAttribElem.String None) :: _ -> Some null @@ -7399,7 +7399,7 @@ let tnames_SignatureDataVersionAttr = splitILTypeName tname_SignatureDataVersion let tref_SignatureDataVersionAttr fsharpCoreAssemblyScopeRef = mkILTyRef(fsharpCoreAssemblyScopeRef, tname_SignatureDataVersionAttr) let mkSignatureDataVersionAttr (g: TcGlobals) (version: ILVersionInfo) = - mkILCustomAttribute g.ilg + mkILCustomAttribute (tref_SignatureDataVersionAttr g.ilg.fsharpCoreAssemblyScopeRef, [g.ilg.typ_Int32;g.ilg.typ_Int32;g.ilg.typ_Int32], [ILAttribElem.Int32 (int32 version.Major) @@ -7410,9 +7410,9 @@ let tname_AutoOpenAttr = FSharpLib.Core + ".AutoOpenAttribute" let IsSignatureDataVersionAttr cattr = isILAttribByName ([], tname_SignatureDataVersionAttr) cattr -let TryFindAutoOpenAttr (ilg: IL.ILGlobals) cattr = +let TryFindAutoOpenAttr cattr = if isILAttribByName ([], tname_AutoOpenAttr) cattr then - match decodeILAttribData ilg cattr with + match decodeILAttribData cattr with | [ILAttribElem.String s], _ -> s | [], _ -> None | _ -> @@ -7423,9 +7423,9 @@ let TryFindAutoOpenAttr (ilg: IL.ILGlobals) cattr = let tname_InternalsVisibleToAttr = "System.Runtime.CompilerServices.InternalsVisibleToAttribute" -let TryFindInternalsVisibleToAttr ilg cattr = +let TryFindInternalsVisibleToAttr cattr = if isILAttribByName ([], tname_InternalsVisibleToAttr) cattr then - match decodeILAttribData ilg cattr with + match decodeILAttribData cattr with | [ILAttribElem.String s], _ -> s | [], _ -> None | _ -> @@ -7434,9 +7434,9 @@ let TryFindInternalsVisibleToAttr ilg cattr = else None -let IsMatchingSignatureDataVersionAttr ilg (version: ILVersionInfo) cattr = +let IsMatchingSignatureDataVersionAttr (version: ILVersionInfo) cattr = IsSignatureDataVersionAttr cattr && - match decodeILAttribData ilg cattr with + match decodeILAttribData cattr with | [ILAttribElem.Int32 u1; ILAttribElem.Int32 u2;ILAttribElem.Int32 u3 ], _ -> (version.Major = uint16 u1) && (version.Minor = uint16 u2) && (version.Build = uint16 u3) | _ -> @@ -7444,7 +7444,7 @@ let IsMatchingSignatureDataVersionAttr ilg (version: ILVersionInfo) cattr = false let mkCompilerGeneratedAttr (g: TcGlobals) n = - mkILCustomAttribute g.ilg (tref_CompilationMappingAttr g, [mkILNonGenericValueTy (tref_SourceConstructFlags g)], [ILAttribElem.Int32 n], []) + mkILCustomAttribute (tref_CompilationMappingAttr g, [mkILNonGenericValueTy (tref_SourceConstructFlags g)], [ILAttribElem.Int32 n], []) //-------------------------------------------------------------------------- // tupled lambda --> method/function with a given topValInfo specification. diff --git a/src/fsharp/TypedTreeOps.fsi b/src/fsharp/TypedTreeOps.fsi index 02f2e607458..ba1e9e7482b 100755 --- a/src/fsharp/TypedTreeOps.fsi +++ b/src/fsharp/TypedTreeOps.fsi @@ -2085,7 +2085,7 @@ val mkLdelem: TcGlobals -> range -> TType -> Expr -> Expr -> Expr // Analyze attribute sets //------------------------------------------------------------------------- -val TryDecodeILAttribute: TcGlobals -> ILTypeRef -> ILAttributes -> (ILAttribElem list * ILAttributeNamedArg list) option +val TryDecodeILAttribute: ILTypeRef -> ILAttributes -> (ILAttribElem list * ILAttributeNamedArg list) option val TryFindILAttribute: BuiltinAttribInfo -> ILAttributes -> bool @@ -2127,16 +2127,16 @@ val TryFindAttributeUsageAttribute: TcGlobals -> range -> TyconRef -> bool optio #if !NO_EXTENSIONTYPING /// returns Some(assemblyName) for success -val TryDecodeTypeProviderAssemblyAttr: ILGlobals -> ILAttribute -> string option +val TryDecodeTypeProviderAssemblyAttr: ILAttribute -> string option #endif val IsSignatureDataVersionAttr: ILAttribute -> bool -val TryFindAutoOpenAttr: IL.ILGlobals -> ILAttribute -> string option +val TryFindAutoOpenAttr: ILAttribute -> string option -val TryFindInternalsVisibleToAttr: IL.ILGlobals -> ILAttribute -> string option +val TryFindInternalsVisibleToAttr: ILAttribute -> string option -val IsMatchingSignatureDataVersionAttr: IL.ILGlobals -> ILVersionInfo -> ILAttribute -> bool +val IsMatchingSignatureDataVersionAttr: ILVersionInfo -> ILAttribute -> bool val mkCompilationMappingAttr: TcGlobals -> int -> ILAttribute val mkCompilationMappingAttrWithSeqNum: TcGlobals -> int -> int -> ILAttribute diff --git a/src/fsharp/absil/il.fs b/src/fsharp/absil/il.fs index da31dd9d2c8..2130c33b0f6 100644 --- a/src/fsharp/absil/il.fs +++ b/src/fsharp/absil/il.fs @@ -3658,32 +3658,85 @@ let rec encodeCustomAttrElemTypeForObject x = | ILAttribElem.Double _ -> [| et_R8 |] | ILAttribElem.Array (elemTy, _) -> [| yield et_SZARRAY; yield! encodeCustomAttrElemType elemTy |] -let rec decodeCustomAttrElemType (ilg: ILGlobals) bytes sigptr x = +let tspan = TimeSpan (DateTime.UtcNow.Ticks - DateTime(2000, 1, 1).Ticks) + +let parseILVersion (vstr : string) = + // matches "v1.2.3.4" or "1.2.3.4". Note, if numbers are missing, returns -1 (not 0). + let mutable vstr = vstr.TrimStart [|'v'|] + // if the version string contains wildcards, replace them + let versionComponents = vstr.Split ([|'.'|]) + + // account for wildcards + if versionComponents.Length > 2 then + let defaultBuild = uint16 tspan.Days % UInt16.MaxValue - 1us + let defaultRevision = uint16 (DateTime.UtcNow.TimeOfDay.TotalSeconds / 2.0) % UInt16.MaxValue - 1us + if versionComponents.[2] = "*" then + if versionComponents.Length > 3 then + failwith "Invalid version format" + else + // set the build number to the number of days since Jan 1, 2000 + versionComponents.[2] <- defaultBuild.ToString() + // Set the revision number to number of seconds today / 2 + vstr <- String.Join (".", versionComponents) + "." + defaultRevision.ToString() + elif versionComponents.Length > 3 && versionComponents.[3] = "*" then + // Set the revision number to number of seconds today / 2 + versionComponents.[3] <- defaultRevision.ToString() + vstr <- String.Join (".", versionComponents) + + let version = System.Version vstr + let zero32 n = if n < 0 then 0us else uint16 n + // since the minor revision will be -1 if none is specified, we need to truncate to 0 to not break existing code + let minorRevision = if version.Revision = -1 then 0us else uint16 version.MinorRevision + ILVersionInfo (zero32 version.Major, zero32 version.Minor, zero32 version.Build, minorRevision) + +let compareILVersions (version1 : ILVersionInfo) (version2 : ILVersionInfo) = + let c = compare version1.Major version2.Major + if c <> 0 then c else + let c = compare version1.Minor version2.Minor + if c <> 0 then c else + let c = compare version1.Build version2.Build + if c <> 0 then c else + let c = compare version1.Revision version2.Revision + if c <> 0 then c else + 0 + +let DummyFSharpCoreScopeRef = + let asmRef = + // The exact public key token and version used here don't actually matter, or shouldn't. + ILAssemblyRef.Create("FSharp.Core", None, + Some (PublicKeyToken(Bytes.ofInt32Array [| 0xb0; 0x3f; 0x5f; 0x7f; 0x11; 0xd5; 0x0a; 0x3a |])), + false, + Some (parseILVersion "0.0.0.0"), None) + ILScopeRef.Assembly asmRef + +let PrimaryAssemblyILGlobals = mkILGlobals (ILScopeRef.PrimaryAssembly, [], DummyFSharpCoreScopeRef) + +let rec decodeCustomAttrElemType bytes sigptr x = match x with - | x when x = et_I1 -> ilg.typ_SByte, sigptr - | x when x = et_U1 -> ilg.typ_Byte, sigptr - | x when x = et_I2 -> ilg.typ_Int16, sigptr - | x when x = et_U2 -> ilg.typ_UInt16, sigptr - | x when x = et_I4 -> ilg.typ_Int32, sigptr - | x when x = et_U4 -> ilg.typ_UInt32, sigptr - | x when x = et_I8 -> ilg.typ_Int64, sigptr - | x when x = et_U8 -> ilg.typ_UInt64, sigptr - | x when x = et_R8 -> ilg.typ_Double, sigptr - | x when x = et_R4 -> ilg.typ_Single, sigptr - | x when x = et_CHAR -> ilg.typ_Char, sigptr - | x when x = et_BOOLEAN -> ilg.typ_Bool, sigptr - | x when x = et_STRING -> ilg.typ_String, sigptr - | x when x = et_OBJECT -> ilg.typ_Object, sigptr + | x when x = et_I1 -> PrimaryAssemblyILGlobals.typ_SByte, sigptr + | x when x = et_U1 -> PrimaryAssemblyILGlobals.typ_Byte, sigptr + | x when x = et_I2 -> PrimaryAssemblyILGlobals.typ_Int16, sigptr + | x when x = et_U2 -> PrimaryAssemblyILGlobals.typ_UInt16, sigptr + | x when x = et_I4 -> PrimaryAssemblyILGlobals.typ_Int32, sigptr + | x when x = et_U4 -> PrimaryAssemblyILGlobals.typ_UInt32, sigptr + | x when x = et_I8 -> PrimaryAssemblyILGlobals.typ_Int64, sigptr + | x when x = et_U8 -> PrimaryAssemblyILGlobals.typ_UInt64, sigptr + | x when x = et_R8 -> PrimaryAssemblyILGlobals.typ_Double, sigptr + | x when x = et_R4 -> PrimaryAssemblyILGlobals.typ_Single, sigptr + | x when x = et_CHAR -> PrimaryAssemblyILGlobals.typ_Char, sigptr + | x when x = et_BOOLEAN -> PrimaryAssemblyILGlobals.typ_Bool, sigptr + | x when x = et_STRING -> PrimaryAssemblyILGlobals.typ_String, sigptr + | x when x = et_OBJECT -> PrimaryAssemblyILGlobals.typ_Object, sigptr | x when x = et_SZARRAY -> let et, sigptr = sigptr_get_u8 bytes sigptr - let elemTy, sigptr = decodeCustomAttrElemType ilg bytes sigptr et + let elemTy, sigptr = decodeCustomAttrElemType bytes sigptr et mkILArr1DTy elemTy, sigptr - | x when x = 0x50uy -> ilg.typ_Type, sigptr + | x when x = 0x50uy -> PrimaryAssemblyILGlobals.typ_Type, sigptr | _ -> failwithf "decodeCustomAttrElemType ilg: unrecognized custom element type: %A" x /// Given a custom attribute element, encode it to a binary representation according to the rules in Ecma 335 Partition II. -let rec encodeCustomAttrPrimValue ilg c = +let rec encodeCustomAttrPrimValue c = match c with | ILAttribElem.Bool b -> [| (if b then 0x01uy else 0x00uy) |] | ILAttribElem.String None @@ -3705,49 +3758,49 @@ let rec encodeCustomAttrPrimValue ilg c = | ILAttribElem.Type (Some ty) -> encodeCustomAttrString ty.QualifiedName | ILAttribElem.TypeRef (Some tref) -> encodeCustomAttrString tref.QualifiedName | ILAttribElem.Array (_, elems) -> - [| yield! i32AsBytes elems.Length; for elem in elems do yield! encodeCustomAttrPrimValue ilg elem |] + [| yield! i32AsBytes elems.Length; for elem in elems do yield! encodeCustomAttrPrimValue elem |] -and encodeCustomAttrValue ilg ty c = +and encodeCustomAttrValue ty c = match ty, c with | ILType.Boxed tspec, _ when tspec.Name = tname_Object -> - [| yield! encodeCustomAttrElemTypeForObject c; yield! encodeCustomAttrPrimValue ilg c |] + [| yield! encodeCustomAttrElemTypeForObject c; yield! encodeCustomAttrPrimValue c |] | ILType.Array (shape, _), ILAttribElem.Null when shape = ILArrayShape.SingleDimensional -> [| yield! i32AsBytes 0xFFFFFFFF |] | ILType.Array (shape, elemType), ILAttribElem.Array (_, elems) when shape = ILArrayShape.SingleDimensional -> - [| yield! i32AsBytes elems.Length; for elem in elems do yield! encodeCustomAttrValue ilg elemType elem |] + [| yield! i32AsBytes elems.Length; for elem in elems do yield! encodeCustomAttrValue elemType elem |] | _ -> - encodeCustomAttrPrimValue ilg c + encodeCustomAttrPrimValue c -let encodeCustomAttrNamedArg ilg (nm, ty, prop, elem) = +let encodeCustomAttrNamedArg (nm, ty, prop, elem) = [| yield (if prop then 0x54uy else 0x53uy) yield! encodeCustomAttrElemType ty yield! encodeCustomAttrString nm - yield! encodeCustomAttrValue ilg ty elem |] + yield! encodeCustomAttrValue ty elem |] -let encodeCustomAttrArgs (ilg: ILGlobals) (mspec: ILMethodSpec) (fixedArgs: list<_>) (namedArgs: list<_>) = +let encodeCustomAttrArgs (mspec: ILMethodSpec) (fixedArgs: list<_>) (namedArgs: list<_>) = let argtys = mspec.MethodRef.ArgTypes [| yield! [| 0x01uy; 0x00uy; |] for (argty, fixedArg) in Seq.zip argtys fixedArgs do - yield! encodeCustomAttrValue ilg argty fixedArg + yield! encodeCustomAttrValue argty fixedArg yield! u16AsBytes (uint16 namedArgs.Length) for namedArg in namedArgs do - yield! encodeCustomAttrNamedArg ilg namedArg |] + yield! encodeCustomAttrNamedArg namedArg |] -let encodeCustomAttr (ilg: ILGlobals) (mspec: ILMethodSpec, fixedArgs: list<_>, namedArgs: list<_>) = - let args = encodeCustomAttrArgs ilg mspec fixedArgs namedArgs +let encodeCustomAttr (mspec: ILMethodSpec, fixedArgs: list<_>, namedArgs: list<_>) = + let args = encodeCustomAttrArgs mspec fixedArgs namedArgs ILAttribute.Encoded (mspec, args, fixedArgs @ (namedArgs |> List.map (fun (_, _, _, e) -> e))) -let mkILCustomAttribMethRef (ilg: ILGlobals) (mspec: ILMethodSpec, fixedArgs: list<_>, namedArgs: list<_>) = - encodeCustomAttr ilg (mspec, fixedArgs, namedArgs) +let mkILCustomAttribMethRef (mspec: ILMethodSpec, fixedArgs: list<_>, namedArgs: list<_>) = + encodeCustomAttr (mspec, fixedArgs, namedArgs) -let mkILCustomAttribute ilg (tref, argtys, argvs, propvs) = - encodeCustomAttr ilg (mkILNonGenericCtorMethSpec (tref, argtys), argvs, propvs) +let mkILCustomAttribute (tref, argtys, argvs, propvs) = + encodeCustomAttr (mkILNonGenericCtorMethSpec (tref, argtys), argvs, propvs) -let getCustomAttrData (ilg: ILGlobals) cattr = +let getCustomAttrData cattr = match cattr with | ILAttribute.Encoded (_, data, _) -> data | ILAttribute.Decoded (mspec, fixedArgs, namedArgs) -> - encodeCustomAttrArgs ilg mspec fixedArgs namedArgs + encodeCustomAttrArgs mspec fixedArgs namedArgs // ILSecurityDecl is a 'blob' having the following format: // - A byte containing a period (.). @@ -3757,7 +3810,7 @@ let getCustomAttrData (ilg: ILGlobals) cattr = // as a compressed int to indicate the size followed by an array of UTF8 characters.) // - A set of properties, encoded as the named arguments to a custom attribute would be (as // in §23.3, beginning with NumNamed). -let mkPermissionSet (ilg: ILGlobals) (action, attributes: list<(ILTypeRef * (string * ILType * ILAttribElem) list)>) = +let mkPermissionSet (action, attributes: list<(ILTypeRef * (string * ILType * ILAttribElem) list)>) = let bytes = [| yield (byte '.') yield! z_unsigned_int attributes.Length @@ -3766,7 +3819,7 @@ let mkPermissionSet (ilg: ILGlobals) (action, attributes: list<(ILTypeRef * (str let bytes = [| yield! z_unsigned_int props.Length for (nm, ty, value) in props do - yield! encodeCustomAttrNamedArg ilg (nm, ty, true, value)|] + yield! encodeCustomAttrNamedArg (nm, ty, true, value)|] yield! z_unsigned_int bytes.Length yield! bytes |] @@ -3910,7 +3963,7 @@ type ILTypeSigParser (tstring : string) = let ilty = x.ParseType() ILAttribElem.Type (Some ilty) -let decodeILAttribData (ilg: ILGlobals) (ca: ILAttribute) = +let decodeILAttribData (ca: ILAttribute) = match ca with | ILAttribute.Decoded (_, fixedArgs, namedArgs) -> fixedArgs, namedArgs | ILAttribute.Encoded (_, bytes, _) -> @@ -3976,7 +4029,7 @@ let decodeILAttribData (ilg: ILGlobals) (ca: ILAttribute) = if et = 0xFFuy then ILAttribElem.Null, sigptr else - let ty, sigptr = decodeCustomAttrElemType ilg bytes sigptr et + let ty, sigptr = decodeCustomAttrElemType bytes sigptr et parseVal ty sigptr | ILType.Array (shape, elemTy) when shape = ILArrayShape.SingleDimensional -> let n, sigptr = sigptr_get_i32 bytes sigptr @@ -4018,13 +4071,13 @@ let decodeILAttribData (ilg: ILGlobals) (ca: ILAttribute) = let scoref = match rest with | Some aname -> ILScopeRef.Assembly (ILAssemblyRef.FromAssemblyName (AssemblyName aname)) - | None -> ilg.primaryAssemblyScopeRef + | None -> PrimaryAssemblyILGlobals.primaryAssemblyScopeRef let tref = mkILTyRef (scoref, unqualified_tname) let tspec = mkILNonGenericTySpec tref ILType.Value tspec, sigptr else - decodeCustomAttrElemType ilg bytes sigptr et + decodeCustomAttrElemType bytes sigptr et let nm, sigptr = sigptr_get_serstring bytes sigptr let v, sigptr = parseVal ty sigptr parseNamed ((nm, ty, isProp, v) :: acc) (n-1) sigptr @@ -4268,48 +4321,6 @@ let computeILRefs ilg modul = { AssemblyReferences = Seq.fold (fun acc x -> x :: acc) [] s.refsA ModuleReferences = Seq.fold (fun acc x -> x :: acc) [] s.refsM } -let tspan = TimeSpan (DateTime.UtcNow.Ticks - DateTime(2000, 1, 1).Ticks) - -let parseILVersion (vstr : string) = - // matches "v1.2.3.4" or "1.2.3.4". Note, if numbers are missing, returns -1 (not 0). - let mutable vstr = vstr.TrimStart [|'v'|] - // if the version string contains wildcards, replace them - let versionComponents = vstr.Split ([|'.'|]) - - // account for wildcards - if versionComponents.Length > 2 then - let defaultBuild = uint16 tspan.Days % UInt16.MaxValue - 1us - let defaultRevision = uint16 (DateTime.UtcNow.TimeOfDay.TotalSeconds / 2.0) % UInt16.MaxValue - 1us - if versionComponents.[2] = "*" then - if versionComponents.Length > 3 then - failwith "Invalid version format" - else - // set the build number to the number of days since Jan 1, 2000 - versionComponents.[2] <- defaultBuild.ToString() - // Set the revision number to number of seconds today / 2 - vstr <- String.Join (".", versionComponents) + "." + defaultRevision.ToString() - elif versionComponents.Length > 3 && versionComponents.[3] = "*" then - // Set the revision number to number of seconds today / 2 - versionComponents.[3] <- defaultRevision.ToString() - vstr <- String.Join (".", versionComponents) - - let version = System.Version vstr - let zero32 n = if n < 0 then 0us else uint16 n - // since the minor revision will be -1 if none is specified, we need to truncate to 0 to not break existing code - let minorRevision = if version.Revision = -1 then 0us else uint16 version.MinorRevision - ILVersionInfo (zero32 version.Major, zero32 version.Minor, zero32 version.Build, minorRevision) - -let compareILVersions (version1 : ILVersionInfo) (version2 : ILVersionInfo) = - let c = compare version1.Major version2.Major - if c <> 0 then c else - let c = compare version1.Minor version2.Minor - if c <> 0 then c else - let c = compare version1.Build version2.Build - if c <> 0 then c else - let c = compare version1.Revision version2.Revision - if c <> 0 then c else - 0 - let unscopeILTypeRef (x: ILTypeRef) = ILTypeRef.Create (ILScopeRef.Local, x.Enclosing, x.Name) let rec unscopeILTypeSpec (tspec: ILTypeSpec) = @@ -4360,20 +4371,6 @@ let resolveILMethodRef td mref = resolveILMethodRefWithRescope id td mref let mkRefToILModule m = ILModuleRef.Create (m.Name, true, None) -let MscorlibScopeRef = ILScopeRef.Assembly (ILAssemblyRef.Create ("mscorlib", None, Some ecmaPublicKey, true, None, None)) - -let DummyFSharpCoreScopeRef = - let asmRef = - // The exact public key token and version used here don't actually matter, or shouldn't. - ILAssemblyRef.Create("FSharp.Core", None, - Some (PublicKeyToken(Bytes.ofInt32Array [| 0xb0; 0x3f; 0x5f; 0x7f; 0x11; 0xd5; 0x0a; 0x3a |])), - false, - Some (parseILVersion "0.0.0.0"), None) - ILScopeRef.Assembly asmRef - -let EcmaMscorlibILGlobals = mkILGlobals (MscorlibScopeRef, [], DummyFSharpCoreScopeRef) -let PrimaryAssemblyILGlobals = mkILGlobals (ILScopeRef.PrimaryAssembly, [], DummyFSharpCoreScopeRef) - type ILEventRef = { erA: ILTypeRef erB: string } diff --git a/src/fsharp/absil/il.fsi b/src/fsharp/absil/il.fsi index 3528e62f60f..03f233ea370 100644 --- a/src/fsharp/absil/il.fsi +++ b/src/fsharp/absil/il.fsi @@ -1658,7 +1658,6 @@ type internal ILGlobals = /// Build the table of commonly used references given functions to find types in system assemblies val internal mkILGlobals: primaryScopeRef: ILScopeRef * assembliesThatForwardToPrimaryAssembly: ILAssemblyRef list * fsharpCoreAssemblyScopeRef: ILScopeRef -> ILGlobals -val internal EcmaMscorlibILGlobals: ILGlobals val internal PrimaryAssemblyILGlobals: ILGlobals /// When writing a binary the fake "toplevel" type definition (called ) @@ -1670,7 +1669,6 @@ val internal destTypeDefsWithGlobalFunctionsFirst: ILGlobals -> ILTypeDefs -> IL /// enums must be bound in order to discover the size of the underlying integer. /// The following assumes enums have size int32. val internal decodeILAttribData: - ILGlobals -> ILAttribute -> ILAttribElem list * (* fixed args *) ILAttributeNamedArg list (* named args: values and flags indicating if they are fields or properties *) @@ -1747,22 +1745,20 @@ val internal mkILSimpleTypar: string -> ILGenericParameterDef /// Make custom attributes. val internal mkILCustomAttribMethRef: - ILGlobals - -> ILMethodSpec + ILMethodSpec * ILAttribElem list (* fixed args: values and implicit types *) * ILAttributeNamedArg list (* named args: values and flags indicating if they are fields or properties *) -> ILAttribute val internal mkILCustomAttribute: - ILGlobals - -> ILTypeRef * ILType list * + ILTypeRef * ILType list * ILAttribElem list (* fixed args: values and implicit types *) * ILAttributeNamedArg list (* named args: values and flags indicating if they are fields or properties *) -> ILAttribute -val internal getCustomAttrData: ILGlobals -> ILAttribute -> byte[] +val internal getCustomAttrData: ILAttribute -> byte[] -val internal mkPermissionSet: ILGlobals -> ILSecurityAction * (ILTypeRef * (string * ILType * ILAttribElem) list) list -> ILSecurityDecl +val internal mkPermissionSet: ILSecurityAction * (ILTypeRef * (string * ILType * ILAttribElem) list) list -> ILSecurityDecl /// Making code. val internal generateCodeLabel: unit -> ILCodeLabel diff --git a/src/fsharp/absil/ilmorph.fs b/src/fsharp/absil/ilmorph.fs index 61e672cd868..600184c8aaf 100644 --- a/src/fsharp/absil/ilmorph.fs +++ b/src/fsharp/absil/ilmorph.fs @@ -133,27 +133,27 @@ let rec celem_ty2ty f celem = let cnamedarg_ty2ty f ((nm, ty, isProp, elem) : ILAttributeNamedArg) = (nm, f ty, isProp, celem_ty2ty f elem) -let cattr_ty2ty ilg f (c: ILAttribute) = +let cattr_ty2ty f (c: ILAttribute) = let meth = mspec_ty2ty (f, (fun _ -> f)) c.Method // dev11 M3 defensive coding: if anything goes wrong with attribute decoding or encoding, then back out. if morphCustomAttributeData then try - let elems,namedArgs = IL.decodeILAttribData ilg c + let elems,namedArgs = IL.decodeILAttribData c let elems = elems |> List.map (celem_ty2ty f) let namedArgs = namedArgs |> List.map (cnamedarg_ty2ty f) - mkILCustomAttribMethRef ilg (meth, elems, namedArgs) + mkILCustomAttribMethRef (meth, elems, namedArgs) with _ -> c.WithMethod(meth) else c.WithMethod(meth) -let cattrs_ty2ty ilg f (cs: ILAttributes) = - mkILCustomAttrs (List.map (cattr_ty2ty ilg f) cs.AsList) +let cattrs_ty2ty f (cs: ILAttributes) = + mkILCustomAttrs (List.map (cattr_ty2ty f) cs.AsList) -let fdef_ty2ty ilg ftye (fd: ILFieldDef) = +let fdef_ty2ty ftye (fd: ILFieldDef) = fd.With(fieldType=ftye fd.FieldType, - customAttrs=cattrs_ty2ty ilg ftye fd.CustomAttrs) + customAttrs=cattrs_ty2ty ftye fd.CustomAttrs) let local_ty2ty f (l: ILLocal) = {l with Type = f l.Type} let varargs_ty2ty f (varargs: ILVarArgs) = Option.map (List.map f) varargs @@ -197,8 +197,8 @@ let morphILTypesInILInstr ((factualty,fformalty)) i = | ILToken.ILField fr -> I_ldtoken (ILToken.ILField (conv_fspec fr)) | x -> x -let return_ty2ty ilg f (r:ILReturn) = {r with Type=f r.Type; CustomAttrsStored= storeILCustomAttrs (cattrs_ty2ty ilg f r.CustomAttrs)} -let param_ty2ty ilg f (p: ILParameter) = {p with Type=f p.Type; CustomAttrsStored= storeILCustomAttrs (cattrs_ty2ty ilg f p.CustomAttrs)} +let return_ty2ty f (r:ILReturn) = {r with Type=f r.Type; CustomAttrsStored= storeILCustomAttrs (cattrs_ty2ty f r.CustomAttrs)} +let param_ty2ty f (p: ILParameter) = {p with Type=f p.Type; CustomAttrsStored= storeILCustomAttrs (cattrs_ty2ty f p.CustomAttrs)} let morphILMethodDefs f (m:ILMethodDefs) = mkILMethods (List.map f m.AsList) let fdefs_fdef2fdef f (m:ILFieldDefs) = mkILFields (List.map f m.AsList) @@ -222,98 +222,98 @@ let morphILMethodBody (filmbody) (x: MethodBody) = let ospec_ty2ty f (OverridesSpec(mref,ty)) = OverridesSpec(mref_ty2ty f mref, f ty) -let mdef_ty2ty_ilmbody2ilmbody ilg fs (md: ILMethodDef) = +let mdef_ty2ty_ilmbody2ilmbody fs (md: ILMethodDef) = let (ftye,filmbody) = fs let ftye' = ftye (Some md) let body' = morphILMethodBody (filmbody (Some md)) md.Body md.With(genericParams=gparams_ty2ty ftye' md.GenericParams, body= notlazy body', - parameters = List.map (param_ty2ty ilg ftye') md.Parameters, - ret = return_ty2ty ilg ftye' md.Return, - customAttrs=cattrs_ty2ty ilg ftye' md.CustomAttrs) + parameters = List.map (param_ty2ty ftye') md.Parameters, + ret = return_ty2ty ftye' md.Return, + customAttrs=cattrs_ty2ty ftye' md.CustomAttrs) -let fdefs_ty2ty ilg f x = fdefs_fdef2fdef (fdef_ty2ty ilg f) x +let fdefs_ty2ty f x = fdefs_fdef2fdef (fdef_ty2ty f) x -let mdefs_ty2ty_ilmbody2ilmbody ilg fs x = morphILMethodDefs (mdef_ty2ty_ilmbody2ilmbody ilg fs) x +let mdefs_ty2ty_ilmbody2ilmbody fs x = morphILMethodDefs (mdef_ty2ty_ilmbody2ilmbody fs) x let mimpl_ty2ty f e = { Overrides = ospec_ty2ty f e.Overrides OverrideBy = mspec_ty2ty (f,(fun _ -> f)) e.OverrideBy; } -let edef_ty2ty ilg f (e: ILEventDef) = +let edef_ty2ty f (e: ILEventDef) = e.With(eventType = Option.map f e.EventType, addMethod = mref_ty2ty f e.AddMethod, removeMethod = mref_ty2ty f e.RemoveMethod, fireMethod = Option.map (mref_ty2ty f) e.FireMethod, otherMethods = List.map (mref_ty2ty f) e.OtherMethods, - customAttrs = cattrs_ty2ty ilg f e.CustomAttrs) + customAttrs = cattrs_ty2ty f e.CustomAttrs) -let pdef_ty2ty ilg f (p: ILPropertyDef) = +let pdef_ty2ty f (p: ILPropertyDef) = p.With(setMethod = Option.map (mref_ty2ty f) p.SetMethod, getMethod = Option.map (mref_ty2ty f) p.GetMethod, propertyType = f p.PropertyType, args = List.map f p.Args, - customAttrs = cattrs_ty2ty ilg f p.CustomAttrs) + customAttrs = cattrs_ty2ty f p.CustomAttrs) -let pdefs_ty2ty ilg f (pdefs: ILPropertyDefs) = mkILProperties (List.map (pdef_ty2ty ilg f) pdefs.AsList) -let edefs_ty2ty ilg f (edefs: ILEventDefs) = mkILEvents (List.map (edef_ty2ty ilg f) edefs.AsList) +let pdefs_ty2ty f (pdefs: ILPropertyDefs) = mkILProperties (List.map (pdef_ty2ty f) pdefs.AsList) +let edefs_ty2ty f (edefs: ILEventDefs) = mkILEvents (List.map (edef_ty2ty f) edefs.AsList) let mimpls_ty2ty f (mimpls : ILMethodImplDefs) = mkILMethodImpls (List.map (mimpl_ty2ty f) mimpls.AsList) -let rec tdef_ty2ty_ilmbody2ilmbody_mdefs2mdefs ilg enc fs (td: ILTypeDef) = +let rec tdef_ty2ty_ilmbody2ilmbody_mdefs2mdefs enc fs (td: ILTypeDef) = let (ftye,fmdefs) = fs let ftye' = ftye (Some (enc,td)) None let mdefs' = fmdefs (enc,td) td.Methods - let fdefs' = fdefs_ty2ty ilg ftye' td.Fields + let fdefs' = fdefs_ty2ty ftye' td.Fields td.With(implements= List.map ftye' td.Implements, genericParams= gparams_ty2ty ftye' td.GenericParams, extends = Option.map ftye' td.Extends, methods=mdefs', - nestedTypes=tdefs_ty2ty_ilmbody2ilmbody_mdefs2mdefs ilg (enc@[td]) fs td.NestedTypes, + nestedTypes=tdefs_ty2ty_ilmbody2ilmbody_mdefs2mdefs (enc@[td]) fs td.NestedTypes, fields=fdefs', methodImpls = mimpls_ty2ty ftye' td.MethodImpls, - events = edefs_ty2ty ilg ftye' td.Events, - properties = pdefs_ty2ty ilg ftye' td.Properties, - customAttrs = cattrs_ty2ty ilg ftye' td.CustomAttrs) + events = edefs_ty2ty ftye' td.Events, + properties = pdefs_ty2ty ftye' td.Properties, + customAttrs = cattrs_ty2ty ftye' td.CustomAttrs) -and tdefs_ty2ty_ilmbody2ilmbody_mdefs2mdefs ilg enc fs tdefs = - morphILTypeDefs (tdef_ty2ty_ilmbody2ilmbody_mdefs2mdefs ilg enc fs) tdefs +and tdefs_ty2ty_ilmbody2ilmbody_mdefs2mdefs enc fs tdefs = + morphILTypeDefs (tdef_ty2ty_ilmbody2ilmbody_mdefs2mdefs enc fs) tdefs // -------------------------------------------------------------------- // Derived versions of the above, e.g. with defaults added // -------------------------------------------------------------------- -let manifest_ty2ty ilg f (m : ILAssemblyManifest) = - { m with CustomAttrsStored = storeILCustomAttrs (cattrs_ty2ty ilg f m.CustomAttrs) } +let manifest_ty2ty f (m : ILAssemblyManifest) = + { m with CustomAttrsStored = storeILCustomAttrs (cattrs_ty2ty f m.CustomAttrs) } -let morphILTypeInILModule_ilmbody2ilmbody_mdefs2mdefs ilg ((ftye: ILModuleDef -> (ILTypeDef list * ILTypeDef) option -> ILMethodDef option -> ILType -> ILType),fmdefs) m = +let morphILTypeInILModule_ilmbody2ilmbody_mdefs2mdefs ((ftye: ILModuleDef -> (ILTypeDef list * ILTypeDef) option -> ILMethodDef option -> ILType -> ILType),fmdefs) m = - let ftdefs = tdefs_ty2ty_ilmbody2ilmbody_mdefs2mdefs ilg [] (ftye m,fmdefs m) + let ftdefs = tdefs_ty2ty_ilmbody2ilmbody_mdefs2mdefs [] (ftye m,fmdefs m) { m with TypeDefs=ftdefs m.TypeDefs - CustomAttrsStored= storeILCustomAttrs (cattrs_ty2ty ilg (ftye m None None) m.CustomAttrs) - Manifest=Option.map (manifest_ty2ty ilg (ftye m None None)) m.Manifest } + CustomAttrsStored= storeILCustomAttrs (cattrs_ty2ty (ftye m None None) m.CustomAttrs) + Manifest=Option.map (manifest_ty2ty (ftye m None None)) m.Manifest } -let module_instr2instr_ty2ty ilg fs x = +let module_instr2instr_ty2ty fs x = let (fcode,ftye) = fs let filmbody modCtxt tdefCtxt mdefCtxt = ilmbody_instr2instr_ty2ty (fcode modCtxt tdefCtxt mdefCtxt, ftye modCtxt (Some tdefCtxt) mdefCtxt) - let fmdefs modCtxt tdefCtxt = mdefs_ty2ty_ilmbody2ilmbody ilg (ftye modCtxt (Some tdefCtxt), filmbody modCtxt tdefCtxt) - morphILTypeInILModule_ilmbody2ilmbody_mdefs2mdefs ilg (ftye, fmdefs) x + let fmdefs modCtxt tdefCtxt = mdefs_ty2ty_ilmbody2ilmbody (ftye modCtxt (Some tdefCtxt), filmbody modCtxt tdefCtxt) + morphILTypeInILModule_ilmbody2ilmbody_mdefs2mdefs (ftye, fmdefs) x -let morphILInstrsAndILTypesInILModule ilg (f1,f2) x = - module_instr2instr_ty2ty ilg (f1, f2) x +let morphILInstrsAndILTypesInILModule (f1,f2) x = + module_instr2instr_ty2ty (f1, f2) x let morphILInstrsInILCode f x = code_instr2instrs f x -let morphILTypeInILModule ilg ftye y = +let morphILTypeInILModule ftye y = let finstr modCtxt tdefCtxt mdefCtxt = let fty = ftye modCtxt (Some tdefCtxt) mdefCtxt morphILTypesInILInstr ((fun _instrCtxt -> fty), (fun _instrCtxt _formalCtxt -> fty)) - morphILInstrsAndILTypesInILModule ilg (finstr,ftye) y + morphILInstrsAndILTypesInILModule (finstr,ftye) y -let morphILTypeRefsInILModuleMemoized ilg f modul = +let morphILTypeRefsInILModuleMemoized f modul = let fty = Tables.memoize (ty_tref2tref f) - morphILTypeInILModule ilg (fun _ _ _ ty -> fty ty) modul + morphILTypeInILModule (fun _ _ _ ty -> fty ty) modul -let morphILScopeRefsInILModuleMemoized ilg f modul = - morphILTypeRefsInILModuleMemoized ilg (morphILScopeRefsInILTypeRef f) modul +let morphILScopeRefsInILModuleMemoized f modul = + morphILTypeRefsInILModuleMemoized (morphILScopeRefsInILTypeRef f) modul diff --git a/src/fsharp/absil/ilmorph.fsi b/src/fsharp/absil/ilmorph.fsi index 1828e87a199..70cb7808f2e 100644 --- a/src/fsharp/absil/ilmorph.fsi +++ b/src/fsharp/absil/ilmorph.fsi @@ -14,9 +14,9 @@ open FSharp.Compiler.AbstractIL.IL val morphILScopeRefsInILTypeRef: (ILScopeRef -> ILScopeRef) -> ILTypeRef -> ILTypeRef /// Morph all type references throughout an entire module. -val morphILTypeRefsInILModuleMemoized: ILGlobals -> (ILTypeRef -> ILTypeRef) -> ILModuleDef -> ILModuleDef +val morphILTypeRefsInILModuleMemoized: (ILTypeRef -> ILTypeRef) -> ILModuleDef -> ILModuleDef -val morphILScopeRefsInILModuleMemoized: ILGlobals -> (ILScopeRef -> ILScopeRef) -> ILModuleDef -> ILModuleDef +val morphILScopeRefsInILModuleMemoized: (ILScopeRef -> ILScopeRef) -> ILModuleDef -> ILModuleDef val morphILInstrsInILCode: (ILInstr -> ILInstr list) -> ILCode -> ILCode diff --git a/src/fsharp/absil/ilprint.fs b/src/fsharp/absil/ilprint.fs index 31ab474c269..782899e9111 100644 --- a/src/fsharp/absil/ilprint.fs +++ b/src/fsharp/absil/ilprint.fs @@ -195,20 +195,20 @@ and goutput_typ env os ty = | ILType.Byref typ -> goutput_typ env os typ; output_string os "&" | ILType.Ptr typ -> goutput_typ env os typ; output_string os "*" - | ILType.Value tspec when tspec.Name = EcmaMscorlibILGlobals.typ_SByte.TypeSpec.Name -> output_string os "int8" - | ILType.Value tspec when tspec.Name = EcmaMscorlibILGlobals.typ_Int16.TypeSpec.Name -> output_string os "int16" - | ILType.Value tspec when tspec.Name = EcmaMscorlibILGlobals.typ_Int32.TypeSpec.Name -> output_string os "int32" - | ILType.Value tspec when tspec.Name = EcmaMscorlibILGlobals.typ_Int64.TypeSpec.Name -> output_string os "int64" - | ILType.Value tspec when tspec.Name = EcmaMscorlibILGlobals.typ_IntPtr.TypeSpec.Name -> output_string os "native int" - | ILType.Value tspec when tspec.Name = EcmaMscorlibILGlobals.typ_Byte.TypeSpec.Name -> output_string os "unsigned int8" - | ILType.Value tspec when tspec.Name = EcmaMscorlibILGlobals.typ_UInt16.TypeSpec.Name -> output_string os "unsigned int16" - | ILType.Value tspec when tspec.Name = EcmaMscorlibILGlobals.typ_UInt32.TypeSpec.Name -> output_string os "unsigned int32" - | ILType.Value tspec when tspec.Name = EcmaMscorlibILGlobals.typ_UInt64.TypeSpec.Name -> output_string os "unsigned int64" - | ILType.Value tspec when tspec.Name = EcmaMscorlibILGlobals.typ_UIntPtr.TypeSpec.Name -> output_string os "native unsigned int" - | ILType.Value tspec when tspec.Name = EcmaMscorlibILGlobals.typ_Double.TypeSpec.Name -> output_string os "float64" - | ILType.Value tspec when tspec.Name = EcmaMscorlibILGlobals.typ_Single.TypeSpec.Name -> output_string os "float32" - | ILType.Value tspec when tspec.Name = EcmaMscorlibILGlobals.typ_Bool.TypeSpec.Name -> output_string os "bool" - | ILType.Value tspec when tspec.Name = EcmaMscorlibILGlobals.typ_Char.TypeSpec.Name -> output_string os "char" + | ILType.Value tspec when tspec.Name = PrimaryAssemblyILGlobals.typ_SByte.TypeSpec.Name -> output_string os "int8" + | ILType.Value tspec when tspec.Name = PrimaryAssemblyILGlobals.typ_Int16.TypeSpec.Name -> output_string os "int16" + | ILType.Value tspec when tspec.Name = PrimaryAssemblyILGlobals.typ_Int32.TypeSpec.Name -> output_string os "int32" + | ILType.Value tspec when tspec.Name = PrimaryAssemblyILGlobals.typ_Int64.TypeSpec.Name -> output_string os "int64" + | ILType.Value tspec when tspec.Name = PrimaryAssemblyILGlobals.typ_IntPtr.TypeSpec.Name -> output_string os "native int" + | ILType.Value tspec when tspec.Name = PrimaryAssemblyILGlobals.typ_Byte.TypeSpec.Name -> output_string os "unsigned int8" + | ILType.Value tspec when tspec.Name = PrimaryAssemblyILGlobals.typ_UInt16.TypeSpec.Name -> output_string os "unsigned int16" + | ILType.Value tspec when tspec.Name = PrimaryAssemblyILGlobals.typ_UInt32.TypeSpec.Name -> output_string os "unsigned int32" + | ILType.Value tspec when tspec.Name = PrimaryAssemblyILGlobals.typ_UInt64.TypeSpec.Name -> output_string os "unsigned int64" + | ILType.Value tspec when tspec.Name = PrimaryAssemblyILGlobals.typ_UIntPtr.TypeSpec.Name -> output_string os "native unsigned int" + | ILType.Value tspec when tspec.Name = PrimaryAssemblyILGlobals.typ_Double.TypeSpec.Name -> output_string os "float64" + | ILType.Value tspec when tspec.Name = PrimaryAssemblyILGlobals.typ_Single.TypeSpec.Name -> output_string os "float32" + | ILType.Value tspec when tspec.Name = PrimaryAssemblyILGlobals.typ_Bool.TypeSpec.Name -> output_string os "bool" + | ILType.Value tspec when tspec.Name = PrimaryAssemblyILGlobals.typ_Char.TypeSpec.Name -> output_string os "char" | ILType.Value tspec -> output_string os "value class " goutput_tref env os tspec.TypeRef @@ -499,7 +499,7 @@ let output_custom_attr_data os data = let goutput_custom_attr env os (attr: ILAttribute) = output_string os " .custom " goutput_mspec env os attr.Method - let data = getCustomAttrData env.ilGlobals attr + let data = getCustomAttrData attr output_custom_attr_data os data let goutput_custom_attrs env os (attrs : ILAttributes) = @@ -730,7 +730,7 @@ let rec goutput_instr env os inst = goutput_dlocref env os (mkILArrTy(typ, shape)) output_string os ".ctor" let rank = shape.Rank - output_parens (output_array ", " (goutput_typ env)) os (Array.create ( rank) EcmaMscorlibILGlobals.typ_Int32) + output_parens (output_array ", " (goutput_typ env)) os (Array.create ( rank) PrimaryAssemblyILGlobals.typ_Int32) | I_stelem_any (shape, dt) -> if shape = ILArrayShape.SingleDimensional then output_string os "stelem.any "; goutput_typ env os dt @@ -739,7 +739,7 @@ let rec goutput_instr env os inst = goutput_dlocref env os (mkILArrTy(dt, shape)) output_string os "Set" let rank = shape.Rank - let arr = Array.create (rank + 1) EcmaMscorlibILGlobals.typ_Int32 + let arr = Array.create (rank + 1) PrimaryAssemblyILGlobals.typ_Int32 arr.[rank] <- dt output_parens (output_array ", " (goutput_typ env)) os arr | I_ldelem_any (shape, tok) -> @@ -752,7 +752,7 @@ let rec goutput_instr env os inst = goutput_dlocref env os (mkILArrTy(tok, shape)) output_string os "Get" let rank = shape.Rank - output_parens (output_array ", " (goutput_typ env)) os (Array.create ( rank) EcmaMscorlibILGlobals.typ_Int32) + output_parens (output_array ", " (goutput_typ env)) os (Array.create ( rank) PrimaryAssemblyILGlobals.typ_Int32) | I_ldelema (ro, _, shape, tok) -> if ro = ReadonlyAddress then output_string os "readonly. " if shape = ILArrayShape.SingleDimensional then @@ -764,7 +764,7 @@ let rec goutput_instr env os inst = goutput_dlocref env os (mkILArrTy(tok, shape)) output_string os "Address" let rank = shape.Rank - output_parens (output_array ", " (goutput_typ env)) os (Array.create ( rank) EcmaMscorlibILGlobals.typ_Int32) + output_parens (output_array ", " (goutput_typ env)) os (Array.create ( rank) PrimaryAssemblyILGlobals.typ_Int32) | I_box tok -> output_string os "box "; goutput_typ env os tok | I_unbox tok -> output_string os "unbox "; goutput_typ env os tok diff --git a/src/fsharp/absil/ilreflect.fs b/src/fsharp/absil/ilreflect.fs index e40d0945934..9af3997e31a 100644 --- a/src/fsharp/absil/ilreflect.fs +++ b/src/fsharp/absil/ilreflect.fs @@ -1384,7 +1384,7 @@ let convCustomAttr cenv emEnv (cattr: ILAttribute) = match convConstructorSpec cenv emEnv cattr.Method with | null -> failwithf "convCustomAttr: %+A" cattr.Method | res -> res - let data = getCustomAttrData cenv.ilg cattr + let data = getCustomAttrData cattr (methInfo, data) let emitCustomAttr cenv emEnv add cattr = add (convCustomAttr cenv emEnv cattr) @@ -1740,7 +1740,7 @@ let typeAttributesOfTypeLayout cenv emEnv x = match cenv.tryFindSysILTypeRef "System.Runtime.InteropServices.StructLayoutAttribute", cenv.tryFindSysILTypeRef "System.Runtime.InteropServices.LayoutKind" with | Some tref1, Some tref2 -> Some(convCustomAttr cenv emEnv - (IL.mkILCustomAttribute cenv.ilg + (IL.mkILCustomAttribute (tref1, [mkILNonGenericValueTy tref2 ], [ ILAttribElem.Int32 x ], diff --git a/src/fsharp/absil/ilwrite.fs b/src/fsharp/absil/ilwrite.fs index ee600b084ea..7fab0d0ae95 100644 --- a/src/fsharp/absil/ilwrite.fs +++ b/src/fsharp/absil/ilwrite.fs @@ -1331,7 +1331,7 @@ let rec GetCustomAttrDataAsBlobIdx cenv (data: byte[]) = and GetCustomAttrRow cenv hca (attr: ILAttribute) = let cat = GetMethodRefAsCustomAttribType cenv attr.Method.MethodRef - let data = getCustomAttrData cenv.ilg attr + let data = getCustomAttrData attr for element in attr.Elements do match element with | ILAttribElem.Type (Some ty) when ty.IsNominal -> GetTypeRefAsTypeRefIdx cenv ty.TypeRef |> ignore diff --git a/src/fsharp/fsc.fs b/src/fsharp/fsc.fs index 963568626b4..f3a4168efd2 100644 --- a/src/fsharp/fsc.fs +++ b/src/fsharp/fsc.fs @@ -559,7 +559,7 @@ let main1(ctok, argv, legacyReferenceResolver, bannerAlreadyPrinted, ReportTime tcConfig "Import non-system references" let tcImports = - TcImports.BuildNonFrameworkTcImports(ctok, tcConfigP, tcGlobals, frameworkTcImports, otherRes, knownUnresolved, dependencyProvider) + TcImports.BuildNonFrameworkTcImports(ctok, tcConfigP, frameworkTcImports, otherRes, knownUnresolved, dependencyProvider) |> Cancellable.runWithoutCancellation // register tcImports to be disposed in future @@ -683,7 +683,7 @@ let main1OfAst // Import other assemblies ReportTime tcConfig "Import non-system references" - let tcImports = TcImports.BuildNonFrameworkTcImports(ctok, tcConfigP, tcGlobals, frameworkTcImports, otherRes, knownUnresolved, dependencyProvider) |> Cancellable.runWithoutCancellation + let tcImports = TcImports.BuildNonFrameworkTcImports(ctok, tcConfigP, frameworkTcImports, otherRes, knownUnresolved, dependencyProvider) |> Cancellable.runWithoutCancellation // register tcImports to be disposed in future disposables.Register tcImports diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index f463f938857..830bfab745a 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -1144,7 +1144,7 @@ type internal FsiDynamicCompiler errorLogger.AbortOnError(fsiConsoleOutput); ReportTime tcConfig "Assembly refs Normalised"; - let mainmod3 = Morphs.morphILScopeRefsInILModuleMemoized ilGlobals (NormalizeAssemblyRefs (ctok, ilGlobals, tcImports)) ilxMainModule + let mainmod3 = Morphs.morphILScopeRefsInILModuleMemoized (NormalizeAssemblyRefs (ctok, ilGlobals, tcImports)) ilxMainModule errorLogger.AbortOnError(fsiConsoleOutput); #if DEBUG @@ -2867,7 +2867,7 @@ type FsiEvaluationSession (fsi: FsiEvaluationSessionHostConfig, argv:string[], i let tcImports = try - TcImports.BuildNonFrameworkTcImports(ctokStartup, tcConfigP, tcGlobals, frameworkTcImports, nonFrameworkResolutions, unresolvedReferences, fsiOptions.DependencyProvider) |> Cancellable.runWithoutCancellation + TcImports.BuildNonFrameworkTcImports(ctokStartup, tcConfigP, frameworkTcImports, nonFrameworkResolutions, unresolvedReferences, fsiOptions.DependencyProvider) |> Cancellable.runWithoutCancellation with e -> stopProcessingRecovery e range0; failwithf "Error creating evaluation session: %A" e diff --git a/src/fsharp/infos.fs b/src/fsharp/infos.fs index 4404472318d..96422ef10b9 100755 --- a/src/fsharp/infos.fs +++ b/src/fsharp/infos.fs @@ -1409,7 +1409,7 @@ type MethInfo = [ [ for p in ilMethInfo.ParamMetadata do let isParamArrayArg = TryFindILAttribute g.attrib_ParamArrayAttribute p.CustomAttrs let reflArgInfo = - match TryDecodeILAttribute g g.attrib_ReflectedDefinitionAttribute.TypeRef p.CustomAttrs with + match TryDecodeILAttribute g.attrib_ReflectedDefinitionAttribute.TypeRef p.CustomAttrs with | Some ([ILAttribElem.Bool b ], _) -> ReflectedArgInfo.Quote b | Some _ -> ReflectedArgInfo.Quote false | _ -> ReflectedArgInfo.None diff --git a/src/fsharp/service/IncrementalBuild.fs b/src/fsharp/service/IncrementalBuild.fs index 27ef3b9fabc..9600eee88ec 100644 --- a/src/fsharp/service/IncrementalBuild.fs +++ b/src/fsharp/service/IncrementalBuild.fs @@ -641,8 +641,8 @@ type RawFSharpAssemblyDataBackedByLanguageService (tcConfig, tcGlobals, tcState: let ivtAttrs = topAttrs.assemblyAttrs |> List.choose (List.singleton >> TryFindFSharpStringAttribute tcGlobals tcGlobals.attrib_InternalsVisibleToAttribute) interface IRawFSharpAssemblyData with - member _.GetAutoOpenAttributes(_ilg) = autoOpenAttrs - member _.GetInternalsVisibleToAttributes(_ilg) = ivtAttrs + member _.GetAutoOpenAttributes() = autoOpenAttrs + member _.GetInternalsVisibleToAttributes() = ivtAttrs member _.TryGetILModuleDef() = None member _.GetRawFSharpSignatureData(_m, _ilShortAssemName, _filename) = sigData member _.GetRawFSharpOptimizationData(_m, _ilShortAssemName, _filename) = [ ] @@ -651,7 +651,7 @@ type RawFSharpAssemblyDataBackedByLanguageService (tcConfig, tcGlobals, tcState: member _.ILScopeRef = IL.ILScopeRef.Assembly ilAssemRef member _.ILAssemblyRefs = [] // These are not significant for service scenarios member _.HasAnyFSharpSignatureDataAttribute = true - member _.HasMatchingFSharpSignatureDataAttribute _ilg = true + member _.HasMatchingFSharpSignatureDataAttribute = true type IncrementalBuilderState = { @@ -754,7 +754,7 @@ type IncrementalBuilder(tcGlobals, let! tcImports = cancellable { try - let! tcImports = TcImports.BuildNonFrameworkTcImports(ctok, tcConfigP, tcGlobals, frameworkTcImports, nonFrameworkResolutions, unresolvedReferences, dependencyProvider) + let! tcImports = TcImports.BuildNonFrameworkTcImports(ctok, tcConfigP, frameworkTcImports, nonFrameworkResolutions, unresolvedReferences, dependencyProvider) #if !NO_EXTENSIONTYPING tcImports.GetCcusExcludingBase() |> Seq.iter (fun ccu -> // When a CCU reports an invalidation, merge them together and just report a diff --git a/src/fsharp/symbols/Symbols.fs b/src/fsharp/symbols/Symbols.fs index 4048b82726a..76a0d443793 100644 --- a/src/fsharp/symbols/Symbols.fs +++ b/src/fsharp/symbols/Symbols.fs @@ -2540,7 +2540,7 @@ type FSharpAttribute(cenv: SymbolEnv, attrib: AttribInfo) = | AttribInfo.FSAttribInfo(g, attrib) -> NicePrint.stringOfFSAttrib (context.Contents g) attrib | AttribInfo.ILAttribInfo (g, _, _scoref, cattr, _) -> - let parms, _args = decodeILAttribData g.ilg cattr + let parms, _args = decodeILAttribData cattr NicePrint.stringOfILAttrib (context.Contents g) (cattr.Method.DeclaringType, parms) member _.Range = attrib.Range From 144207b5cfa44cfb2fa7b05c7c128f063cc215e0 Mon Sep 17 00:00:00 2001 From: Hadrian Tang Date: Thu, 27 May 2021 20:21:52 +0800 Subject: [PATCH 08/12] [RFC FS-1100] Printf format as binary number (#11603) --- src/fsharp/CheckFormatStrings.fs | 3 +- src/fsharp/FSComp.txt | 3 +- src/fsharp/FSharp.Core/printf.fs | 24 ++++++++----- src/fsharp/LanguageFeatures.fs | 3 ++ src/fsharp/LanguageFeatures.fsi | 1 + src/fsharp/xlf/FSComp.txt.cs.xlf | 7 +++- src/fsharp/xlf/FSComp.txt.de.xlf | 7 +++- src/fsharp/xlf/FSComp.txt.es.xlf | 7 +++- src/fsharp/xlf/FSComp.txt.fr.xlf | 7 +++- src/fsharp/xlf/FSComp.txt.it.xlf | 7 +++- src/fsharp/xlf/FSComp.txt.ja.xlf | 7 +++- src/fsharp/xlf/FSComp.txt.ko.xlf | 7 +++- src/fsharp/xlf/FSComp.txt.pl.xlf | 7 +++- src/fsharp/xlf/FSComp.txt.pt-BR.xlf | 7 +++- src/fsharp/xlf/FSComp.txt.ru.xlf | 7 +++- src/fsharp/xlf/FSComp.txt.tr.xlf | 7 +++- src/fsharp/xlf/FSComp.txt.zh-Hans.xlf | 7 +++- src/fsharp/xlf/FSComp.txt.zh-Hant.xlf | 7 +++- .../Microsoft.FSharp.Core/PrintfTests.fs | 30 ++++++++++++++++ .../Compiler/Language/StringInterpolation.fs | 16 +++++++-- .../fsharp/core/printf-interpolated/test.fsx | 25 +++++++++++-- tests/fsharp/core/printf/test.fsx | 35 +++++++++++++++++-- tests/fsharp/tests.fs | 2 +- 23 files changed, 202 insertions(+), 31 deletions(-) diff --git a/src/fsharp/CheckFormatStrings.fs b/src/fsharp/CheckFormatStrings.fs index 5520268b424..4556a9190f3 100644 --- a/src/fsharp/CheckFormatStrings.fs +++ b/src/fsharp/CheckFormatStrings.fs @@ -366,7 +366,8 @@ let parseFormatStringInternal (m: range) (fragRanges: range list) (g: TcGlobals) appendToDotnetFormatString "%" parseLoop acc (i+1, fragLine, fragCol+1) fragments - | ('d' | 'i' | 'o' | 'u' | 'x' | 'X') -> + | ('d' | 'i' | 'u' | 'B' | 'o' | 'x' | 'X') -> + if ch = 'B' then ErrorLogger.checkLanguageFeatureError g.langVersion Features.LanguageFeature.PrintfBinaryFormat m if info.precision then failwithf "%s" <| FSComp.SR.forFormatDoesntSupportPrecision(ch.ToString()) collectSpecifierLocation fragLine fragCol 1 let i = skipPossibleInterpolationHole (i+1) diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index a022bc80aae..1d05fc756e5 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -1230,6 +1230,7 @@ invalidFullNameForProvidedType,"invalid full name for provided type" 3087,tcCustomOperationMayNotBeOverloaded,"The custom operation '%s' refers to a method which is overloaded. The implementations of custom operations may not be overloaded." featureOverloadsForCustomOperations,"overloads for custom operations" featureExpandedMeasurables,"more types support units of measure" +featurePrintfBinaryFormat,"binary formatting for integers" 3090,tcIfThenElseMayNotBeUsedWithinQueries,"An if/then/else expression may not be used within queries. Consider using either an if/then expression, or use a sequence expression instead." 3091,ilxgenUnexpectedArgumentToMethodHandleOfDuringCodegen,"Invalid argument to 'methodhandleof' during codegen" 3092,etProvidedTypeReferenceMissingArgument,"A reference to a provided type was missing a value for the static parameter '%s'. You may need to recompile one or more referenced assemblies." @@ -1558,4 +1559,4 @@ forFormatInvalidForInterpolated4,"Interpolated strings used as type IFormattable 3390,xmlDocMissingParameter,"This XML comment is incomplete: no documentation for parameter '%s'" 3391,tcLiteralAttributeCannotUseActivePattern,"A [] declaration cannot use an active pattern for its identifier" 3392,containerDeprecated,"The 'AssemblyKeyNameAttribute' has been deprecated. Use 'AssemblyKeyFileAttribute' instead." -3393,containerSigningUnsupportedOnThisPlatform,"Key container signing is not supported on this platform." \ No newline at end of file +3393,containerSigningUnsupportedOnThisPlatform,"Key container signing is not supported on this platform." diff --git a/src/fsharp/FSharp.Core/printf.fs b/src/fsharp/FSharp.Core/printf.fs index 05ffcce3ea6..0dbdb801c88 100644 --- a/src/fsharp/FSharp.Core/printf.fs +++ b/src/fsharp/FSharp.Core/printf.fs @@ -724,7 +724,7 @@ module internal PrintfImpl = else fun (v: obj) -> noJustificationCore (f v) true (isPositive v) prefix - /// contains functions to handle left\right and no justification case for numbers + /// contains functions to handle left/right and no justification case for numbers module Integer = let eliminateNative (v: obj) = @@ -821,21 +821,27 @@ module internal PrintfImpl = (rightJustify f prefix padChar isUnsigned) let getValueConverter (spec: FormatSpecifier) : ValueConverter = - let c = spec.TypeChar - if c = 'd' || c = 'i' then + match spec.TypeChar with + | 'd' | 'i' -> withPadding spec false toString - elif c = 'u' then + | 'u' -> withPadding spec true (toUnsigned >> toString) - elif c = 'x' then + | 'x' -> withPadding spec true (toFormattedString "x") - elif c = 'X' then + | 'X' -> withPadding spec true (toFormattedString "X") - elif c = 'o' then + | 'o' -> withPadding spec true (fun (v: obj) -> + // Convert.ToInt64 throws for uint64 with values above int64 range so cast directly match toUnsigned v with | :? uint64 as u -> Convert.ToString(int64 u, 8) | u -> Convert.ToString(Convert.ToInt64 u, 8)) - else raise (ArgumentException()) + | 'B' -> + withPadding spec true (fun (v: obj) -> + match toUnsigned v with + | :? uint64 as u -> Convert.ToString(int64 u, 2) + | u -> Convert.ToString(Convert.ToInt64 u, 2)) + | _ -> invalidArg (nameof spec) "Invalid integer format" module FloatAndDecimal = @@ -982,7 +988,7 @@ module internal PrintfImpl = Basic.withPadding spec (fun (c: obj) -> (unbox c).ToString()) | 'M' -> FloatAndDecimal.withPadding spec (fun _ -> "G") "G" // %M ignores precision - | 'd' | 'i' | 'x' | 'X' | 'u' | 'o'-> + | 'd' | 'i' | 'u' | 'B' | 'o' | 'x' | 'X' -> Integer.getValueConverter spec | 'e' | 'E' | 'f' | 'F' diff --git a/src/fsharp/LanguageFeatures.fs b/src/fsharp/LanguageFeatures.fs index 96c4f6baa5c..ba539fea0ed 100644 --- a/src/fsharp/LanguageFeatures.fs +++ b/src/fsharp/LanguageFeatures.fs @@ -36,6 +36,7 @@ type LanguageFeature = | StringInterpolation | OverloadsForCustomOperations | ExpandedMeasurables + | PrintfBinaryFormat /// LanguageVersion management type LanguageVersion (specifiedVersionAsString) = @@ -77,6 +78,7 @@ type LanguageVersion (specifiedVersionAsString) = LanguageFeature.OverloadsForCustomOperations, previewVersion LanguageFeature.ExpandedMeasurables, previewVersion LanguageFeature.FromEndSlicing, previewVersion + LanguageFeature.PrintfBinaryFormat, previewVersion ] let specified = @@ -150,6 +152,7 @@ type LanguageVersion (specifiedVersionAsString) = | LanguageFeature.StringInterpolation -> FSComp.SR.featureStringInterpolation() | LanguageFeature.OverloadsForCustomOperations -> FSComp.SR.featureOverloadsForCustomOperations() | LanguageFeature.ExpandedMeasurables -> FSComp.SR.featureExpandedMeasurables() + | LanguageFeature.PrintfBinaryFormat -> FSComp.SR.featurePrintfBinaryFormat() /// Get a version string associated with the given feature. member _.GetFeatureVersionString feature = diff --git a/src/fsharp/LanguageFeatures.fsi b/src/fsharp/LanguageFeatures.fsi index b914016d9a5..6f16e6b1f41 100644 --- a/src/fsharp/LanguageFeatures.fsi +++ b/src/fsharp/LanguageFeatures.fsi @@ -24,6 +24,7 @@ type LanguageFeature = | StringInterpolation | OverloadsForCustomOperations | ExpandedMeasurables + | PrintfBinaryFormat /// LanguageVersion management type LanguageVersion = diff --git a/src/fsharp/xlf/FSComp.txt.cs.xlf b/src/fsharp/xlf/FSComp.txt.cs.xlf index b077c7f4cde..fc00ec4242c 100644 --- a/src/fsharp/xlf/FSComp.txt.cs.xlf +++ b/src/fsharp/xlf/FSComp.txt.cs.xlf @@ -152,6 +152,11 @@ správa balíčků + + binary formatting for integers + binary formatting for integers + + whitespace relexation uvolnění prázdných znaků @@ -7654,4 +7659,4 @@ - \ No newline at end of file + diff --git a/src/fsharp/xlf/FSComp.txt.de.xlf b/src/fsharp/xlf/FSComp.txt.de.xlf index e58df8110fe..70b0ab49105 100644 --- a/src/fsharp/xlf/FSComp.txt.de.xlf +++ b/src/fsharp/xlf/FSComp.txt.de.xlf @@ -152,6 +152,11 @@ Paketverwaltung + + binary formatting for integers + binary formatting for integers + + whitespace relexation Lockerung für Leerraum @@ -7654,4 +7659,4 @@ - \ No newline at end of file + diff --git a/src/fsharp/xlf/FSComp.txt.es.xlf b/src/fsharp/xlf/FSComp.txt.es.xlf index 3a88e25c5fb..1d199c1f700 100644 --- a/src/fsharp/xlf/FSComp.txt.es.xlf +++ b/src/fsharp/xlf/FSComp.txt.es.xlf @@ -152,6 +152,11 @@ administración de paquetes + + binary formatting for integers + binary formatting for integers + + whitespace relexation relajación de espacio en blanco @@ -7654,4 +7659,4 @@ - \ No newline at end of file + diff --git a/src/fsharp/xlf/FSComp.txt.fr.xlf b/src/fsharp/xlf/FSComp.txt.fr.xlf index 24b1b52b226..d5d20379091 100644 --- a/src/fsharp/xlf/FSComp.txt.fr.xlf +++ b/src/fsharp/xlf/FSComp.txt.fr.xlf @@ -152,6 +152,11 @@ Package Management + + binary formatting for integers + binary formatting for integers + + whitespace relexation assouplissement de la mise en retrait avec des espaces blancs @@ -7654,4 +7659,4 @@ - \ No newline at end of file + diff --git a/src/fsharp/xlf/FSComp.txt.it.xlf b/src/fsharp/xlf/FSComp.txt.it.xlf index b5f1168716b..7276e8a34de 100644 --- a/src/fsharp/xlf/FSComp.txt.it.xlf +++ b/src/fsharp/xlf/FSComp.txt.it.xlf @@ -152,6 +152,11 @@ gestione pacchetti + + binary formatting for integers + binary formatting for integers + + whitespace relexation uso meno restrittivo degli spazi vuoti @@ -7654,4 +7659,4 @@ - \ No newline at end of file + diff --git a/src/fsharp/xlf/FSComp.txt.ja.xlf b/src/fsharp/xlf/FSComp.txt.ja.xlf index 0ec531ae4cf..a666c8a19bf 100644 --- a/src/fsharp/xlf/FSComp.txt.ja.xlf +++ b/src/fsharp/xlf/FSComp.txt.ja.xlf @@ -152,6 +152,11 @@ パッケージの管理 + + binary formatting for integers + binary formatting for integers + + whitespace relexation 空白の緩和 @@ -7654,4 +7659,4 @@ - \ No newline at end of file + diff --git a/src/fsharp/xlf/FSComp.txt.ko.xlf b/src/fsharp/xlf/FSComp.txt.ko.xlf index f60e003fb06..c714c5fd827 100644 --- a/src/fsharp/xlf/FSComp.txt.ko.xlf +++ b/src/fsharp/xlf/FSComp.txt.ko.xlf @@ -152,6 +152,11 @@ 패키지 관리 + + binary formatting for integers + binary formatting for integers + + whitespace relexation 공백 완화 @@ -7654,4 +7659,4 @@ - \ No newline at end of file + diff --git a/src/fsharp/xlf/FSComp.txt.pl.xlf b/src/fsharp/xlf/FSComp.txt.pl.xlf index 94fbb32c38d..e0545f3766c 100644 --- a/src/fsharp/xlf/FSComp.txt.pl.xlf +++ b/src/fsharp/xlf/FSComp.txt.pl.xlf @@ -152,6 +152,11 @@ zarządzanie pakietami + + binary formatting for integers + binary formatting for integers + + whitespace relexation rozluźnianie reguł dotyczących odstępów @@ -7654,4 +7659,4 @@ - \ No newline at end of file + diff --git a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf index 411e0b993b7..93de19089bc 100644 --- a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf +++ b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf @@ -152,6 +152,11 @@ gerenciamento de pacotes + + binary formatting for integers + binary formatting for integers + + whitespace relexation atenuação de espaço em branco @@ -7654,4 +7659,4 @@ - \ No newline at end of file + diff --git a/src/fsharp/xlf/FSComp.txt.ru.xlf b/src/fsharp/xlf/FSComp.txt.ru.xlf index f5f628ab960..035d8e725ed 100644 --- a/src/fsharp/xlf/FSComp.txt.ru.xlf +++ b/src/fsharp/xlf/FSComp.txt.ru.xlf @@ -152,6 +152,11 @@ управление пакетами + + binary formatting for integers + binary formatting for integers + + whitespace relexation уменьшение строгости для пробелов @@ -7654,4 +7659,4 @@ - \ No newline at end of file + diff --git a/src/fsharp/xlf/FSComp.txt.tr.xlf b/src/fsharp/xlf/FSComp.txt.tr.xlf index 329836e514f..c909ab82cd7 100644 --- a/src/fsharp/xlf/FSComp.txt.tr.xlf +++ b/src/fsharp/xlf/FSComp.txt.tr.xlf @@ -152,6 +152,11 @@ paket yönetimi + + binary formatting for integers + binary formatting for integers + + whitespace relexation boşluk genişlemesi @@ -7654,4 +7659,4 @@ - \ No newline at end of file + diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf index 0a1d33a3bf9..8fdbe1771f0 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf @@ -152,6 +152,11 @@ 包管理 + + binary formatting for integers + binary formatting for integers + + whitespace relexation 空格松弛法 @@ -7654,4 +7659,4 @@ - \ No newline at end of file + diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf index 58ebec0c197..c24ab78a551 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf @@ -152,6 +152,11 @@ 套件管理 + + binary formatting for integers + binary formatting for integers + + whitespace relexation 空白字元放寬 @@ -7654,4 +7659,4 @@ - \ No newline at end of file + diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Core/PrintfTests.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Core/PrintfTests.fs index 2cbb201bfe1..187fa62c60e 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Core/PrintfTests.fs +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Core/PrintfTests.fs @@ -45,6 +45,36 @@ type PrintfTests() = test "%10c" 'a' " a" test "%-10c" 'a' "a " + [] + member this.NumbersInDifferentBases() = + test "%10u" 123 " 123" + test "%-10u" 123 "123 " + test "%10B" 123 " 1111011" + test "%-10B" 123 "1111011 " + test "%10o" 123 " 173" + test "%-10o" 123 "173 " + test "%10x" 123 " 7b" + test "%-10x" 123 "7b " + test "%10X" 123 " 7B" + test "%-10X" 123 "7B " + + [] + member this.VariableWidth() = + Assert.AreEqual(" a", sprintf "%*c" 8 'a' ) + Assert.AreEqual("a ", sprintf "%-*c" 8 'a' ) + Assert.AreEqual(" abc", sprintf "%*s" 8 "abc") + Assert.AreEqual("abc ", sprintf "%-*s" 8 "abc") + Assert.AreEqual(" 123", sprintf "%*u" 8 123 ) + Assert.AreEqual("123 ", sprintf "%-*u" 8 123 ) + Assert.AreEqual(" 1111011", sprintf "%*B" 8 123 ) + Assert.AreEqual("1111011 ", sprintf "%-*B" 8 123 ) + Assert.AreEqual(" 173", sprintf "%*o" 8 123 ) + Assert.AreEqual("173 ", sprintf "%-*o" 8 123 ) + Assert.AreEqual(" 7b", sprintf "%*x" 8 123 ) + Assert.AreEqual("7b ", sprintf "%-*x" 8 123 ) + Assert.AreEqual(" 7B", sprintf "%*X" 8 123 ) + Assert.AreEqual("7B ", sprintf "%-*X" 8 123 ) + [] member _.``union case formatting`` () = Assert.AreEqual("CaseOne", sprintf "%A" CaseOne) diff --git a/tests/fsharp/Compiler/Language/StringInterpolation.fs b/tests/fsharp/Compiler/Language/StringInterpolation.fs index 284f55b1a52..6d41510b038 100644 --- a/tests/fsharp/Compiler/Language/StringInterpolation.fs +++ b/tests/fsharp/Compiler/Language/StringInterpolation.fs @@ -536,7 +536,19 @@ check "vcewweh22g" $"x = %A{s}" "x = \"sixsix\"" check "vcewweh20" $"x = %A{1}" "x = 1" """ - + [] + let ``%B fails for langVersion 5.0`` () = + CompilerAssert.TypeCheckWithErrorsAndOptions [| "--langversion:5.0" |] + """printf "%B" 10""" + [|(FSharpDiagnosticSeverity.Error, 3350, (1, 8, 1, 12), + "Feature 'binary formatting for integers' is not available in F# 5.0. Please use language version 'preview' or greater.")|] + [] + let ``%B succeeds for langVersion preview`` () = + CompilerAssert.CompileExeAndRunWithOptions [| "--langversion:preview" |] """ +let check msg a b = + if a = b then printfn "test case '%s' succeeded" msg else failwithf "test case '%s' failed, expected %A, got %A" msg b a +check "vcewweh22a" $"x = %B{19}" "x = 10011" + """ [] let ``String interpolation using list and array data`` () = @@ -860,4 +872,4 @@ let TripleInterpolatedInVerbatimInterpolated = $\"123{456}789{$\"\"\"012\"\"\"}3 CompilerAssert.TypeCheckWithErrorsAndOptions [| |] code [|(FSharpDiagnosticSeverity.Error, 39, (2, 14, 2, 17), - "The value or constructor 'foo' is not defined. Maybe you want one of the following:\n floor")|] \ No newline at end of file + "The value or constructor 'foo' is not defined. Maybe you want one of the following:\n floor")|] diff --git a/tests/fsharp/core/printf-interpolated/test.fsx b/tests/fsharp/core/printf-interpolated/test.fsx index 64e08fec66e..b1891f31ad9 100644 --- a/tests/fsharp/core/printf-interpolated/test.fsx +++ b/tests/fsharp/core/printf-interpolated/test.fsx @@ -41,8 +41,17 @@ let _ = test "cewoui2e" (lazy(sprintf $"%o{System.Int32.MinValue}" )) "200000000 let _ = test "cewoui2r" (lazy(sprintf $"%o{0xffffffff}" )) "37777777777" let _ = test "cewoui2t" (lazy(sprintf $"%o{System.Int32.MinValue+1}")) "20000000001" let _ = test "cewoui2y" (lazy(sprintf $"%o{System.Int32.MaxValue}")) "17777777777" - let _ = test "cewoui2u" (lazy(sprintf $"%o{-1}" )) "37777777777" +let _ = test "cewoui2aB" (lazy(sprintf $"%B{0}")) "0" +let _ = test "cewoui2bB" (lazy(sprintf $"%B{0}")) "0" +let _ = test "cewoui2cB" (lazy(sprintf $"%B{5}")) "101" +let _ = test "cewoui2qB" (lazy(sprintf $"%B{8}")) "1000" +let _ = test "cewoui2wB" (lazy(sprintf $"%B{15}")) "1111" +let _ = test "cewoui2eB" (lazy(sprintf $"%B{System.Int32.MinValue}" )) "10000000000000000000000000000000" +let _ = test "cewoui2rB" (lazy(sprintf $"%B{0xffffffff}" )) "11111111111111111111111111111111" +let _ = test "cewoui2tB" (lazy(sprintf $"%B{System.Int32.MinValue+1}")) "10000000000000000000000000000001" +let _ = test "cewoui2yB" (lazy(sprintf $"%B{System.Int32.MaxValue}")) "1111111111111111111111111111111" +let _ = test "cewoui2uB" (lazy(sprintf $"%B{-1}" )) "11111111111111111111111111111111" let f z = sprintf $"%o{z}" @@ -55,9 +64,21 @@ let _ = test "cewoui2h" (lazy(f System.Int32.MinValue)) "20000000000" let _ = test "cewoui2j" (lazy(f 0xffffffff)) "37777777777" let _ = test "cewoui2lk" (lazy(f (System.Int32.MinValue+1))) "20000000001" let _ = test "cewoui2l" (lazy(f System.Int32.MaxValue)) "17777777777" - let _ = test "cewoui212" (lazy(f (-1))) "37777777777" +let fB z = sprintf $"%B{z}" + +let _ = test "cewoui2aB" (lazy(fB 0)) "0" +let _ = test "cewoui2sB" (lazy(fB 0)) "0" +let _ = test "cewoui2dB" (lazy(fB 5)) "101" +let _ = test "cewoui2fB" (lazy(fB 8)) "1000" +let _ = test "cewoui2gB" (lazy(fB 15)) "1111" +let _ = test "cewoui2hB" (lazy(fB System.Int32.MinValue)) "10000000000000000000000000000000" +let _ = test "cewoui2jB" (lazy(fB 0xffffffff)) "11111111111111111111111111111111" +let _ = test "cewoui2lkB" (lazy(fB (System.Int32.MinValue+1))) "10000000000000000000000000000001" +let _ = test "cewoui2lB" (lazy(fB System.Int32.MaxValue)) "1111111111111111111111111111111" +let _ = test "cewoui212B" (lazy(fB (-1))) "11111111111111111111111111111111" + // check bprintf let _ = test "csd3oui2!" (lazy(let buf = new System.Text.StringBuilder() in ignore (bprintf buf $"%x{0}%x{1}"); buf.ToString())) "01" diff --git a/tests/fsharp/core/printf/test.fsx b/tests/fsharp/core/printf/test.fsx index af5673500f3..defd79d73bc 100644 --- a/tests/fsharp/core/printf/test.fsx +++ b/tests/fsharp/core/printf/test.fsx @@ -58,8 +58,22 @@ let _ = test "cewoui2e" (lazy(sprintf "%o" System.Int32.MinValue)) "20000000000" let _ = test "cewoui2r" (lazy(sprintf "%o" 0xffffffff)) "37777777777" let _ = test "cewoui2t" (lazy(sprintf "%o" (System.Int32.MinValue+1))) "20000000001" let _ = test "cewoui2y" (lazy(sprintf "%o" System.Int32.MaxValue)) "17777777777" - let _ = test "cewoui2u" (lazy(sprintf "%o" (-1))) "37777777777" +let _ = test "cewoui2i" (lazy(sprintf "%o" System.UInt64.MaxValue)) "1777777777777777777777" +let _ = test "cewoui2i" (lazy(sprintf "%o" System.Int64.MinValue)) "1000000000000000000000" + +let _ = test "cewoui2aB" (lazy(sprintf "%B" 0)) "0" +let _ = test "cewoui2bB" (lazy(sprintf "%B" 0)) "0" +let _ = test "cewoui2cB" (lazy(sprintf "%B" 5)) "101" +let _ = test "cewoui2qB" (lazy(sprintf "%B" 8)) "1000" +let _ = test "cewoui2wB" (lazy(sprintf "%B" 15)) "1111" +let _ = test "cewoui2eB" (lazy(sprintf "%B" System.Int32.MinValue)) "10000000000000000000000000000000" +let _ = test "cewoui2rB" (lazy(sprintf "%B" 0xffffffff)) "11111111111111111111111111111111" +let _ = test "cewoui2tB" (lazy(sprintf "%B" (System.Int32.MinValue+1))) "10000000000000000000000000000001" +let _ = test "cewoui2yB" (lazy(sprintf "%B" System.Int32.MaxValue)) "1111111111111111111111111111111" +let _ = test "cewoui2uB" (lazy(sprintf "%B" (-1))) "11111111111111111111111111111111" +let _ = test "cewoui2iB" (lazy(sprintf "%B" System.UInt64.MaxValue)) "1111111111111111111111111111111111111111111111111111111111111111" +let _ = test "cewoui2iB" (lazy(sprintf "%B" System.Int64.MinValue)) "1000000000000000000000000000000000000000000000000000000000000000" let f = sprintf "%o" @@ -72,9 +86,21 @@ let _ = test "cewoui2h" (lazy(f System.Int32.MinValue)) "20000000000" let _ = test "cewoui2j" (lazy(f 0xffffffff)) "37777777777" let _ = test "cewoui2lk" (lazy(f (System.Int32.MinValue+1))) "20000000001" let _ = test "cewoui2l" (lazy(f System.Int32.MaxValue)) "17777777777" - let _ = test "cewoui212" (lazy(f (-1))) "37777777777" +let fB = sprintf "%B" + +let _ = test "cewoui2a" (lazy(fB 0)) "0" +let _ = test "cewoui2s" (lazy(fB 0)) "0" +let _ = test "cewoui2d" (lazy(fB 5)) "101" +let _ = test "cewoui2f" (lazy(fB 8)) "1000" +let _ = test "cewoui2g" (lazy(fB 15)) "1111" +let _ = test "cewoui2h" (lazy(fB System.Int32.MinValue)) "10000000000000000000000000000000" +let _ = test "cewoui2j" (lazy(fB 0xffffffff)) "11111111111111111111111111111111" +let _ = test "cewoui2lk" (lazy(fB (System.Int32.MinValue+1))) "10000000000000000000000000000001" +let _ = test "cewoui2l" (lazy(fB System.Int32.MaxValue)) "1111111111111111111111111111111" +let _ = test "cewoui212" (lazy(fB (-1))) "11111111111111111111111111111111" + // Test nothing comes out until all arguments have been applied let _ = test "csd3oui2!" (lazy(let buf = new System.Text.StringBuilder() in ignore (bprintf buf "%x%x" 0); buf.ToString())) "" let _ = test "csd3oui2!" (lazy(let buf = new System.Text.StringBuilder() in ignore (bprintf buf "%x%x" 0 1); buf.ToString())) "01" @@ -89,6 +115,8 @@ let _ = test "cewoui2Z" (lazy(sprintf "%x" System.Int32.MinValue)) "80000000" let _ = test "cewoui2X" (lazy(sprintf "%x" 0xffffffff)) "ffffffff" let _ = test "cewoui2A" (lazy(sprintf "%x" (System.Int32.MinValue+1))) "80000001" let _ = test "cewoui2Q" (lazy(sprintf "%x" System.Int32.MaxValue)) "7fffffff" +let _ = test "cewoui2`" (lazy(sprintf "%x" System.UInt64.MaxValue)) "ffffffffffffffff" +let _ = test "cewoui2~" (lazy(sprintf "%x" System.Int64.MinValue)) "8000000000000000" let fx = sprintf "%x" let _ = test "cewoui2W" (lazy(fx 0)) "0" @@ -108,6 +136,8 @@ let _ = test "cewoui2v" (lazy(sprintf "%X" System.Int32.MinValue)) "80000000" let _ = test "cewoui2B" (lazy(sprintf "%X" 0xffffffff)) "FFFFFFFF" let _ = test "cewoui2N" (lazy(sprintf "%X" (System.Int32.MinValue+1))) "80000001" let _ = test "cewoui2M" (lazy(sprintf "%X" System.Int32.MaxValue)) "7FFFFFFF" +let _ = test "cewoui2," (lazy(sprintf "%X" System.UInt64.MaxValue)) "FFFFFFFFFFFFFFFF" +let _ = test "cewoui2." (lazy(sprintf "%X" System.Int64.MinValue)) "FFFFFFFFFFFFFFFF" let _ = test "cewou44a" (lazy(sprintf "%u" 0)) "0" let _ = test "cewou44b" (lazy(sprintf "%u" 5)) "5" @@ -117,6 +147,7 @@ let _ = test "cewou44e" (lazy(sprintf "%u" System.Int32.MinValue)) "2147483648" let _ = test "cewou44f" (lazy(sprintf "%u" 0xffffffff)) "4294967295" let _ = test "cewou44g" (lazy(sprintf "%u" (System.Int32.MinValue+1))) "2147483649" let _ = test "cewou44h" (lazy(sprintf "%u" System.Int32.MaxValue)) "2147483647" +let _ = test "cewou44i" (lazy(sprintf "%u" System.UInt64.MaxValue)) "18446744073709551615" let _ = test "cewou45a" (lazy(sprintf "%d" 0ul)) "0" let _ = test "cewou45b" (lazy(sprintf "%d" 5ul)) "5" diff --git a/tests/fsharp/tests.fs b/tests/fsharp/tests.fs index 253703752a7..edca7419f6a 100644 --- a/tests/fsharp/tests.fs +++ b/tests/fsharp/tests.fs @@ -196,7 +196,7 @@ module CoreTests = let ``letrec (mutrec variations part two) FSI_BASIC`` () = singleTestBuildAndRun "core/letrec-mutrec2" FSI_BASIC [] - let ``printf`` () = singleTestBuildAndRun "core/printf" FSC_BASIC + let ``printf`` () = singleTestBuildAndRunVersion "core/printf" FSC_BASIC "preview" [] let ``printf-interpolated`` () = singleTestBuildAndRunVersion "core/printf-interpolated" FSC_BASIC "preview" From 98e11ae6c8fa0ded00a805d33d42f55ddb4890c2 Mon Sep 17 00:00:00 2001 From: Vlad Zarytovskii Date: Thu, 27 May 2021 14:26:23 +0200 Subject: [PATCH 09/12] Various fixes to FS API + use streams by default, instead of ByteMemory (#11601) * Various fixes fixes for FileSystem API: fixes to fsi files, changed API to use streams instead of ByteMemory, since we use those more often. Some better disposing for streams and mmf * Made DefaultFielSystem members virtual, so only needed functions can be overriden. Added comment regarding zero-copy mmf vs regular file implementations. Changed a bunch of Directory and Path APIs to use Shims instead. --- src/fsharp/CompilerConfig.fs | 24 +- src/fsharp/CompilerImports.fs | 4 +- src/fsharp/CompilerOptions.fs | 2 +- .../FSharp.Compiler.Service.fsproj | 3 + src/fsharp/FxResolver.fs | 19 +- src/fsharp/LegacyMSBuildReferenceResolver.fs | 2 +- src/fsharp/ParseAndCheckInputs.fs | 2 +- src/fsharp/ScriptClosure.fs | 7 +- .../SimulatedMSBuildReferenceResolver.fs | 6 +- src/fsharp/XmlDoc.fs | 2 +- src/fsharp/absil/ilread.fs | 18 +- src/fsharp/absil/ilsupp.fs | 2 +- src/fsharp/absil/ilwrite.fs | 5 +- src/fsharp/absil/ilwritepdb.fs | 8 +- src/fsharp/fsi/fsi.fs | 4 +- src/fsharp/range.fs | 4 +- src/fsharp/service/service.fs | 3 +- src/fsharp/utils/FileSystem.fs | 324 +++++++++++------- src/fsharp/utils/FileSystem.fsi | 105 +++++- src/fsharp/utils/PathMap.fs | 4 +- .../SurfaceArea.netstandard.fs | 98 ++---- tests/FSharp.Test.Utilities/Compiler.fs | 4 +- tests/fsharp/TypeProviderTests.fs | 1 - tests/service/FileSystemTests.fs | 59 +--- tests/service/MultiProjectAnalysisTests.fs | 4 +- tests/service/ProjectAnalysisTests.fs | 8 +- 26 files changed, 400 insertions(+), 322 deletions(-) diff --git a/src/fsharp/CompilerConfig.fs b/src/fsharp/CompilerConfig.fs index 2417eae3dd6..4b4951e3010 100644 --- a/src/fsharp/CompilerConfig.fs +++ b/src/fsharp/CompilerConfig.fs @@ -138,7 +138,7 @@ type VersionFlag = if not(FileSystem.FileExistsShim s) then errorR(Error(FSComp.SR.buildInvalidVersionFile s, rangeStartup)); "0.0.0.0" else - use fs = FileSystem.OpenFileForReadShim(s).AsReadOnlyStream() + use fs = FileSystem.OpenFileForReadShim(s) use is = new StreamReader(fs) is.ReadLine() | VersionNone -> "0.0.0.0" @@ -752,7 +752,7 @@ type TcConfigBuilder = let absolutePath = ComputeMakePathAbsolute pathIncludedFrom path let ok = let existsOpt = - try Some(Directory.Exists absolutePath) + try Some(FileSystem.DirectoryExistsShim absolutePath) with e -> warning(Error(FSComp.SR.buildInvalidSearchDirectory path, m)); None match existsOpt with | Some exists -> @@ -1065,7 +1065,7 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = let clrRoot = tcConfig.MakePathAbsolute x yield clrRoot let clrFacades = Path.Combine(clrRoot, "Facades") - if Directory.Exists(clrFacades) then yield clrFacades + if FileSystem.DirectoryExistsShim(clrFacades) then yield clrFacades | None -> // "there is no really good notion of runtime directory on .NETCore" @@ -1084,13 +1084,13 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = // // In the current way of doing things, F# Interactive refers to implementation assemblies. yield runtimeRoot - if Directory.Exists runtimeRootFacades then + if FileSystem.DirectoryExistsShim runtimeRootFacades then yield runtimeRootFacades // System.Runtime.dll is in /usr/lib/mono/4.5/Facades - if Directory.Exists runtimeRootWPF then + if FileSystem.DirectoryExistsShim runtimeRootWPF then yield runtimeRootWPF // PresentationCore.dll is in C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF match tcConfig.FxResolver.GetFrameworkRefsPackDirectory() with - | Some path when Directory.Exists(path) -> + | Some path when FileSystem.DirectoryExistsShim(path) -> yield path | _ -> () @@ -1102,16 +1102,16 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = // On Mono, the default references come from the implementation assemblies. // This is because we have had trouble reliably using MSBuild APIs to compute DotNetFrameworkReferenceAssembliesRootDirectory on Mono. yield runtimeRoot - if Directory.Exists runtimeRootFacades then + if FileSystem.DirectoryExistsShim runtimeRootFacades then yield runtimeRootFacades // System.Runtime.dll is in /usr/lib/mono/4.5/Facades - if Directory.Exists runtimeRootWPF then + if FileSystem.DirectoryExistsShim runtimeRootWPF then yield runtimeRootWPF // PresentationCore.dll is in C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF // On Mono we also add a default reference to the 4.5-api and 4.5-api/Facades directories. let runtimeRootApi = runtimeRootWithoutSlash + "-api" let runtimeRootApiFacades = Path.Combine(runtimeRootApi, "Facades") - if Directory.Exists runtimeRootApi then + if FileSystem.DirectoryExistsShim runtimeRootApi then yield runtimeRootApi - if Directory.Exists runtimeRootApiFacades then + if FileSystem.DirectoryExistsShim runtimeRootApiFacades then yield runtimeRootApiFacades else #endif @@ -1122,10 +1122,10 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = let frameworkRootVersion = Path.Combine(frameworkRoot, tcConfig.targetFrameworkVersion) yield frameworkRootVersion let facades = Path.Combine(frameworkRootVersion, "Facades") - if Directory.Exists facades then + if FileSystem.DirectoryExistsShim facades then yield facades match tcConfig.FxResolver.GetFrameworkRefsPackDirectory() with - | Some path when Directory.Exists(path) -> + | Some path when FileSystem.DirectoryExistsShim(path) -> yield path | _ -> () ] diff --git a/src/fsharp/CompilerImports.fs b/src/fsharp/CompilerImports.fs index 6c0e2b0222a..f61f467c995 100644 --- a/src/fsharp/CompilerImports.fs +++ b/src/fsharp/CompilerImports.fs @@ -690,7 +690,7 @@ type RawFSharpAssemblyDataBackedByFileOnDisk (ilModule: ILModuleDef, ilAssemblyR let sigFileName = Path.ChangeExtension(filename, "sigdata") if not (FileSystem.FileExistsShim sigFileName) then error(Error(FSComp.SR.buildExpectedSigdataFile (FileSystem.GetFullPathShim sigFileName), m)) - [ (ilShortAssemName, fun () -> FileSystem.OpenFileForReadShim(sigFileName, shouldShadowCopy=true).AsReadOnly())] + [ (ilShortAssemName, fun () -> FileSystem.OpenFileForReadShim(sigFileName, useMemoryMappedFile=true, shouldShadowCopy=true).AsByteMemory().AsReadOnly())] else sigDataReaders sigDataReaders @@ -706,7 +706,7 @@ type RawFSharpAssemblyDataBackedByFileOnDisk (ilModule: ILModuleDef, ilAssemblyR let optDataFile = Path.ChangeExtension(filename, "optdata") if not (FileSystem.FileExistsShim optDataFile) then error(Error(FSComp.SR.buildExpectedFileAlongSideFSharpCore(optDataFile, FileSystem.GetFullPathShim optDataFile), m)) - [ (ilShortAssemName, (fun () -> FileSystem.OpenFileForReadShim(optDataFile, shouldShadowCopy=true).AsReadOnly()))] + [ (ilShortAssemName, (fun () -> FileSystem.OpenFileForReadShim(optDataFile, useMemoryMappedFile=true, shouldShadowCopy=true).AsByteMemory().AsReadOnly()))] else optDataReaders optDataReaders diff --git a/src/fsharp/CompilerOptions.fs b/src/fsharp/CompilerOptions.fs index 9d0c7dc6662..b04c13031ab 100644 --- a/src/fsharp/CompilerOptions.fs +++ b/src/fsharp/CompilerOptions.fs @@ -183,7 +183,7 @@ module ResponseFile = | s -> Some (ResponseFileLine.CompilerOptionSpec (s.Trim())) try - use stream = FileSystem.OpenFileForReadShim(path).AsReadOnlyStream() + use stream = FileSystem.OpenFileForReadShim(path) use reader = new StreamReader(stream, true) let data = seq { while not reader.EndOfStream do yield reader.ReadLine () } diff --git a/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj b/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj index 8d22cba56df..d9df9c7eae3 100644 --- a/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj +++ b/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj @@ -153,6 +153,9 @@ Utilities\illib.fs + + Utilities\FileSystem.fsi + Utilities\FileSystem.fs diff --git a/src/fsharp/FxResolver.fs b/src/fsharp/FxResolver.fs index a6e22e39cc3..9a1eb6a920d 100644 --- a/src/fsharp/FxResolver.fs +++ b/src/fsharp/FxResolver.fs @@ -88,7 +88,7 @@ type internal FxResolver(assumeDotNetFramework: bool, projectDir: string, useSdk | Some dotnetHostPath -> try let workingDir = - if Directory.Exists(projectDir) then + if FileSystem.DirectoryExistsShim(projectDir) then Some projectDir else None @@ -131,8 +131,8 @@ type internal FxResolver(assumeDotNetFramework: bool, projectDir: string, useSdk let sdksDir = match getDotnetHostDirectory() with | Some dotnetDir -> - let candidate = Path.GetFullPath(Path.Combine(dotnetDir, "sdk")) - if Directory.Exists(candidate) then Some candidate else None + let candidate = FileSystem.GetFullPathShim(Path.Combine(dotnetDir, "sdk")) + if FileSystem.DirectoryExistsShim(candidate) then Some candidate else None | None -> None match sdksDir with @@ -177,13 +177,14 @@ type internal FxResolver(assumeDotNetFramework: bool, projectDir: string, useSdk | Some dir -> try let dotnetConfigFile = Path.Combine(dir, "dotnet.runtimeconfig.json") - let dotnetConfig = FileSystem.OpenFileForReadShim(dotnetConfigFile).AsStream().ReadAllText() + use stream = FileSystem.OpenFileForReadShim(dotnetConfigFile) + let dotnetConfig = stream.ReadAllText() let pattern = "\"version\": \"" let startPos = dotnetConfig.IndexOf(pattern, StringComparison.OrdinalIgnoreCase) + pattern.Length let endPos = dotnetConfig.IndexOf("\"", startPos) let ver = dotnetConfig.[startPos..endPos-1] - let path = Path.GetFullPath(Path.Combine(dir, "..", "..", "shared", "Microsoft.NETCore.App", ver)) - if Directory.Exists(path) then + let path = FileSystem.GetFullPathShim(Path.Combine(dir, "..", "..", "shared", "Microsoft.NETCore.App", ver)) + if FileSystem.DirectoryExistsShim(path) then path, warnings else getRunningImplementationAssemblyDir(), warnings @@ -322,7 +323,8 @@ type internal FxResolver(assumeDotNetFramework: bool, projectDir: string, useSdk | asm -> let depsJsonPath = Path.ChangeExtension(asm.Location, "deps.json") if FileSystem.FileExistsShim(depsJsonPath) then - FileSystem.OpenFileForReadShim(depsJsonPath).AsReadOnlyStream().ReadAllText() + use stream = FileSystem.OpenFileForReadShim(depsJsonPath) + stream.ReadAllText() else "" with _ -> @@ -783,7 +785,8 @@ type internal FxResolver(assumeDotNetFramework: bool, projectDir: string, useSdk match sdkDir with | Some dir -> let dotnetConfigFile = Path.Combine(dir, "dotnet.runtimeconfig.json") - let dotnetConfig = FileSystem.OpenFileForReadShim(dotnetConfigFile).AsReadOnlyStream().ReadAllText() + use stream = FileSystem.OpenFileForReadShim(dotnetConfigFile) + let dotnetConfig = stream.ReadAllText() let pattern = "\"tfm\": \"" let startPos = dotnetConfig.IndexOf(pattern, StringComparison.OrdinalIgnoreCase) + pattern.Length let endPos = dotnetConfig.IndexOf("\"", startPos) diff --git a/src/fsharp/LegacyMSBuildReferenceResolver.fs b/src/fsharp/LegacyMSBuildReferenceResolver.fs index 9620d166786..ab60534c718 100644 --- a/src/fsharp/LegacyMSBuildReferenceResolver.fs +++ b/src/fsharp/LegacyMSBuildReferenceResolver.fs @@ -129,7 +129,7 @@ module FSharp.Compiler.CodeAnalysis.LegacyMSBuildReferenceResolver let v = if dotNetVersion.StartsWith("v") then dotNetVersion.Substring(1) else dotNetVersion let frameworkName = new System.Runtime.Versioning.FrameworkName(".NETFramework", new Version(v)) match ToolLocationHelper.GetPathToReferenceAssemblies(frameworkName) |> Seq.tryHead with - | Some p -> if Directory.Exists(p) then true else false + | Some p -> if FileSystem.DirectoryExistsShim(p) then true else false | None -> false with _ -> false else false diff --git a/src/fsharp/ParseAndCheckInputs.fs b/src/fsharp/ParseAndCheckInputs.fs index 64d0419cecb..33b2278c721 100644 --- a/src/fsharp/ParseAndCheckInputs.fs +++ b/src/fsharp/ParseAndCheckInputs.fs @@ -404,7 +404,7 @@ let checkInputFile (tcConfig: TcConfig) filename = let parseInputFileAux (tcConfig: TcConfig, lexResourceManager, conditionalCompilationDefines, filename, isLastCompiland, errorLogger, retryLocked) = // Get a stream reader for the file - use fileStream = FileSystem.OpenFileForReadShim(filename).AsStream() + use fileStream = FileSystem.OpenFileForReadShim(filename) use reader = fileStream.GetReader(tcConfig.inputCodePage, retryLocked) // Set up the LexBuffer for the file diff --git a/src/fsharp/ScriptClosure.fs b/src/fsharp/ScriptClosure.fs index 46b1b368d2f..c1907a5f145 100644 --- a/src/fsharp/ScriptClosure.fs +++ b/src/fsharp/ScriptClosure.fs @@ -188,7 +188,7 @@ module ScriptPreprocessClosure = let ClosureSourceOfFilename(filename, m, inputCodePage, parseRequired) = try let filename = FileSystem.GetFullPathShim filename - use stream = FileSystem.OpenFileForReadShim(filename).AsReadOnlyStream() + use stream = FileSystem.OpenFileForReadShim(filename) use reader = match inputCodePage with | None -> new StreamReader(stream, true) @@ -270,7 +270,7 @@ module ScriptPreprocessClosure = for line in result.StdOut do Console.Out.WriteLine(line) for line in result.StdError do Console.Error.WriteLine(line) - packageReferences.[m] <- [ for script in result.SourceFiles do yield! FileSystem.OpenFileForReadShim(script).AsReadOnlyStream().ReadLines() ] + packageReferences.[m] <- [ for script in result.SourceFiles do yield! FileSystem.OpenFileForReadShim(script).ReadLines() ] if not (Seq.isEmpty result.Roots) then let tcConfigB = tcConfig.CloneToBuilder() for folder in result.Roots do @@ -285,7 +285,8 @@ module ScriptPreprocessClosure = tcConfig <- TcConfig.Create(tcConfigB, validate = false) for script in result.SourceFiles do - let scriptText = FileSystem.OpenFileForReadShim(script).AsReadOnlyStream().ReadAllText() + use stream = FileSystem.OpenFileForReadShim(script) + let scriptText = stream.ReadAllText() loadScripts.Add script |> ignore let iSourceText = SourceText.ofString scriptText yield! loop (ClosureSource(script, m, iSourceText, true)) diff --git a/src/fsharp/SimulatedMSBuildReferenceResolver.fs b/src/fsharp/SimulatedMSBuildReferenceResolver.fs index 470beb6a150..c7fd441ded2 100644 --- a/src/fsharp/SimulatedMSBuildReferenceResolver.fs +++ b/src/fsharp/SimulatedMSBuildReferenceResolver.fs @@ -87,7 +87,7 @@ let private SimulatedMSBuildResolver = member x.HighestInstalledNetFrameworkVersion() = let root = x.DotNetFrameworkReferenceAssembliesRootDirectory - let fwOpt = SupportedDesktopFrameworkVersions |> Seq.tryFind(fun fw -> Directory.Exists(Path.Combine(root, fw) )) + let fwOpt = SupportedDesktopFrameworkVersions |> Seq.tryFind(fun fw -> FileSystem.DirectoryExistsShim(Path.Combine(root, fw) )) match fwOpt with | Some fw -> fw | None -> "v4.5" @@ -201,7 +201,7 @@ let private SimulatedMSBuildResolver = match n.Version, n.GetPublicKeyToken() with | null, _ | _, null -> let options = - [ if Directory.Exists gac then + [ if FileSystem.DirectoryExistsShim gac then for gacDir in FileSystem.EnumerateDirectoriesShim gac do let assemblyDir = Path.Combine(gacDir, n.Name) if FileSystem.DirectoryExistsShim assemblyDir then @@ -216,7 +216,7 @@ let private SimulatedMSBuildResolver = |> function None -> () | Some p -> success p | v, tok -> - if Directory.Exists gac then + if FileSystem.DirectoryExistsShim gac then for gacDir in Directory.EnumerateDirectories gac do //printfn "searching GAC directory: %s" gacDir let assemblyDir = Path.Combine(gacDir, n.Name) diff --git a/src/fsharp/XmlDoc.fs b/src/fsharp/XmlDoc.fs index a6d719a31da..3236e7c2f66 100644 --- a/src/fsharp/XmlDoc.fs +++ b/src/fsharp/XmlDoc.fs @@ -265,7 +265,7 @@ type XmlDocumentationInfo private (tryGetXmlDocument: unit -> XmlDocument option | Some doc -> Some doc | _ -> let doc = XmlDocument() - use xmlStream = FileSystem.OpenFileForReadShim(xmlFileName).AsStream() + use xmlStream = FileSystem.OpenFileForReadShim(xmlFileName) doc.Load(xmlStream) cache.Put((), cacheKey, doc) Some doc diff --git a/src/fsharp/absil/ilread.fs b/src/fsharp/absil/ilread.fs index dab6faf14ea..63b0c684a4c 100644 --- a/src/fsharp/absil/ilread.fs +++ b/src/fsharp/absil/ilread.fs @@ -205,9 +205,10 @@ type WeakByteFile(fileName: string, chunk: (int * int) option) = error (Error (FSComp.SR.ilreadFileChanged fileName, range0)) let bytes = + use stream = FileSystem.OpenFileForReadShim(fileName) match chunk with - | None -> FileSystem.OpenFileForReadShim(fileName).ReadAllBytes() - | Some(start, length) -> FileSystem.OpenFileForReadShim(fileName).ReadBytes(start, length) + | None -> stream.ReadAllBytes() + | Some(start, length) -> stream.ReadBytes(start, length) tg <- bytes @@ -3905,14 +3906,16 @@ let createByteFileChunk opts fileName chunk = WeakByteFile(fileName, chunk) :> BinaryFile else let bytes = + use stream = FileSystem.OpenFileForReadShim(fileName) match chunk with - | None -> FileSystem.OpenFileForReadShim(fileName).ReadAllBytes() - | Some(start, length) -> FileSystem.OpenFileForReadShim(fileName).ReadBytes(start, length) + | None -> stream.ReadAllBytes() + | Some(start, length) -> stream.ReadBytes(start, length) ByteFile(fileName, bytes) :> BinaryFile let createMemoryMapFile fileName = - let byteMem = FileSystem.OpenFileForReadShim(fileName, useMemoryMappedFile = true) + let stream = FileSystem.OpenFileForReadShim(fileName, useMemoryMappedFile = true) + let byteMem = stream.AsByteMemory() let safeHolder = { new obj() with @@ -3921,7 +3924,7 @@ let createMemoryMapFile fileName = interface IDisposable with member x.Dispose() = GC.SuppressFinalize x - byteMem.AsStream().Dispose() + stream.Dispose() stats.memoryMapFileClosedCount <- stats.memoryMapFileClosedCount + 1 } stats.memoryMapFileOpenedCount <- stats.memoryMapFileOpenedCount + 1 @@ -4037,7 +4040,8 @@ let OpenILModuleReader fileName opts = // still use an in-memory ByteFile let pefile = if not runningOnMono && (alwaysMemoryMapFSC || stableFileHeuristicApplies fullPath) then - ByteMemoryFile(fullPath, FileSystem.OpenFileForReadShim(fullPath)) :> BinaryFile + let _, pefile = createMemoryMapFile fullPath + pefile else createByteFileChunk opts fullPath None diff --git a/src/fsharp/absil/ilsupp.fs b/src/fsharp/absil/ilsupp.fs index e8b0d84d103..fa77befa8d3 100644 --- a/src/fsharp/absil/ilsupp.fs +++ b/src/fsharp/absil/ilsupp.fs @@ -931,7 +931,7 @@ let hashSizeOfMD5 = 16 // In this case, catch the failure, and not set a checksum. let internal setCheckSum (url: string, writer: ISymUnmanagedDocumentWriter) = try - use file = FileSystem.OpenFileForReadShim(url).AsReadOnlyStream() + use file = FileSystem.OpenFileForReadShim(url) use md5 = System.Security.Cryptography.MD5.Create() let checkSum = md5.ComputeHash file if (checkSum.Length = hashSizeOfMD5) then diff --git a/src/fsharp/absil/ilwrite.fs b/src/fsharp/absil/ilwrite.fs index 7fab0d0ae95..6bb374edad4 100644 --- a/src/fsharp/absil/ilwrite.fs +++ b/src/fsharp/absil/ilwrite.fs @@ -3720,7 +3720,8 @@ and writeBinaryAndReportMappingsAux (stream: Stream, leaveStreamOpen: bool, resources |> List.map (function | ILNativeResource.Out bytes -> bytes | ILNativeResource.In (fileName, linkedResourceBase, start, len) -> - let linkedResource = FileSystem.OpenFileForReadShim(fileName).ReadBytes(start, len) + use stream = FileSystem.OpenFileForReadShim(fileName) + let linkedResource = stream.ReadBytes(start, len) unlinkResource linkedResourceBase linkedResource) begin @@ -4208,7 +4209,7 @@ and writePdb (dumpDebugInfo, showTimes, portablePDB, embeddedPDB, pdbfile, outfi reportTime showTimes "Generate PDB Info" // Now we have the debug data we can go back and fill in the debug directory in the image - let fs2 = FileSystem.OpenFileForWriteShim(outfile, FileMode.Open, FileAccess.Write, FileShare.Read) + use fs2 = FileSystem.OpenFileForWriteShim(outfile, FileMode.Open, FileAccess.Write, FileShare.Read) let os2 = new BinaryWriter(fs2) try // write the IMAGE_DEBUG_DIRECTORY diff --git a/src/fsharp/absil/ilwritepdb.fs b/src/fsharp/absil/ilwritepdb.fs index f0648d3caf4..a2bc08dd470 100644 --- a/src/fsharp/absil/ilwritepdb.fs +++ b/src/fsharp/absil/ilwritepdb.fs @@ -135,7 +135,7 @@ let guidSha2 = Guid("8829d00f-11b8-4213-878b-770e8597ac16") let checkSum (url: string) (checksumAlgorithm: HashAlgorithm) = try - use file = FileSystem.OpenFileForReadShim(url).AsReadOnlyStream() + use file = FileSystem.OpenFileForReadShim(url) let guid, alg = match checksumAlgorithm with | HashAlgorithm.Sha1 -> guidSha1, System.Security.Cryptography.SHA1.Create() :> System.Security.Cryptography.HashAlgorithm @@ -310,7 +310,7 @@ let generatePortablePdb (embedAllSource: bool) (embedSourceList: string list) (s if not embedAllSource && not isInList || not (FileSystem.FileExistsShim file) then None else - use stream = FileSystem.OpenFileForReadShim(file).AsReadOnlyStream() + use stream = FileSystem.OpenFileForReadShim(file) let length64 = stream.Length if length64 > int64 (Int32.MaxValue) then raise (new IOException("File is too long")) @@ -355,8 +355,8 @@ let generatePortablePdb (embedAllSource: bool) (embedSourceList: string list) (s index.Add(doc.File, handle) if not (String.IsNullOrWhiteSpace sourceLink) then - let fs = FileSystem.OpenFileForReadShim(sourceLink).AsReadOnlyStream() - let ms = new MemoryStream() + use fs = FileSystem.OpenFileForReadShim(sourceLink) + use ms = new MemoryStream() fs.CopyTo ms metadata.AddCustomDebugInformation( ModuleDefinitionHandle.op_Implicit(EntityHandle.ModuleDefinition), diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index 830bfab745a..bb567989e1a 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -2131,7 +2131,7 @@ type internal FsiInteractionProcessor let ChangeDirectory (path:string) m = let tcConfig = TcConfig.Create(tcConfigB,validate=false) let path = tcConfig.MakePathAbsolute path - if Directory.Exists(path) then + if FileSystem.DirectoryExistsShim(path) then tcConfigB.implicitIncludeDir <- path else error(Error(FSIstrings.SR.fsiDirectoryDoesNotExist(path),m)) @@ -2472,7 +2472,7 @@ type internal FsiInteractionProcessor // An included script file may contain maybe several interaction blocks. // We repeatedly parse and process these, until an error occurs. - use fileStream = FileSystem.OpenFileForReadShim(sourceFile).AsStream() + use fileStream = FileSystem.OpenFileForReadShim(sourceFile) use reader = fileStream.GetReader(tcConfigB.inputCodePage, false) let tokenizer = fsiStdinLexerProvider.CreateIncludedScriptLexer (sourceFile, reader, errorLogger) diff --git a/src/fsharp/range.fs b/src/fsharp/range.fs index 48f85e53f36..690420ba7e5 100755 --- a/src/fsharp/range.fs +++ b/src/fsharp/range.fs @@ -259,7 +259,7 @@ type Range(code1:int64, code2: int64) = if FileSystem.IsInvalidPathShim r.FileName then "path invalid: " + r.FileName elif not (FileSystem.FileExistsShim r.FileName) then "non existing file: " + r.FileName else - FileSystem.OpenFileForReadShim(r.FileName).AsStream().ReadLines() + FileSystem.OpenFileForReadShim(r.FileName).ReadLines() |> Seq.skip (r.StartLine - 1) |> Seq.take (r.EndLine - r.StartLine + 1) |> String.concat "\n" @@ -391,7 +391,7 @@ module Range = let mkFirstLineOfFile (file: string) = try - let lines = FileSystem.OpenFileForReadShim(file).AsStream().ReadLines() |> Seq.indexed + let lines = FileSystem.OpenFileForReadShim(file).ReadLines() |> Seq.indexed let nonWhiteLine = lines |> Seq.tryFind (fun (_,s) -> not (String.IsNullOrWhiteSpace s)) match nonWhiteLine with | Some (i,s) -> mkRange file (mkPos (i+1) 0) (mkPos (i+1) s.Length) diff --git a/src/fsharp/service/service.fs b/src/fsharp/service/service.fs index d3b4d8043e5..4a65f6ca1a1 100644 --- a/src/fsharp/service/service.fs +++ b/src/fsharp/service/service.fs @@ -23,6 +23,7 @@ open FSharp.Compiler.DependencyManager open FSharp.Compiler.Diagnostics open FSharp.Compiler.Driver open FSharp.Compiler.ErrorLogger +open FSharp.Compiler.IO open FSharp.Compiler.ParseAndCheckInputs open FSharp.Compiler.ScriptClosure open FSharp.Compiler.Symbols @@ -1214,7 +1215,7 @@ type FSharpChecker(legacyReferenceResolver, let debugInfo = defaultArg debug false let noframework = defaultArg noframework false - let location = Path.Combine(Path.GetTempPath(),"test"+string(hash assemblyName)) + let location = Path.Combine(FileSystem.GetTempPathShim(),"test"+string(hash assemblyName)) try Directory.CreateDirectory(location) |> ignore with _ -> () let outFile = Path.Combine(location, assemblyName + ".dll") diff --git a/src/fsharp/utils/FileSystem.fs b/src/fsharp/utils/FileSystem.fs index 81f31d5dc4f..dd1de9a6b2f 100644 --- a/src/fsharp/utils/FileSystem.fs +++ b/src/fsharp/utils/FileSystem.fs @@ -372,13 +372,13 @@ type DefaultAssemblyLoader() = [] type IFileSystem = abstract AssemblyLoader: IAssemblyLoader - abstract OpenFileForReadShim: filePath: string * ?useMemoryMappedFile: bool * ?shouldShadowCopy: bool -> ByteMemory + abstract OpenFileForReadShim: filePath: string * ?useMemoryMappedFile: bool * ?shouldShadowCopy: bool -> Stream abstract OpenFileForWriteShim: filePath: string * ?fileMode: FileMode * ?fileAccess: FileAccess * ?fileShare: FileShare -> Stream abstract GetFullPathShim: fileName: string -> string abstract GetFullFilePathInDirectoryShim: dir: string -> fileName: string -> string abstract IsPathRootedShim: path: string -> bool abstract NormalizePathShim: path: string -> string - abstract IsInvalidPathShim: filename: string -> bool + abstract IsInvalidPathShim: path: string -> bool abstract GetTempPathShim: unit -> string abstract GetDirectoryNameShim: path: string -> string abstract GetLastWriteTimeShim: fileName: string -> DateTime @@ -395,153 +395,186 @@ type IFileSystem = [] type DefaultFileSystem() as this = - interface IFileSystem with - member _.AssemblyLoader = DefaultAssemblyLoader() :> IAssemblyLoader + abstract AssemblyLoader : IAssemblyLoader + default _.AssemblyLoader = DefaultAssemblyLoader() :> IAssemblyLoader + + abstract OpenFileForReadShim: filePath: string * ?useMemoryMappedFile: bool * ?shouldShadowCopy: bool -> Stream + default _.OpenFileForReadShim(filePath: string, ?useMemoryMappedFile: bool, ?shouldShadowCopy: bool) : Stream = + let fileMode = FileMode.Open + let fileAccess = FileAccess.Read + let fileShare = FileShare.Delete ||| FileShare.ReadWrite + let shouldShadowCopy = defaultArg shouldShadowCopy false + let useMemoryMappedFile = defaultArg useMemoryMappedFile false + let fileStream = new FileStream(filePath, fileMode, fileAccess, fileShare) + let length = fileStream.Length + + // We want to use mmaped files only when: + // - Opening large binary files (no need to use for source or resource files really) + // - Running on mono, since its MemoryMappedFile implementation throws when "mapName" is not provided (is null). + // (See: https://github.com/mono/mono/issues/10245) + + if runningOnMono || (not useMemoryMappedFile) then + fileStream :> Stream + else + use mmf = + if shouldShadowCopy then + let mmf = + MemoryMappedFile.CreateNew( + null, + length, + MemoryMappedFileAccess.Read, + MemoryMappedFileOptions.None, + HandleInheritability.None) + use stream = mmf.CreateViewStream(0L, length, MemoryMappedFileAccess.Read) + fileStream.CopyTo(stream) + fileStream.Dispose() + mmf + else + MemoryMappedFile.CreateFromFile( + fileStream, + null, + length, + MemoryMappedFileAccess.Read, + HandleInheritability.None, + leaveOpen=false) + let stream = mmf.CreateViewStream(0L, length, MemoryMappedFileAccess.Read) + if not stream.CanRead then + invalidOp "Cannot read file" + stream :> Stream - member this.OpenFileForReadShim(filePath: string, ?useMemoryMappedFile: bool, ?shouldShadowCopy: bool) : ByteMemory = - let fileMode = FileMode.Open - let fileAccess = FileAccess.Read - let fileShare = FileShare.Delete ||| FileShare.ReadWrite - let shouldShadowCopy = defaultArg shouldShadowCopy false - let useMemoryMappedFile = defaultArg useMemoryMappedFile false + abstract OpenFileForWriteShim: filePath: string * ?fileMode: FileMode * ?fileAccess: FileAccess * ?fileShare: FileShare -> Stream + default _.OpenFileForWriteShim(filePath: string, ?fileMode: FileMode, ?fileAccess: FileAccess, ?fileShare: FileShare) : Stream = + let fileMode = defaultArg fileMode FileMode.OpenOrCreate + let fileAccess = defaultArg fileAccess FileAccess.ReadWrite + let fileShare = defaultArg fileShare FileShare.Delete ||| FileShare.ReadWrite - let fileStream = new FileStream(filePath, fileMode, fileAccess, fileShare) - let length = fileStream.Length + new FileStream(filePath, fileMode, fileAccess, fileShare) :> Stream - // We want to use mmaped files only when: - // - Opening large binary files (no need to use for source or resource files really) - // - Running on mono, since its MemoryMappedFile implementation throws when "mapName" is not provided (is null). - // (See: https://github.com/mono/mono/issues/10245) - if runningOnMono || (not useMemoryMappedFile) then - let bytes = File.ReadAllBytes filePath - let byteArrayMemory = if bytes.Length = 0 then ByteArrayMemory([||], 0, 0) else ByteArrayMemory(bytes, 0, bytes.Length) - byteArrayMemory :> ByteMemory + abstract GetFullPathShim: fileName: string -> string + default _.GetFullPathShim (fileName: string) = Path.GetFullPath fileName + + abstract GetFullFilePathInDirectoryShim: dir: string -> fileName: string -> string + default this.GetFullFilePathInDirectoryShim (dir: string) (fileName: string) = + let p = if (this :> IFileSystem).IsPathRootedShim(fileName) then fileName else Path.Combine(dir, fileName) + try (this :> IFileSystem).GetFullPathShim(p) with + | :? ArgumentException + | :? ArgumentNullException + | :? NotSupportedException + | :? PathTooLongException + | :? System.Security.SecurityException -> p + + abstract IsPathRootedShim: path: string -> bool + default _.IsPathRootedShim (path: string) = Path.IsPathRooted path + + abstract NormalizePathShim: path: string -> string + default _.NormalizePathShim (path: string) = + try + let ifs = this :> IFileSystem + if ifs.IsPathRootedShim path then + ifs.GetFullPathShim path else - let mmf, viewStream, length = - let mmf = - if shouldShadowCopy then - let mmf = - MemoryMappedFile.CreateNew( - null, - length, - MemoryMappedFileAccess.Read, - MemoryMappedFileOptions.None, - HandleInheritability.None) - use stream = mmf.CreateViewStream(0L, length, MemoryMappedFileAccess.Read) - fileStream.CopyTo(stream) - fileStream.Dispose() - mmf - else - MemoryMappedFile.CreateFromFile( - fileStream, - null, - length, - MemoryMappedFileAccess.Read, - HandleInheritability.None, - leaveOpen=false) - mmf, mmf.CreateViewStream(0L, length, MemoryMappedFileAccess.Read), length - - if not viewStream.CanRead then - invalidOp "Cannot read file" + path + with _ -> path - let safeHolder = - { new obj() with - override x.Finalize() = - (x :?> IDisposable).Dispose() - interface IDisposable with - member x.Dispose() = - GC.SuppressFinalize x - viewStream.Dispose() - mmf.SafeMemoryMappedFileHandle.Close() - mmf.Dispose() - fileStream.Dispose() } + abstract IsInvalidPathShim: path: string -> bool + default _.IsInvalidPathShim(path: string) = + let isInvalidPath(p: string) = + String.IsNullOrEmpty p || p.IndexOfAny(Path.GetInvalidPathChars()) <> -1 - RawByteMemory( - NativePtr.ofNativeInt (viewStream.SafeMemoryMappedViewHandle.DangerousGetHandle()), - int length, - safeHolder) :> ByteMemory + let isInvalidFilename(p: string) = + String.IsNullOrEmpty p || p.IndexOfAny(Path.GetInvalidFileNameChars()) <> -1 - member _.OpenFileForWriteShim(filePath: string, ?fileMode: FileMode, ?fileAccess: FileAccess, ?fileShare: FileShare) : Stream = - let fileMode = defaultArg fileMode FileMode.OpenOrCreate - let fileAccess = defaultArg fileAccess FileAccess.ReadWrite - let fileShare = defaultArg fileShare FileShare.Delete ||| FileShare.ReadWrite + let isInvalidDirectory(d: string) = + d=null || d.IndexOfAny(Path.GetInvalidPathChars()) <> -1 - new FileStream(filePath, fileMode, fileAccess, fileShare) :> Stream + isInvalidPath path || + let directory = Path.GetDirectoryName path + let filename = Path.GetFileName path + isInvalidDirectory directory || isInvalidFilename filename - member _.GetFullPathShim (fileName: string) = Path.GetFullPath fileName + abstract GetTempPathShim: unit -> string + default _.GetTempPathShim() = Path.GetTempPath() - member _.IsPathRootedShim (path: string) = Path.IsPathRooted path + abstract GetDirectoryNameShim: path: string -> string + default _.GetDirectoryNameShim(path:string) = + FileSystemUtils.checkPathForIllegalChars path + if path = "" then "." + else + match Path.GetDirectoryName(path) with + | null -> if (this :> IFileSystem).IsPathRootedShim(path) then path else "." + | res -> if res = "" then "." else res - member _.NormalizePathShim (path: string) = - try - let ifs = this :> IFileSystem - if ifs.IsPathRootedShim path then - ifs.GetFullPathShim path - else - path - with _ -> path - - member this.GetFullFilePathInDirectoryShim (dir: string) (fileName: string) = - let p = if (this :> IFileSystem).IsPathRootedShim(fileName) then fileName else Path.Combine(dir, fileName) - try (this :> IFileSystem).GetFullPathShim(p) with - | :? ArgumentException - | :? ArgumentNullException - | :? NotSupportedException - | :? PathTooLongException - | :? System.Security.SecurityException -> p - - member _.IsInvalidPathShim(path: string) = - let isInvalidPath(p: string) = - String.IsNullOrEmpty p || p.IndexOfAny(Path.GetInvalidPathChars()) <> -1 - - let isInvalidFilename(p: string) = - String.IsNullOrEmpty p || p.IndexOfAny(Path.GetInvalidFileNameChars()) <> -1 - - let isInvalidDirectory(d: string) = - d=null || d.IndexOfAny(Path.GetInvalidPathChars()) <> -1 - - isInvalidPath path || - let directory = Path.GetDirectoryName path - let filename = Path.GetFileName path - isInvalidDirectory directory || isInvalidFilename filename - - member _.GetTempPathShim() = Path.GetTempPath() - - member _.GetDirectoryNameShim(s:string) = - FileSystemUtils.checkPathForIllegalChars s - if s = "" then "." - else - match Path.GetDirectoryName(s) with - | null -> if (this :> IFileSystem).IsPathRootedShim(s) then s else "." - | res -> if res = "" then "." else res + abstract GetLastWriteTimeShim: fileName: string -> DateTime + default _.GetLastWriteTimeShim (fileName: string) = File.GetLastWriteTimeUtc fileName - member _.GetLastWriteTimeShim (fileName: string) = File.GetLastWriteTimeUtc fileName + abstract GetCreationTimeShim: path: string -> DateTime + default _.GetCreationTimeShim (path: string) = File.GetCreationTimeUtc path - member _.GetCreationTimeShim (path: string) = File.GetCreationTimeUtc path + abstract CopyShim: src: string * dest: string * overwrite: bool -> unit + default _.CopyShim (src: string, dest: string, overwrite: bool) = File.Copy(src, dest, overwrite) - member _.CopyShim (src: string, dest: string, overwrite: bool) = File.Copy(src, dest, overwrite) + abstract FileExistsShim: fileName: string -> bool + default _.FileExistsShim (fileName: string) = File.Exists fileName - member _.FileExistsShim (fileName: string) = File.Exists fileName + abstract FileDeleteShim: fileName: string -> unit + default _.FileDeleteShim (fileName: string) = File.Delete fileName - member _.FileDeleteShim (fileName: string) = File.Delete fileName + abstract DirectoryCreateShim: path: string -> DirectoryInfo + default _.DirectoryCreateShim (path: string) = Directory.CreateDirectory path - member _.DirectoryCreateShim (path: string) = Directory.CreateDirectory path + abstract DirectoryExistsShim: path: string -> bool + default _.DirectoryExistsShim (path: string) = Directory.Exists path - member _.DirectoryExistsShim (path: string) = Directory.Exists path + abstract DirectoryDeleteShim: path: string -> unit + default _.DirectoryDeleteShim (path: string) = Directory.Delete path - member _.DirectoryDeleteShim (path: string) = Directory.Delete path + abstract EnumerateFilesShim: path: string * pattern: string -> string seq + default _.EnumerateFilesShim(path: string, pattern: string) = Directory.EnumerateFiles(path, pattern) - member _.EnumerateFilesShim(path: string, pattern: string) = Directory.EnumerateFiles(path, pattern) + abstract EnumerateDirectoriesShim: path: string -> string seq + default _.EnumerateDirectoriesShim(path: string) = Directory.EnumerateDirectories(path) + + abstract IsStableFileHeuristic: fileName: string -> bool + default _.IsStableFileHeuristic (fileName: string) = + let directory = Path.GetDirectoryName fileName + directory.Contains("Reference Assemblies/") || + directory.Contains("Reference Assemblies\\") || + directory.Contains("packages/") || + directory.Contains("packages\\") || + directory.Contains("lib/mono/") + + interface IFileSystem with + member _.AssemblyLoader = this.AssemblyLoader - member _.EnumerateDirectoriesShim(path: string) = Directory.EnumerateDirectories(path) + member _.OpenFileForReadShim(filePath: string, ?useMemoryMappedFile: bool, ?shouldShadowCopy: bool) : Stream = + let shouldShadowCopy = defaultArg shouldShadowCopy false + let useMemoryMappedFile = defaultArg useMemoryMappedFile false + this.OpenFileForReadShim(filePath, useMemoryMappedFile, shouldShadowCopy) - member _.IsStableFileHeuristic (fileName: string) = - let directory = Path.GetDirectoryName fileName - directory.Contains("Reference Assemblies/") || - directory.Contains("Reference Assemblies\\") || - directory.Contains("packages/") || - directory.Contains("packages\\") || - directory.Contains("lib/mono/") + member _.OpenFileForWriteShim(filePath: string, ?fileMode: FileMode, ?fileAccess: FileAccess, ?fileShare: FileShare) : Stream = + let fileMode = defaultArg fileMode FileMode.OpenOrCreate + let fileAccess = defaultArg fileAccess FileAccess.ReadWrite + let fileShare = defaultArg fileShare FileShare.Delete ||| FileShare.ReadWrite + this.OpenFileForWriteShim(filePath, fileMode, fileAccess, fileShare) + + member _.GetFullPathShim (fileName: string) = this.GetFullPathShim fileName + member _.GetFullFilePathInDirectoryShim (dir: string) (fileName: string) = this.GetFullFilePathInDirectoryShim dir fileName + member _.IsPathRootedShim (path: string) = this.IsPathRootedShim path + member _.NormalizePathShim (path: string) = this.NormalizePathShim path + member _.IsInvalidPathShim(path: string) = this.IsInvalidPathShim path + member _.GetTempPathShim() = this.GetTempPathShim() + member _.GetDirectoryNameShim(s:string) = this.GetDirectoryNameShim s + member _.GetLastWriteTimeShim (fileName: string) = this.GetLastWriteTimeShim fileName + member _.GetCreationTimeShim (path: string) = this.GetCreationTimeShim path + member _.CopyShim (src: string, dest: string, overwrite: bool) = this.CopyShim(src, dest, overwrite) + member _.FileExistsShim (fileName: string) = this.FileExistsShim fileName + member _.FileDeleteShim (fileName: string) = this.FileDeleteShim fileName + member _.DirectoryCreateShim (path: string) = this.DirectoryCreateShim path + member _.DirectoryExistsShim (path: string) = this.DirectoryExistsShim path + member _.DirectoryDeleteShim (path: string) = this.DirectoryDeleteShim path + member _.EnumerateFilesShim(path: string, pattern: string) = this.EnumerateFilesShim(path, pattern) + member _.EnumerateDirectoriesShim(path: string) = this.EnumerateDirectoriesShim path + member _.IsStableFileHeuristic (fileName: string) = this.IsStableFileHeuristic fileName [] module public StreamExtensions = @@ -588,6 +621,19 @@ module public StreamExtensions = reraise() getSource 0 + member s.ReadBytes (start, len) = + s.Seek(int64 start, SeekOrigin.Begin) |> ignore + let buffer = Array.zeroCreate len + let mutable n = 0 + while n < len do + n <- n + s.Read(buffer, n, len-n) + buffer + + member s.ReadAllBytes() = + use reader = new BinaryReader(s) + let count = (int s.Length) + reader.ReadBytes(count) + member s.ReadAllText(?encoding: Encoding) = let encoding = defaultArg encoding Encoding.UTF8 use sr = new StreamReader(s, encoding, true) @@ -604,6 +650,30 @@ module public StreamExtensions = let encoding = defaultArg encoding Encoding.UTF8 s.ReadLines(encoding) |> Seq.toArray + /// If we are working with the view stream from mmf, we wrap it in RawByteMemory (which does zero copy, bu just using handle from the views stream). + /// However, when we use any other stream (FileStream, MemoryStream, etc) - we just read everything from it and expose via ByteArrayMemory. + member s.AsByteMemory() : ByteMemory = + match s with + | :? MemoryMappedViewStream as mmvs -> + let safeHolder = + { new obj() with + override x.Finalize() = + (x :?> IDisposable).Dispose() + interface IDisposable with + member x.Dispose() = + GC.SuppressFinalize x + mmvs.Dispose() } + let length = mmvs.Length + RawByteMemory( + NativePtr.ofNativeInt (mmvs.SafeMemoryMappedViewHandle.DangerousGetHandle()), + int length, + safeHolder) :> ByteMemory + + | _ -> + let bytes = s.ReadAllBytes() + let byteArrayMemory = if bytes.Length = 0 then ByteArrayMemory([||], 0, 0) else ByteArrayMemory(bytes, 0, bytes.Length) + byteArrayMemory :> ByteMemory + [] module public FileSystemAutoOpens = /// The global hook into the file system diff --git a/src/fsharp/utils/FileSystem.fsi b/src/fsharp/utils/FileSystem.fsi index 58a426091d8..37c2b1a66b1 100644 --- a/src/fsharp/utils/FileSystem.fsi +++ b/src/fsharp/utils/FileSystem.fsi @@ -4,7 +4,12 @@ namespace FSharp.Compiler.IO open System open System.IO +open System.IO.MemoryMappedFiles open System.Reflection +open System.Runtime.InteropServices +open System.Text + +open FSharp.NativeInterop open Internal.Utilities.Library @@ -25,12 +30,14 @@ module internal Bytes = /// A view over bytes. /// May be backed by managed or unmanaged memory, or memory mapped file. [] -type internal ByteMemory = +type public ByteMemory = abstract Item: int -> byte with get abstract Length: int + abstract ReadAllBytes: unit -> byte[] + abstract ReadBytes: pos: int * count: int -> byte[] abstract ReadInt32: pos: int -> int @@ -65,6 +72,8 @@ type internal ReadOnlyByteMemory = member Length: int + member ReadAllBytes: unit -> byte[] + member ReadBytes: pos: int * count: int -> byte[] member ReadInt32: pos: int -> int @@ -83,7 +92,11 @@ type internal ReadOnlyByteMemory = member AsStream: unit -> Stream - +/// MemoryMapped extensions +module internal MemoryMappedFileExtensions = + type MemoryMappedFile with + static member TryFromByteMemory : bytes: ReadOnlyByteMemory -> MemoryMappedFile option + /// Filesystem helpers module internal FileSystemUtils = val checkPathForIllegalChars: (string -> unit) @@ -109,21 +122,12 @@ module internal FileSystemUtils = /// Trim the quotes and spaces from either end of a string val trimQuotes: string -> string - /// Checks whether filename ends in suffidx, ignoring case. + /// Checks whether filename ends in suffix, ignoring case. val hasSuffixCaseInsensitive: string -> string -> bool /// Checks whether file is dll (ends in .dll) val isDll: string -> bool - // Reads all data from Stream. - val readAllFromStream: Stream -> string - - // Yields content line by line from stream - val readLinesFromStream: Stream -> string seq - - // Writes data to a stream - val inline writeToStream: Stream -> ^a -> unit - /// Type which we use to load assemblies. type public IAssemblyLoader = /// Used to load a dependency for F# Interactive and in an unused corner-case of type provider loading @@ -140,8 +144,11 @@ type DefaultAssemblyLoader = /// Represents a shim for the file system type public IFileSystem = + // Assembly loader. + abstract member AssemblyLoader : IAssemblyLoader + /// Open the file for read, returns ByteMemory, uses either FileStream (for smaller files) or MemoryMappedFile (for potentially big files, such as dlls). - abstract member OpenFileForReadShim: filePath: string * ?useMemoryMappedFile: bool * ?shouldShadowCopy: bool -> ByteMemory + abstract member OpenFileForReadShim: filePath: string * ?useMemoryMappedFile: bool * ?shouldShadowCopy: bool -> Stream /// Open the file for writing. Returns a Stream. abstract member OpenFileForWriteShim: filePath: string * ?fileMode: FileMode * ?fileAccess: FileAccess * ?fileShare: FileShare -> Stream @@ -163,7 +170,7 @@ type public IFileSystem = abstract member NormalizePathShim: path: string -> string /// A shim over Path.IsInvalidPath - abstract member IsInvalidPathShim: filename:string -> bool + abstract member IsInvalidPathShim: path:string -> bool /// A shim over Path.GetTempPath abstract member GetTempPathShim: unit -> string @@ -209,6 +216,69 @@ type public IFileSystem = type DefaultFileSystem = /// Create a default implementation of the file system new: unit -> DefaultFileSystem + abstract member AssemblyLoader: IAssemblyLoader + override AssemblyLoader: IAssemblyLoader + + abstract member OpenFileForReadShim: filePath: string * ?useMemoryMappedFile: bool * ?shouldShadowCopy: bool -> Stream + override OpenFileForReadShim: filePath: string * ?useMemoryMappedFile: bool * ?shouldShadowCopy: bool -> Stream + + abstract member OpenFileForWriteShim: filePath: string * ?fileMode: FileMode * ?fileAccess: FileAccess * ?fileShare: FileShare -> Stream + override OpenFileForWriteShim: filePath: string * ?fileMode: FileMode * ?fileAccess: FileAccess * ?fileShare: FileShare -> Stream + + abstract member GetFullPathShim: fileName: string -> string + override GetFullPathShim: fileName: string -> string + + abstract member GetFullFilePathInDirectoryShim: dir: string -> fileName: string -> string + override GetFullFilePathInDirectoryShim: dir: string -> fileName: string -> string + + abstract member IsPathRootedShim: path: string -> bool + override IsPathRootedShim: path: string -> bool + + abstract member NormalizePathShim: path: string -> string + override NormalizePathShim: path: string -> string + + abstract member IsInvalidPathShim: path: string -> bool + override IsInvalidPathShim: path: string -> bool + + abstract member GetTempPathShim: unit -> string + override GetTempPathShim: unit -> string + + abstract member GetDirectoryNameShim: path: string -> string + override GetDirectoryNameShim: path: string -> string + + abstract member GetLastWriteTimeShim: fileName: string -> DateTime + override GetLastWriteTimeShim: fileName: string -> DateTime + + abstract member GetCreationTimeShim: path: string -> DateTime + override GetCreationTimeShim: path: string -> DateTime + + abstract member CopyShim: src: string * dest: string * overwrite: bool -> unit + override CopyShim: src: string * dest: string * overwrite: bool -> unit + + abstract member FileExistsShim: fileName: string -> bool + override FileExistsShim: fileName: string -> bool + + abstract member FileDeleteShim: fileName: string -> unit + override FileDeleteShim: fileName: string -> unit + + abstract member DirectoryCreateShim: path: string -> DirectoryInfo + override DirectoryCreateShim: path: string -> DirectoryInfo + + abstract member DirectoryExistsShim: path: string -> bool + override DirectoryExistsShim: path: string -> bool + + abstract member DirectoryDeleteShim: path: string -> unit + override DirectoryDeleteShim: path: string -> unit + + abstract member EnumerateFilesShim: path: string * pattern: string -> string seq + override EnumerateFilesShim: path: string * pattern: string -> string seq + + abstract member EnumerateDirectoriesShim: path: string -> string seq + override EnumerateDirectoriesShim: path: string -> string seq + + abstract member IsStableFileHeuristic: fileName: string -> bool + override IsStableFileHeuristic: fileName: string -> bool + interface IFileSystem [] @@ -217,11 +287,14 @@ module public StreamExtensions = type System.IO.Stream with member GetWriter : ?encoding: Encoding -> TextWriter member WriteAllLines : contents: string seq * ?encoding: Encoding -> unit - member Write : data: ^a -> unit + member Write<'a> : data:'a -> unit member GetReader : codePage: int option * ?retryLocked: bool -> StreamReader - member ReadAlLText : ?encoding: Encoding -> string + member ReadBytes : start: int * len: int -> byte[] + member ReadAllBytes : unit -> byte[] + member ReadAllText : ?encoding: Encoding -> string member ReadLines : ?encoding: Encoding -> string seq member ReadAllLines : ?encoding: Encoding -> string array + member AsByteMemory : unit -> ByteMemory [] module public FileSystemAutoOpens = diff --git a/src/fsharp/utils/PathMap.fs b/src/fsharp/utils/PathMap.fs index 3e4f6fad96c..906c3831e6d 100644 --- a/src/fsharp/utils/PathMap.fs +++ b/src/fsharp/utils/PathMap.fs @@ -6,6 +6,8 @@ namespace Internal.Utilities open System open System.IO +open FSharp.Compiler.IO + type PathMap = PathMap of Map [] @@ -17,7 +19,7 @@ module internal PathMap = let addMapping (src : string) (dst : string) (PathMap map) : PathMap = // Normalise the path - let normalSrc = Path.GetFullPath src + let normalSrc = FileSystem.GetFullPathShim src let oldPrefix = if normalSrc.EndsWith dirSepStr then normalSrc diff --git a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs index a20e0a8ce41..cfff214df56 100644 --- a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs +++ b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs @@ -3991,24 +3991,6 @@ FSharp.Compiler.EditorServices.XmlDocable: Int32 line FSharp.Compiler.EditorServices.XmlDocable: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_paramNames() FSharp.Compiler.EditorServices.XmlDocable: Microsoft.FSharp.Collections.FSharpList`1[System.String] paramNames FSharp.Compiler.EditorServices.XmlDocable: System.String ToString() -FSharp.Compiler.IO.ByteArrayMemory -FSharp.Compiler.IO.ByteArrayMemory: Byte Item [Int32] -FSharp.Compiler.IO.ByteArrayMemory: Byte get_Item(Int32) -FSharp.Compiler.IO.ByteArrayMemory: Byte[] ReadAllBytes() -FSharp.Compiler.IO.ByteArrayMemory: Byte[] ReadBytes(Int32, Int32) -FSharp.Compiler.IO.ByteArrayMemory: Byte[] ToArray() -FSharp.Compiler.IO.ByteArrayMemory: FSharp.Compiler.IO.ByteMemory Slice(Int32, Int32) -FSharp.Compiler.IO.ByteArrayMemory: Int32 Length -FSharp.Compiler.IO.ByteArrayMemory: Int32 ReadInt32(Int32) -FSharp.Compiler.IO.ByteArrayMemory: Int32 get_Length() -FSharp.Compiler.IO.ByteArrayMemory: System.IO.Stream AsReadOnlyStream() -FSharp.Compiler.IO.ByteArrayMemory: System.IO.Stream AsStream() -FSharp.Compiler.IO.ByteArrayMemory: System.String ReadUtf8String(Int32, Int32) -FSharp.Compiler.IO.ByteArrayMemory: UInt16 ReadUInt16(Int32) -FSharp.Compiler.IO.ByteArrayMemory: Void .ctor(Byte[], Int32, Int32) -FSharp.Compiler.IO.ByteArrayMemory: Void Copy(Int32, Byte[], Int32, Int32) -FSharp.Compiler.IO.ByteArrayMemory: Void CopyTo(System.IO.Stream) -FSharp.Compiler.IO.ByteArrayMemory: Void set_Item(Int32, Byte) FSharp.Compiler.IO.ByteMemory FSharp.Compiler.IO.ByteMemory: Byte Item [Int32] FSharp.Compiler.IO.ByteMemory: Byte get_Item(Int32) @@ -4030,21 +4012,35 @@ FSharp.Compiler.IO.ByteMemory: System.IO.Stream AsReadOnlyStream() FSharp.Compiler.IO.ByteMemory: System.IO.Stream AsStream() FSharp.Compiler.IO.ByteMemory: System.String ReadUtf8String(Int32, Int32) FSharp.Compiler.IO.ByteMemory: UInt16 ReadUInt16(Int32) -FSharp.Compiler.IO.ByteMemory: Void .ctor() FSharp.Compiler.IO.ByteMemory: Void Copy(Int32, Byte[], Int32, Int32) FSharp.Compiler.IO.ByteMemory: Void CopyTo(System.IO.Stream) FSharp.Compiler.IO.ByteMemory: Void set_Item(Int32, Byte) -FSharp.Compiler.IO.ByteStorage -FSharp.Compiler.IO.ByteStorage: FSharp.Compiler.IO.ByteStorage FromByteArray(Byte[]) -FSharp.Compiler.IO.ByteStorage: FSharp.Compiler.IO.ByteStorage FromByteArrayAndCopy(Byte[], Boolean) -FSharp.Compiler.IO.ByteStorage: FSharp.Compiler.IO.ByteStorage FromByteMemory(FSharp.Compiler.IO.ReadOnlyByteMemory) -FSharp.Compiler.IO.ByteStorage: FSharp.Compiler.IO.ByteStorage FromByteMemoryAndCopy(FSharp.Compiler.IO.ReadOnlyByteMemory, Boolean) -FSharp.Compiler.IO.ByteStorage: FSharp.Compiler.IO.ReadOnlyByteMemory GetByteMemory() -FSharp.Compiler.IO.ByteStorage: Void .ctor(Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,FSharp.Compiler.IO.ReadOnlyByteMemory]) FSharp.Compiler.IO.DefaultAssemblyLoader FSharp.Compiler.IO.DefaultAssemblyLoader: Void .ctor() FSharp.Compiler.IO.DefaultFileSystem +FSharp.Compiler.IO.DefaultFileSystem: Boolean DirectoryExistsShim(System.String) +FSharp.Compiler.IO.DefaultFileSystem: Boolean FileExistsShim(System.String) +FSharp.Compiler.IO.DefaultFileSystem: Boolean IsInvalidPathShim(System.String) +FSharp.Compiler.IO.DefaultFileSystem: Boolean IsPathRootedShim(System.String) +FSharp.Compiler.IO.DefaultFileSystem: Boolean IsStableFileHeuristic(System.String) +FSharp.Compiler.IO.DefaultFileSystem: FSharp.Compiler.IO.IAssemblyLoader AssemblyLoader +FSharp.Compiler.IO.DefaultFileSystem: FSharp.Compiler.IO.IAssemblyLoader get_AssemblyLoader() +FSharp.Compiler.IO.DefaultFileSystem: System.Collections.Generic.IEnumerable`1[System.String] EnumerateDirectoriesShim(System.String) +FSharp.Compiler.IO.DefaultFileSystem: System.Collections.Generic.IEnumerable`1[System.String] EnumerateFilesShim(System.String, System.String) +FSharp.Compiler.IO.DefaultFileSystem: System.DateTime GetCreationTimeShim(System.String) +FSharp.Compiler.IO.DefaultFileSystem: System.DateTime GetLastWriteTimeShim(System.String) +FSharp.Compiler.IO.DefaultFileSystem: System.IO.DirectoryInfo DirectoryCreateShim(System.String) +FSharp.Compiler.IO.DefaultFileSystem: System.IO.Stream OpenFileForReadShim(System.String, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) +FSharp.Compiler.IO.DefaultFileSystem: System.IO.Stream OpenFileForWriteShim(System.String, Microsoft.FSharp.Core.FSharpOption`1[System.IO.FileMode], Microsoft.FSharp.Core.FSharpOption`1[System.IO.FileAccess], Microsoft.FSharp.Core.FSharpOption`1[System.IO.FileShare]) +FSharp.Compiler.IO.DefaultFileSystem: System.String GetDirectoryNameShim(System.String) +FSharp.Compiler.IO.DefaultFileSystem: System.String GetFullFilePathInDirectoryShim(System.String, System.String) +FSharp.Compiler.IO.DefaultFileSystem: System.String GetFullPathShim(System.String) +FSharp.Compiler.IO.DefaultFileSystem: System.String GetTempPathShim() +FSharp.Compiler.IO.DefaultFileSystem: System.String NormalizePathShim(System.String) FSharp.Compiler.IO.DefaultFileSystem: Void .ctor() +FSharp.Compiler.IO.DefaultFileSystem: Void CopyShim(System.String, System.String, Boolean) +FSharp.Compiler.IO.DefaultFileSystem: Void DirectoryDeleteShim(System.String) +FSharp.Compiler.IO.DefaultFileSystem: Void FileDeleteShim(System.String) FSharp.Compiler.IO.FileSystemAutoOpens FSharp.Compiler.IO.FileSystemAutoOpens: FSharp.Compiler.IO.IFileSystem FileSystem FSharp.Compiler.IO.FileSystemAutoOpens: FSharp.Compiler.IO.IFileSystem get_FileSystem() @@ -4058,7 +4054,6 @@ FSharp.Compiler.IO.IFileSystem: Boolean FileExistsShim(System.String) FSharp.Compiler.IO.IFileSystem: Boolean IsInvalidPathShim(System.String) FSharp.Compiler.IO.IFileSystem: Boolean IsPathRootedShim(System.String) FSharp.Compiler.IO.IFileSystem: Boolean IsStableFileHeuristic(System.String) -FSharp.Compiler.IO.IFileSystem: FSharp.Compiler.IO.ByteMemory OpenFileForReadShim(System.String, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) FSharp.Compiler.IO.IFileSystem: FSharp.Compiler.IO.IAssemblyLoader AssemblyLoader FSharp.Compiler.IO.IFileSystem: FSharp.Compiler.IO.IAssemblyLoader get_AssemblyLoader() FSharp.Compiler.IO.IFileSystem: System.Collections.Generic.IEnumerable`1[System.String] EnumerateDirectoriesShim(System.String) @@ -4066,6 +4061,7 @@ FSharp.Compiler.IO.IFileSystem: System.Collections.Generic.IEnumerable`1[System. FSharp.Compiler.IO.IFileSystem: System.DateTime GetCreationTimeShim(System.String) FSharp.Compiler.IO.IFileSystem: System.DateTime GetLastWriteTimeShim(System.String) FSharp.Compiler.IO.IFileSystem: System.IO.DirectoryInfo DirectoryCreateShim(System.String) +FSharp.Compiler.IO.IFileSystem: System.IO.Stream OpenFileForReadShim(System.String, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) FSharp.Compiler.IO.IFileSystem: System.IO.Stream OpenFileForWriteShim(System.String, Microsoft.FSharp.Core.FSharpOption`1[System.IO.FileMode], Microsoft.FSharp.Core.FSharpOption`1[System.IO.FileAccess], Microsoft.FSharp.Core.FSharpOption`1[System.IO.FileShare]) FSharp.Compiler.IO.IFileSystem: System.String GetDirectoryNameShim(System.String) FSharp.Compiler.IO.IFileSystem: System.String GetFullFilePathInDirectoryShim(System.String, System.String) @@ -4076,7 +4072,6 @@ FSharp.Compiler.IO.IFileSystem: Void CopyShim(System.String, System.String, Bool FSharp.Compiler.IO.IFileSystem: Void DirectoryDeleteShim(System.String) FSharp.Compiler.IO.IFileSystem: Void FileDeleteShim(System.String) FSharp.Compiler.IO.IllegalFileNameChar -FSharp.Compiler.IO.IllegalFileNameChar: Boolean Equals(System.Exception) FSharp.Compiler.IO.IllegalFileNameChar: Boolean Equals(System.Object) FSharp.Compiler.IO.IllegalFileNameChar: Boolean Equals(System.Object, System.Collections.IEqualityComparer) FSharp.Compiler.IO.IllegalFileNameChar: Char Data1 @@ -4087,56 +4082,15 @@ FSharp.Compiler.IO.IllegalFileNameChar: System.String Data0 FSharp.Compiler.IO.IllegalFileNameChar: System.String get_Data0() FSharp.Compiler.IO.IllegalFileNameChar: Void .ctor() FSharp.Compiler.IO.IllegalFileNameChar: Void .ctor(System.String, Char) -FSharp.Compiler.IO.MemoryMappedFileExtensions -FSharp.Compiler.IO.MemoryMappedFileExtensions: Microsoft.FSharp.Core.FSharpOption`1[System.IO.MemoryMappedFiles.MemoryMappedFile] MemoryMappedFile.TryFromByteMemory.Static(FSharp.Compiler.IO.ReadOnlyByteMemory) -FSharp.Compiler.IO.RawByteMemory -FSharp.Compiler.IO.RawByteMemory: Byte Item [Int32] -FSharp.Compiler.IO.RawByteMemory: Byte get_Item(Int32) -FSharp.Compiler.IO.RawByteMemory: Byte[] ReadAllBytes() -FSharp.Compiler.IO.RawByteMemory: Byte[] ReadBytes(Int32, Int32) -FSharp.Compiler.IO.RawByteMemory: Byte[] ToArray() -FSharp.Compiler.IO.RawByteMemory: FSharp.Compiler.IO.ByteMemory Slice(Int32, Int32) -FSharp.Compiler.IO.RawByteMemory: Int32 Length -FSharp.Compiler.IO.RawByteMemory: Int32 ReadInt32(Int32) -FSharp.Compiler.IO.RawByteMemory: Int32 get_Length() -FSharp.Compiler.IO.RawByteMemory: System.IO.Stream AsReadOnlyStream() -FSharp.Compiler.IO.RawByteMemory: System.IO.Stream AsStream() -FSharp.Compiler.IO.RawByteMemory: System.String ReadUtf8String(Int32, Int32) -FSharp.Compiler.IO.RawByteMemory: UInt16 ReadUInt16(Int32) -FSharp.Compiler.IO.RawByteMemory: Void .ctor(Byte*, Int32, System.Object) -FSharp.Compiler.IO.RawByteMemory: Void Copy(Int32, Byte[], Int32, Int32) -FSharp.Compiler.IO.RawByteMemory: Void CopyTo(System.IO.Stream) -FSharp.Compiler.IO.RawByteMemory: Void set_Item(Int32, Byte) -FSharp.Compiler.IO.ReadOnlyByteMemory -FSharp.Compiler.IO.ReadOnlyByteMemory: Byte Item [Int32] -FSharp.Compiler.IO.ReadOnlyByteMemory: Byte get_Item(Int32) -FSharp.Compiler.IO.ReadOnlyByteMemory: Byte[] ReadAllBytes() -FSharp.Compiler.IO.ReadOnlyByteMemory: Byte[] ReadBytes(Int32, Int32) -FSharp.Compiler.IO.ReadOnlyByteMemory: Byte[] ToArray() -FSharp.Compiler.IO.ReadOnlyByteMemory: FSharp.Compiler.IO.ByteMemory Underlying -FSharp.Compiler.IO.ReadOnlyByteMemory: FSharp.Compiler.IO.ByteMemory get_Underlying() -FSharp.Compiler.IO.ReadOnlyByteMemory: FSharp.Compiler.IO.ReadOnlyByteMemory Slice(Int32, Int32) -FSharp.Compiler.IO.ReadOnlyByteMemory: Int32 Length -FSharp.Compiler.IO.ReadOnlyByteMemory: Int32 ReadInt32(Int32) -FSharp.Compiler.IO.ReadOnlyByteMemory: Int32 get_Length() -FSharp.Compiler.IO.ReadOnlyByteMemory: System.IO.Stream AsStream() -FSharp.Compiler.IO.ReadOnlyByteMemory: System.String ReadUtf8String(Int32, Int32) -FSharp.Compiler.IO.ReadOnlyByteMemory: UInt16 ReadUInt16(Int32) -FSharp.Compiler.IO.ReadOnlyByteMemory: Void .ctor(FSharp.Compiler.IO.ByteMemory) -FSharp.Compiler.IO.ReadOnlyByteMemory: Void Copy(Int32, Byte[], Int32, Int32) -FSharp.Compiler.IO.ReadOnlyByteMemory: Void CopyTo(System.IO.Stream) -FSharp.Compiler.IO.SafeUnmanagedMemoryStream -FSharp.Compiler.IO.SafeUnmanagedMemoryStream: Void .ctor(Byte*, Int64, Int64, System.IO.FileAccess, System.Object) -FSharp.Compiler.IO.SafeUnmanagedMemoryStream: Void .ctor(Byte*, Int64, System.Object) -FSharp.Compiler.IO.SafeUnmanagedMemoryStream: Void Dispose(Boolean) FSharp.Compiler.IO.StreamExtensions +FSharp.Compiler.IO.StreamExtensions: Byte[] Stream.ReadAllBytes(System.IO.Stream) +FSharp.Compiler.IO.StreamExtensions: Byte[] Stream.ReadBytes(System.IO.Stream, Int32, Int32) +FSharp.Compiler.IO.StreamExtensions: FSharp.Compiler.IO.ByteMemory Stream.AsByteMemory(System.IO.Stream) FSharp.Compiler.IO.StreamExtensions: System.Collections.Generic.IEnumerable`1[System.String] Stream.ReadLines(System.IO.Stream, Microsoft.FSharp.Core.FSharpOption`1[System.Text.Encoding]) FSharp.Compiler.IO.StreamExtensions: System.IO.StreamReader Stream.GetReader(System.IO.Stream, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) FSharp.Compiler.IO.StreamExtensions: System.IO.TextWriter Stream.GetWriter(System.IO.Stream, Microsoft.FSharp.Core.FSharpOption`1[System.Text.Encoding]) FSharp.Compiler.IO.StreamExtensions: System.String Stream.ReadAllText(System.IO.Stream, Microsoft.FSharp.Core.FSharpOption`1[System.Text.Encoding]) FSharp.Compiler.IO.StreamExtensions: System.String[] Stream.ReadAllLines(System.IO.Stream, Microsoft.FSharp.Core.FSharpOption`1[System.Text.Encoding]) -FSharp.Compiler.IO.StreamExtensions: System.Text.Encoding get_utf8noBOM() -FSharp.Compiler.IO.StreamExtensions: System.Text.Encoding utf8noBOM FSharp.Compiler.IO.StreamExtensions: Void Stream.WriteAllLines(System.IO.Stream, System.Collections.Generic.IEnumerable`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Text.Encoding]) FSharp.Compiler.IO.StreamExtensions: Void Stream.Write[a](System.IO.Stream, a) FSharp.Compiler.Interactive.Shell diff --git a/tests/FSharp.Test.Utilities/Compiler.fs b/tests/FSharp.Test.Utilities/Compiler.fs index 0233c3f3954..153904e1636 100644 --- a/tests/FSharp.Test.Utilities/Compiler.fs +++ b/tests/FSharp.Test.Utilities/Compiler.fs @@ -102,7 +102,9 @@ module rec Compiler = let private getSource (src: TestType) : string = match src with | Text t -> t - | Path p -> FileSystem.OpenFileForReadShim(p).AsStream().ReadAllText() + | Path p -> + use stream = FileSystem.OpenFileForReadShim(p) + stream.ReadAllText() let private fsFromString (source: string) (kind: SourceKind) : FSharpCompilationSource = match source with diff --git a/tests/fsharp/TypeProviderTests.fs b/tests/fsharp/TypeProviderTests.fs index df743eea3c5..b129bea904e 100644 --- a/tests/fsharp/TypeProviderTests.fs +++ b/tests/fsharp/TypeProviderTests.fs @@ -244,7 +244,6 @@ let ``negative type provider tests`` (name:string) = let dirp = (dir |> Commands.pathAddBackslash) do FileSystem.OpenFileForReadShim(sprintf "%s%s.%sbslpp" dirp name pref) - .AsStream() .ReadAllText() .Replace("", getfullpath cfg (sprintf "provider_%s.dll" name)) .Replace("",dirp) diff --git a/tests/service/FileSystemTests.fs b/tests/service/FileSystemTests.fs index 98396fd2c75..a6dd94fcc45 100644 --- a/tests/service/FileSystemTests.fs +++ b/tests/service/FileSystemTests.fs @@ -23,68 +23,33 @@ let fileName2 = @"c:\mycode\test2.fs" // note, the path doesn' exist #nowarn "57" -type internal MyFileSystem(defaultFileSystem:IFileSystem) = - let file1 = """ +let file1 = """ module File1 let A = 1""" - let file2 = """ + +let file2 = """ module File2 let B = File1.A + File1.A""" - let files = dict [(fileName1, file1); (fileName2, file2)] - - interface IFileSystem with - member _.AssemblyLoader = DefaultAssemblyLoader() :> IAssemblyLoader +type internal MyFileSystem() = + inherit DefaultFileSystem() + static member FilesCache = dict [(fileName1, file1); (fileName2, file2)] // Implement the service to open files for reading and writing - member _.OpenFileForReadShim(filePath, ?useMemoryMappedFile: bool, ?shouldShadowCopy: bool) = + override _.OpenFileForReadShim(filePath, ?useMemoryMappedFile: bool, ?shouldShadowCopy: bool) = let shouldShadowCopy = defaultArg shouldShadowCopy false let useMemoryMappedFile = defaultArg useMemoryMappedFile false - match files.TryGetValue filePath with + match MyFileSystem.FilesCache.TryGetValue filePath with | true, text -> - let bytes = Encoding.UTF8.GetBytes(text) - ByteArrayMemory(bytes, 0, bytes.Length) :> ByteMemory - | _ -> defaultFileSystem.OpenFileForReadShim(filePath, useMemoryMappedFile, shouldShadowCopy) - - member _.OpenFileForWriteShim(filePath, ?fileMode: FileMode, ?fileAccess: FileAccess, ?fileShare: FileShare) = - let fileMode = defaultArg fileMode FileMode.OpenOrCreate - let fileAccess = defaultArg fileAccess FileAccess.ReadWrite - let fileShare = defaultArg fileShare FileShare.Read - defaultFileSystem.OpenFileForWriteShim(filePath, fileMode, fileAccess, fileShare) - - member _.IsStableFileHeuristic(fileName) = - defaultFileSystem.IsStableFileHeuristic(fileName) - - - // Implement the service related to temporary paths and file time stamps - member _.GetTempPathShim() = defaultFileSystem.GetTempPathShim() - member _.GetLastWriteTimeShim(fileName) = defaultFileSystem.GetLastWriteTimeShim(fileName) - member _.GetFullPathShim(fileName) = defaultFileSystem.GetFullPathShim(fileName) - member _.IsInvalidPathShim(fileName) = defaultFileSystem.IsInvalidPathShim(fileName) - member _.IsPathRootedShim(fileName) = defaultFileSystem.IsPathRootedShim(fileName) - - member _.CopyShim(src, dest, overwrite) = defaultFileSystem.CopyShim(src, dest, overwrite) - member _.DirectoryCreateShim(path) = defaultFileSystem.DirectoryCreateShim(path) - member _.DirectoryDeleteShim(path) = defaultFileSystem.DirectoryDeleteShim(path) - member _.DirectoryExistsShim(path) = defaultFileSystem.DirectoryExistsShim(path) - member _.EnumerateDirectoriesShim(path) = defaultFileSystem.EnumerateDirectoriesShim(path) - member _.EnumerateFilesShim(path, pattern) = defaultFileSystem.EnumerateFilesShim(path, pattern) - member _.FileDeleteShim(fileName) = defaultFileSystem.FileDeleteShim(fileName) - member _.FileExistsShim(fileName) = files.ContainsKey(fileName) || defaultFileSystem.FileExistsShim(fileName) - member _.GetCreationTimeShim(path) = defaultFileSystem.GetCreationTimeShim(path) - member _.GetDirectoryNameShim(path) = defaultFileSystem.GetDirectoryNameShim(path) - member _.GetFullFilePathInDirectoryShim(dir) (fileName) = defaultFileSystem.GetFullFilePathInDirectoryShim dir fileName - member _.NormalizePathShim(path) = defaultFileSystem.NormalizePathShim(path) - - - + new MemoryStream(Encoding.UTF8.GetBytes(text)) :> Stream + | _ -> base.OpenFileForReadShim(filePath, useMemoryMappedFile, shouldShadowCopy) + override _.FileExistsShim(fileName) = MyFileSystem.FilesCache.ContainsKey(fileName) || base.FileExistsShim(fileName) let UseMyFileSystem() = - let myFileSystem = MyFileSystem(FileSystemAutoOpens.FileSystem) + let myFileSystem = MyFileSystem() FileSystemAutoOpens.FileSystem <- myFileSystem { new IDisposable with member x.Dispose() = FileSystemAutoOpens.FileSystem <- myFileSystem } - [] #if NETCOREAPP [] diff --git a/tests/service/MultiProjectAnalysisTests.fs b/tests/service/MultiProjectAnalysisTests.fs index 5363ceed00b..d8d41480664 100644 --- a/tests/service/MultiProjectAnalysisTests.fs +++ b/tests/service/MultiProjectAnalysisTests.fs @@ -885,7 +885,7 @@ let ``Type provider project references should not throw exceptions`` () = //printfn "options: %A" options let fileName = __SOURCE_DIRECTORY__ + @"/data/TypeProviderConsole/Program.fs" - let fileSource = FileSystem.OpenFileForReadShim(fileName).AsStream().ReadAllText() + let fileSource = FileSystem.OpenFileForReadShim(fileName).ReadAllText() let fileParseResults, fileCheckAnswer = checker.ParseAndCheckFileInProject(fileName, 0, SourceText.ofString fileSource, options) |> Async.RunSynchronously let fileCheckResults = match fileCheckAnswer with @@ -976,7 +976,7 @@ let ``Projects creating generated types should not utilize cross-project-referen OriginalLoadReferences = [] } //printfn "options: %A" options let fileName = __SOURCE_DIRECTORY__ + @"/data/TypeProvidersBug/TestConsole/Program.fs" - let fileSource = FileSystem.OpenFileForReadShim(fileName).AsStream().ReadAllText() + let fileSource = FileSystem.OpenFileForReadShim(fileName).ReadAllText() let fileParseResults, fileCheckAnswer = checker.ParseAndCheckFileInProject(fileName, 0, SourceText.ofString fileSource, options) |> Async.RunSynchronously let fileCheckResults = diff --git a/tests/service/ProjectAnalysisTests.fs b/tests/service/ProjectAnalysisTests.fs index c441d44207d..4e6503797c6 100644 --- a/tests/service/ProjectAnalysisTests.fs +++ b/tests/service/ProjectAnalysisTests.fs @@ -5168,7 +5168,7 @@ let test2() = test() [] let ``Test project42 to ensure cached checked results are invalidated`` () = - let text2 = SourceText.ofString(FileSystem.OpenFileForReadShim(Project42.fileName2).AsStream().ReadAllText()) + let text2 = SourceText.ofString(FileSystem.OpenFileForReadShim(Project42.fileName2).ReadAllText()) let checkedFile2 = checker.ParseAndCheckFileInProject(Project42.fileName2, text2.GetHashCode(), text2, Project42.options) |> Async.RunSynchronously match checkedFile2 with | _, FSharpCheckFileAnswer.Succeeded(checkedFile2Results) -> @@ -5431,7 +5431,7 @@ type UseTheThings(i:int) = //(snd symbolUses.[42]).Symbol.IsEffectivelySameAs((snd symbolUses.[37]).Symbol) //(snd symbolUses.[42]).Symbol.GetEffectivelySameAsHash() //(snd symbolUses.[37]).Symbol.GetEffectivelySameAsHash() - let lines = FileSystem.OpenFileForReadShim(fileName1).AsStream().ReadAllLines() + let lines = FileSystem.OpenFileForReadShim(fileName1).ReadAllLines() let unusedOpens = UnusedOpens.getUnusedOpens (fileCheckResults, (fun i -> lines.[i-1])) |> Async.RunSynchronously let unusedOpensData = [ for uo in unusedOpens -> tups uo, lines.[uo.StartLine-1] ] let expected = @@ -5504,7 +5504,7 @@ type UseTheThings(i:int) = //(snd symbolUses.[42]).Symbol.IsEffectivelySameAs((snd symbolUses.[37]).Symbol) //(snd symbolUses.[42]).Symbol.GetEffectivelySameAsHash() //(snd symbolUses.[37]).Symbol.GetEffectivelySameAsHash() - let lines = FileSystem.OpenFileForReadShim(fileName1).AsStream().ReadAllLines() + let lines = FileSystem.OpenFileForReadShim(fileName1).ReadAllLines() let unusedOpens = UnusedOpens.getUnusedOpens (fileCheckResults, (fun i -> lines.[i-1])) |> Async.RunSynchronously let unusedOpensData = [ for uo in unusedOpens -> tups uo, lines.[uo.StartLine-1] ] let expected = @@ -5580,7 +5580,7 @@ module M2 = |> function | _, FSharpCheckFileAnswer.Succeeded(res) -> res | _ -> failwithf "Parsing aborted unexpectedly..." - let lines = FileSystem.OpenFileForReadShim(fileName1).AsStream().ReadAllLines() + let lines = FileSystem.OpenFileForReadShim(fileName1).ReadAllLines() let unusedOpens = UnusedOpens.getUnusedOpens (fileCheckResults, (fun i -> lines.[i-1])) |> Async.RunSynchronously let unusedOpensData = [ for uo in unusedOpens -> tups uo, lines.[uo.StartLine-1] ] let expected = From 43648d7457a445bb61a1391824cbd694c3e3f503 Mon Sep 17 00:00:00 2001 From: kerams Date: Sun, 30 May 2021 02:39:42 +0200 Subject: [PATCH 10/12] Compile `[||]` to `System.Array.Empty<_>()` (#11330) --- src/fsharp/IlxGen.fs | 16 +++-- src/fsharp/TcGlobals.fs | 6 +- .../EmittedIL/Misc.fs | 32 +++++++++ .../FSharp.Compiler.ComponentTests.fsproj | 1 + .../Language/SpanOptimizationTests.fs | 71 +++++++++---------- 5 files changed, 83 insertions(+), 43 deletions(-) create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc.fs diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 72e742b4312..39c2c63d3c4 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -2893,12 +2893,16 @@ and GenNewArraySimple cenv cgbuf eenv (elems, elemTy, m) sequel = let ilElemTy = GenType cenv.amap m eenv.tyenv elemTy let ilArrTy = mkILArr1DTy ilElemTy - CG.EmitInstrs cgbuf (pop 0) (Push [ilArrTy]) [ (AI_ldc (DT_I4, ILConst.I4 (elems.Length))); I_newarr (ILArrayShape.SingleDimensional, ilElemTy) ] - elems |> List.iteri (fun i e -> - CG.EmitInstrs cgbuf (pop 0) (Push [ilArrTy; cenv.g.ilg.typ_Int32]) [ AI_dup; (AI_ldc (DT_I4, ILConst.I4 i)) ] - GenExpr cenv cgbuf eenv SPSuppress e Continue - CG.EmitInstr cgbuf (pop 3) Push0 (I_stelem_any (ILArrayShape.SingleDimensional, ilElemTy))) - + if List.isEmpty elems && cenv.g.isArrayEmptyAvailable then + mkNormalCall (mkILMethSpecInTy (cenv.g.ilg.typ_Array, ILCallingConv.Static, "Empty", [], mkILArr1DTy (mkILTyvarTy 0us), [ilElemTy])) + |> CG.EmitInstr cgbuf (pop 0) (Push [ilArrTy]) + else + CG.EmitInstrs cgbuf (pop 0) (Push [ilArrTy]) [ (AI_ldc (DT_I4, ILConst.I4 (elems.Length))); I_newarr (ILArrayShape.SingleDimensional, ilElemTy) ] + elems |> List.iteri (fun i e -> + CG.EmitInstrs cgbuf (pop 0) (Push [ilArrTy; cenv.g.ilg.typ_Int32]) [ AI_dup; (AI_ldc (DT_I4, ILConst.I4 i)) ] + GenExpr cenv cgbuf eenv SPSuppress e Continue + CG.EmitInstr cgbuf (pop 3) Push0 (I_stelem_any (ILArrayShape.SingleDimensional, ilElemTy))) + GenSequel cenv eenv.cloc cgbuf sequel and GenNewArray cenv cgbuf eenv (elems: Expr list, elemTy, m) sequel = diff --git a/src/fsharp/TcGlobals.fs b/src/fsharp/TcGlobals.fs index 3cb9441cb4d..a21e5e11399 100755 --- a/src/fsharp/TcGlobals.fs +++ b/src/fsharp/TcGlobals.fs @@ -351,6 +351,7 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d let v_decimal_ty = mkSysNonGenericTy sys "Decimal" let v_unit_ty = mkNonGenericTy v_unit_tcr_nice let v_system_Type_ty = mkSysNonGenericTy sys "Type" + let v_Array_tcref = findSysTyconRef sys "Array" let v_system_Reflection_MethodInfo_ty = mkSysNonGenericTy ["System";"Reflection"] "MethodInfo" @@ -1097,7 +1098,7 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d member _.system_Reflection_MethodInfo_ty = v_system_Reflection_MethodInfo_ty - member val system_Array_tcref = findSysTyconRef sys "Array" + member val system_Array_tcref = v_Array_tcref member val system_Object_tcref = findSysTyconRef sys "Object" member val system_Value_tcref = findSysTyconRef sys "ValueType" member val system_Void_tcref = findSysTyconRef sys "Void" @@ -1508,6 +1509,9 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d compilingFslib || ((ValRefForIntrinsic g.call_with_witnesses_info).TryDeref.IsSome && langVersion.SupportsFeature LanguageFeature.WitnessPassing) + /// Indicates if we can use System.Array.Empty when emitting IL for empty array literals + member val isArrayEmptyAvailable = v_Array_tcref.ILTyconRawMetadata.Methods.FindByName "Empty" |> List.isEmpty |> not + member _.FindSysTyconRef path nm = findSysTyconRef path nm member _.TryFindSysTyconRef path nm = tryFindSysTyconRef path nm diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc.fs new file mode 100644 index 00000000000..88410a24e11 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc.fs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.ComponentTests.EmittedIL + +open Xunit +open FSharp.Test.Utilities.Compiler + +module ``Misc`` = + [] + let ``Empty array construct compiles to System.Array.Empty<_>()``() = + FSharp """ +module Misc + +let zInt (): int[] = [||] + +let zString (): string[] = [||] + +let zGeneric<'a> (): 'a[] = [||] + """ + |> compile + |> shouldSucceed + |> verifyIL [""" +IL_0000: call !!0[] [runtime]System.Array::Empty() +IL_0005: ret""" + """ + +IL_0000: call !!0[] [runtime]System.Array::Empty() +IL_0005: ret""" + + """ +IL_0000: call !!0[] [runtime]System.Array::Empty() +IL_0005: ret""" ] diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index 05fc99b3fb7..d5ef0fd4b62 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -21,6 +21,7 @@ + diff --git a/tests/fsharp/Compiler/Language/SpanOptimizationTests.fs b/tests/fsharp/Compiler/Language/SpanOptimizationTests.fs index 1a83d26902a..64ceb55ec20 100644 --- a/tests/fsharp/Compiler/Language/SpanOptimizationTests.fs +++ b/tests/fsharp/Compiler/Language/SpanOptimizationTests.fs @@ -166,51 +166,50 @@ module Test = class [System.Runtime]System.Collections.IEnumerator V_1, class [FSharp.Core]Microsoft.FSharp.Core.Unit V_2, class [System.Runtime]System.IDisposable V_3) - IL_0000: ldc.i4.0 - IL_0001: newarr [System.Runtime]System.Object - IL_0006: newobj instance void valuetype System.Span`1::.ctor(!0[]) - IL_000b: stloc.0 - IL_000c: ldloc.0 - IL_000d: box valuetype System.Span`1 - IL_0012: unbox.any [System.Runtime]System.Collections.IEnumerable - IL_0017: callvirt instance class [System.Runtime]System.Collections.IEnumerator [System.Runtime]System.Collections.IEnumerable::GetEnumerator() - IL_001c: stloc.1 + IL_0000: call !!0[] [runtime]System.Array::Empty() + IL_0005: newobj instance void valuetype System.Span`1::.ctor(!0[]) + IL_000a: stloc.0 + IL_000b: ldloc.0 + IL_000c: box valuetype System.Span`1 + IL_0011: unbox.any [System.Runtime]System.Collections.IEnumerable + IL_0016: callvirt instance class [System.Runtime]System.Collections.IEnumerator [System.Runtime]System.Collections.IEnumerable::GetEnumerator() + IL_001b: stloc.1 .try { - IL_001d: ldloc.1 - IL_001e: callvirt instance bool [System.Runtime]System.Collections.IEnumerator::MoveNext() - IL_0023: brfalse.s IL_0032 + IL_001c: ldloc.1 + IL_001d: callvirt instance bool [System.Runtime]System.Collections.IEnumerator::MoveNext() + IL_0022: brfalse.s IL_0031 - IL_0025: ldloc.1 - IL_0026: callvirt instance object [System.Runtime]System.Collections.IEnumerator::get_Current() - IL_002b: call void [System.Console]System.Console::WriteLine(object) - IL_0030: br.s IL_001d + IL_0024: ldloc.1 + IL_0025: callvirt instance object [System.Runtime]System.Collections.IEnumerator::get_Current() + IL_002a: call void [System.Console]System.Console::WriteLine(object) + IL_002f: br.s IL_001c - IL_0032: ldnull - IL_0033: stloc.2 - IL_0034: leave.s IL_004c + IL_0031: ldnull + IL_0032: stloc.2 + IL_0033: leave.s IL_004b } finally { - IL_0036: ldloc.1 - IL_0037: isinst [System.Runtime]System.IDisposable - IL_003c: stloc.3 - IL_003d: ldloc.3 - IL_003e: brfalse.s IL_0049 - - IL_0040: ldloc.3 - IL_0041: callvirt instance void [System.Runtime]System.IDisposable::Dispose() - IL_0046: ldnull - IL_0047: pop - IL_0048: endfinally - IL_0049: ldnull - IL_004a: pop - IL_004b: endfinally + IL_0035: ldloc.1 + IL_0036: isinst [System.Runtime]System.IDisposable + IL_003b: stloc.3 + IL_003c: ldloc.3 + IL_003d: brfalse.s IL_0048 + + IL_003f: ldloc.3 + IL_0040: callvirt instance void [System.Runtime]System.IDisposable::Dispose() + IL_0045: ldnull + IL_0046: pop + IL_0047: endfinally + IL_0048: ldnull + IL_0049: pop + IL_004a: endfinally } - IL_004c: ldloc.2 - IL_004d: pop - IL_004e: ret + IL_004b: ldloc.2 + IL_004c: pop + IL_004d: ret }""" ]) From 56ce803e1979b360445565b2b075e24d061c6e2b Mon Sep 17 00:00:00 2001 From: kerams Date: Mon, 31 May 2021 10:38:56 +0200 Subject: [PATCH 11/12] Remove cached empty array values (#11615) --- src/fsharp/absil/il.fs | 4 +--- src/fsharp/absil/ilread.fs | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/fsharp/absil/il.fs b/src/fsharp/absil/il.fs index 2130c33b0f6..68d0d20ed48 100644 --- a/src/fsharp/absil/il.fs +++ b/src/fsharp/absil/il.fs @@ -95,8 +95,6 @@ let splitILTypeName (nm: string) = let s1, s2 = splitNameAt nm idx splitNamespace s1, s2 -let emptyStringArray = ([| |] : string[]) - // Duplicate of comment in import.fs: // The type names that flow to the point include the "mangled" type names used for static parameters for provided types. // For example, @@ -111,7 +109,7 @@ let splitILTypeNameWithPossibleStaticArguments (nm: string) = let nsp, nm = match nm.LastIndexOf '.' with - | -1 -> emptyStringArray, nm + | -1 -> [| |], nm | idx -> let s1, s2 = splitNameAt nm idx splitNamespaceToArray s1, s2 diff --git a/src/fsharp/absil/ilread.fs b/src/fsharp/absil/ilread.fs index 63b0c684a4c..058c57cbe94 100644 --- a/src/fsharp/absil/ilread.fs +++ b/src/fsharp/absil/ilread.fs @@ -1406,14 +1406,12 @@ let readStringHeap (ctxt: ILMetadataReader) idx = ctxt.readStringHeap idx let readStringHeapOption (ctxt: ILMetadataReader) idx = if idx = 0 then None else Some (readStringHeap ctxt idx) -let emptyByteArray: byte[] = [||] - let readBlobHeapUncached ctxtH idx = let (ctxt: ILMetadataReader) = getHole ctxtH let mdv = ctxt.mdfile.GetView() // valid index lies in range [1..streamSize) // NOTE: idx cannot be 0 - Blob\String heap has first empty element that mdv one byte 0 - if idx <= 0 || idx >= ctxt.blobsStreamSize then emptyByteArray + if idx <= 0 || idx >= ctxt.blobsStreamSize then [| |] else seekReadBlob mdv (ctxt.blobsStreamPhysicalLoc + idx) let readBlobHeap (ctxt: ILMetadataReader) idx = ctxt.readBlobHeap idx From 6034e99b1e939c46963650d22ded174bc85de112 Mon Sep 17 00:00:00 2001 From: Evgeniy Andreev Date: Mon, 31 May 2021 12:40:38 +0400 Subject: [PATCH 12/12] Make Event's AddHandler/RemoveHandler atomic (#11326) --- src/fsharp/FSharp.Core/event.fs | 31 ++++++-- src/fsharp/FSharp.Core/event.fsi | 2 +- .../FSharp.Core.UnitTests.fsproj | 1 + .../Microsoft.FSharp.Control/EventTypes.fs | 77 +++++++++++++++++++ 4 files changed, 102 insertions(+), 9 deletions(-) create mode 100644 tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/EventTypes.fs diff --git a/src/fsharp/FSharp.Core/event.fs b/src/fsharp/FSharp.Core/event.fs index d14eea26904..8e1d0826f33 100644 --- a/src/fsharp/FSharp.Core/event.fs +++ b/src/fsharp/FSharp.Core/event.fs @@ -10,6 +10,19 @@ namespace Microsoft.FSharp.Control open Microsoft.FSharp.Control open System.Reflection open System.Diagnostics + + module private Atomic = + open System.Threading + + let inline setWith (thunk: 'a -> 'a) (value: byref<'a>) = + let mutable exchanged = false + let mutable oldValue = value + while not exchanged do + let comparand = oldValue + let newValue = thunk comparand + oldValue <- Interlocked.CompareExchange(&value, newValue, comparand) + if obj.ReferenceEquals(comparand, oldValue) then + exchanged <- true [] type DelegateEvent<'Delegate when 'Delegate :> System.Delegate>() = @@ -21,9 +34,9 @@ namespace Microsoft.FSharp.Control member x.Publish = { new IDelegateEvent<'Delegate> with member x.AddHandler(d) = - multicast <- System.Delegate.Combine(multicast, d) - member x.RemoveHandler(d) = - multicast <- System.Delegate.Remove(multicast, d) } + Atomic.setWith (fun value -> System.Delegate.Combine(value, d)) &multicast + member x.RemoveHandler(d) = + Atomic.setWith (fun value -> System.Delegate.Remove(value, d)) &multicast } type EventDelegee<'Args>(observer: System.IObserver<'Args>) = static let makeTuple = @@ -54,7 +67,7 @@ namespace Microsoft.FSharp.Control type EventWrapper<'Delegate,'Args> = delegate of 'Delegate * obj * 'Args -> unit [] - type Event<'Delegate, 'Args when 'Delegate : delegate<'Args, unit> and 'Delegate :> System.Delegate>() = + type Event<'Delegate, 'Args when 'Delegate : delegate<'Args, unit> and 'Delegate :> System.Delegate and 'Delegate: not struct>() = let mutable multicast : 'Delegate = Unchecked.defaultof<_> @@ -85,6 +98,8 @@ namespace Microsoft.FSharp.Control mi member x.Trigger(sender:obj,args: 'Args) = + // Copy multicast value into local variable to avoid changing during member call. + let multicast = multicast match box multicast with | null -> () | _ -> @@ -102,9 +117,9 @@ namespace Microsoft.FSharp.Control member x.ToString() = "" interface IEvent<'Delegate,'Args> with member e.AddHandler(d) = - multicast <- System.Delegate.Combine(multicast, d) :?> 'Delegate + Atomic.setWith (fun value -> System.Delegate.Combine(value, d) :?> 'Delegate) &multicast member e.RemoveHandler(d) = - multicast <- System.Delegate.Remove(multicast, d) :?> 'Delegate + Atomic.setWith (fun value -> System.Delegate.Remove(value, d) :?> 'Delegate) &multicast interface System.IObservable<'Args> with member e.Subscribe(observer) = let obj = new EventDelegee<'Args>(observer) @@ -128,9 +143,9 @@ namespace Microsoft.FSharp.Control member x.ToString() = "" interface IEvent<'T> with member e.AddHandler(d) = - x.multicast <- (System.Delegate.Combine(x.multicast, d) :?> Handler<'T>) + Atomic.setWith (fun value -> System.Delegate.Combine(value, d) :?> Handler<'T>) &x.multicast member e.RemoveHandler(d) = - x.multicast <- (System.Delegate.Remove(x.multicast, d) :?> Handler<'T>) + Atomic.setWith (fun value -> System.Delegate.Remove(value, d) :?> Handler<'T>) &x.multicast interface System.IObservable<'T> with member e.Subscribe(observer) = let h = new Handler<_>(fun sender args -> observer.OnNext(args)) diff --git a/src/fsharp/FSharp.Core/event.fsi b/src/fsharp/FSharp.Core/event.fsi index 855a259121b..fd6c23e0008 100644 --- a/src/fsharp/FSharp.Core/event.fsi +++ b/src/fsharp/FSharp.Core/event.fsi @@ -26,7 +26,7 @@ namespace Microsoft.FSharp.Control /// /// Events and Observables [] - type Event<'Delegate,'Args when 'Delegate : delegate<'Args,unit> and 'Delegate :> System.Delegate > = + type Event<'Delegate,'Args when 'Delegate : delegate<'Args,unit> and 'Delegate :> System.Delegate and 'Delegate : not struct> = /// Creates an event object suitable for delegate types following the standard .NET Framework convention of a first 'sender' argument. /// The created event. new : unit -> Event<'Delegate,'Args> diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj b/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj index e0d363f10a2..75d013df43e 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj +++ b/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj @@ -74,6 +74,7 @@ + diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/EventTypes.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/EventTypes.fs new file mode 100644 index 00000000000..69cb4d65143 --- /dev/null +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/EventTypes.fs @@ -0,0 +1,77 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +// Various tests for the: +// Microsoft.FSharp.Control event types + +namespace FSharp.Core.UnitTests.Control + +open System +open System.Reflection +open Xunit + +module private EventTypes = + type MultiArgDelegate = delegate of obj * obj[] -> unit + + let getListeners event = + let eventType = event.GetType() + let multicastField = + eventType + .GetField("multicast", BindingFlags.NonPublic ||| BindingFlags.Instance) + .GetValue event + :?> System.Delegate + + if not (isNull multicastField) then + let multicastType = typeof + let listeners = + multicastType + .GetMethod("GetInvocationList") + .Invoke(multicastField, [||]) + :?> System.Delegate [] + Some listeners + else + None + +type EventTypes() = + + [] + let RunsCount = 100 + + let runAddRemoveHandlers (event: IDelegateEvent<_>) handlerInitializer = + seq { + for _ in 1 .. RunsCount do + async { + let h = handlerInitializer() + event.AddHandler(h) + event.RemoveHandler(h) + } + } |> Async.Parallel |> Async.RunSynchronously |> ignore + + [] + member this.``Adding/removing handlers to published Event<'T> is thread-safe``() = + let event = new Event() + let listenersBefore = EventTypes.getListeners event + runAddRemoveHandlers (event.Publish) (fun _ -> new Handler<_>(fun sender args -> ())) + let listenersAfter = EventTypes.getListeners event + + Assert.True(listenersBefore.IsNone) + Assert.True(listenersAfter.IsNone) + + [] + member this.``Adding/removing handlers to published DelegateEvent is thread-safe``() = + let event = new DelegateEvent<_>() + let listenersBefore = EventTypes.getListeners event + runAddRemoveHandlers (event.Publish) (fun _ -> EventTypes.MultiArgDelegate(fun sender args -> ())) + let listenersAfter = EventTypes.getListeners event + + Assert.True(listenersBefore.IsNone) + Assert.True(listenersAfter.IsNone) + + [] + member this.``Adding/removing handlers to published Event<'D,'A> is thread-safe``() = + let event = new Event<_, _>() + let listenersBefore = EventTypes.getListeners event + runAddRemoveHandlers (event.Publish) (fun _ -> EventTypes.MultiArgDelegate(fun sender args -> ())) + let listenersAfter = EventTypes.getListeners event + + Assert.True(listenersBefore.IsNone) + Assert.True(listenersAfter.IsNone)