Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<int, int>((+) 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 `[<AllowOverloadOnReturnType>]` 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))
Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/AbstractIL/ilread.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖🕵️ [P2] Empty references leave a read handle open until GC, blocking an exclusive reopen after FCS reports the invalid assembly. CreateFromFile throws before disposer exists; the mapping-construction failure path needs to dispose its opened FileStream.

open System
open System.IO
open FSharp.Compiler.CodeAnalysis
open FSharp.Compiler.Text

let dll = Path.GetFullPath "empty.dll"
let script = Path.GetFullPath "check.fsx"
File.WriteAllBytes(dll, [||])
let source = SourceText.ofString (sprintf "#r @\"%s\"\nlet value = 1" dll)
let checker = FSharpChecker.Create()
let options, _ =
    checker.GetProjectOptionsFromScript(script, source, useSdkRefs = true)
    |> Async.RunSynchronously

// Keep GC from hiding the leaked handle during this repro.
if GC.TryStartNoGCRegion(256L * 1024L * 1024L) then
    try
        checker.ParseAndCheckFileInProject(script, 0, source, options)
        |> Async.RunSynchronously |> ignore
        use retry = new FileStream(dll, FileMode.Open, FileAccess.ReadWrite, FileShare.None)
        () // Base succeeds; mapped path throws IOException on Windows.
    finally
        GC.EndNoGCRegion()

use _disposer = disposer

let metadataPhysLoc, metadataSize, peinfo, pectxtEager, pevEager =
Expand Down
11 changes: 4 additions & 7 deletions src/Compiler/Utilities/FileSystem.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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()

[<Experimental("This FCS API/Type is experimental and subject to change.")>]
type RawByteMemory(addr: nativeptr<byte>, length: int, holder: obj) =
Expand Down
Loading