diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index ed1e382d6c7..50ddd78a27d 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -169,6 +169,7 @@ * Checker: recover on checking language version ([PR ##19970](https://github.com/dotnet/fsharp/pull/19970)) * Implied argument names for function-to-delegate coercions now fall back to the delegate's `Invoke` parameter names when the function has no recoverable names (e.g. a partial application like `System.Func((+) 1)`), instead of synthetic `delegateArg0`, `delegateArg1`, … names. ([PR #20001](https://github.com/dotnet/fsharp/pull/20001)) * Add internal `ResetCompilerGeneratedNameState` to `CompilerGlobalState` name generators so warm-checker re-compilation can produce fresh-process-identical generated names. ([PR #20017](https://github.com/dotnet/fsharp/pull/20017)) +* IL: map the short-lived metadata-only PE reader ([PR #20489](https://github.com/dotnet/fsharp/pull/20489)) * Add internal ECMA-335 Edit-and-Continue metadata delta writer to AbstractIL. ([PR #20019](https://github.com/dotnet/fsharp/pull/20019)) * Add Roslyn-format EnC CustomDebugInformation codec and portable PDB method CDI emission support to AbstractIL. ([PR #20018](https://github.com/dotnet/fsharp/pull/20018)) * Extension members (including operators) now participate in SRTP (statically-resolved type parameter) constraint resolution, so member constraints on `inline` code can be satisfied by extension members — including operators defined on types you don't own via type extensions. Intrinsic members keep priority over extension members, and extension members solve SRTP constraints without satisfying nominal static-abstract interface (IWSAM) constraints. Also adds the `[]` attribute for overloads that differ only by return type, and tuple type extensions (`type ('T1 * 'T2) with` / `type struct ('T1 * 'T2) with`). Requires `--langversion:preview`. ([RFC FS-1043](https://github.com/fsharp/fslang-design/blob/main/RFCs/FS-1043-extension-members-for-operators-and-srtp-constraints.md), [fslang-suggestions#230](https://github.com/fsharp/fslang-suggestions/issues/230), [PR #19602](https://github.com/dotnet/fsharp/pull/19602)) diff --git a/src/Compiler/AbstractIL/ilread.fs b/src/Compiler/AbstractIL/ilread.fs index d1728dc36d2..a9a052cb092 100644 --- a/src/Compiler/AbstractIL/ilread.fs +++ b/src/Compiler/AbstractIL/ilread.fs @@ -5168,7 +5168,7 @@ let OpenILModuleReader fileName opts = // For metadata-only, always use a temporary, short-lived PE file reader, preferably over a memory mapped file. // Then use the metadata blob as the long-lived memory resource. - let disposer, pefileEager = getBinaryFile fullPath false + let disposer, pefileEager = getBinaryFile fullPath true use _disposer = disposer let metadataPhysLoc, metadataSize, peinfo, pectxtEager, pevEager = diff --git a/src/Compiler/Utilities/FileSystem.fs b/src/Compiler/Utilities/FileSystem.fs index 5fd055b525d..172702aee47 100644 --- a/src/Compiler/Utilities/FileSystem.fs +++ b/src/Compiler/Utilities/FileSystem.fs @@ -199,13 +199,10 @@ type internal MemoryMappedStream(mmf: MemoryMappedFile, length: int64) = override x.Write(buffer, offset, count) = viewStream.Write(buffer, offset, count) override x.Read(buffer, offset, count) = viewStream.Read(buffer, offset, count) - override x.Finalize() = x.Dispose() - - interface IDisposable with - override x.Dispose() = - GC.SuppressFinalize x - mmf.Dispose() - viewStream.Dispose() + override _.Dispose disposing = + base.Dispose disposing + viewStream.Dispose() + mmf.Dispose() [] type RawByteMemory(addr: nativeptr, length: int, holder: obj) = @@ -529,37 +526,41 @@ type DefaultFileSystem() as this = if not useMemoryMappedFile then fileStream :> Stream else - let mmf = - if shouldShadowCopy then - let mmf = - MemoryMappedFile.CreateNew( + try + let mmf = + if shouldShadowCopy then + let mmf = + MemoryMappedFile.CreateNew( + null, + length, + MemoryMappedFileAccess.ReadWrite, + MemoryMappedFileOptions.None, + HandleInheritability.None + ) + + use stream = mmf.CreateViewStream(0L, length, MemoryMappedFileAccess.ReadWrite) + fileStream.CopyTo(stream) + fileStream.Dispose() + mmf + else + MemoryMappedFile.CreateFromFile( + fileStream, null, length, - MemoryMappedFileAccess.ReadWrite, - MemoryMappedFileOptions.None, - HandleInheritability.None + MemoryMappedFileAccess.Read, + HandleInheritability.None, + leaveOpen = false ) - use stream = mmf.CreateViewStream(0L, length, MemoryMappedFileAccess.ReadWrite) - fileStream.CopyTo(stream) - fileStream.Dispose() - mmf - else - MemoryMappedFile.CreateFromFile( - fileStream, - null, - length, - MemoryMappedFileAccess.Read, - HandleInheritability.None, - leaveOpen = false - ) - - let stream = new MemoryMappedStream(mmf, length) + let stream = new MemoryMappedStream(mmf, length) - if not stream.CanRead then - invalidOp "Cannot read file" + if not stream.CanRead then + invalidOp "Cannot read file" - stream :> Stream + stream :> Stream + with _ -> + fileStream.Dispose() + reraise () abstract OpenFileForWriteShim: filePath: string * ?fileMode: FileMode * ?fileAccess: FileAccess * ?fileShare: FileShare -> Stream