Problem
While debugging the F# compiler in VS, the compiler crashes with a System.NotSupportedException when it tries to use the memory-mapped-file fast path for ReadOnlyMemory<byte> data.
The exception is:
This operation is not supported for an UnmanagedMemoryStream created from a SafeBuffer.
Location
The failing code is in:
src/Compiler/Utilities/FileSystem.fs
The relevant code path is:
static member TryFromMemory(bytes: ReadOnlyMemory<byte>) =
let length = int64 bytes.Length
trymmf length (fun stream ->
let span = Span<byte>(stream.PositionPointer |> NativePtr.toVoidPtr, int length)
bytes.Span.CopyTo(span)
stream.Position <- stream.Position + length)
This is reached from:
ByteStorage.FromMemoryAndCopy(..., useBackingMemoryMappedFile = true)
CompilerImports.PickleToResource
CompilerImports.WriteSignatureData
CompilerImports.EncodeSignatureData
Stack trace
The debugger shows:
System.NotSupportedException
This operation is not supported for an UnmanagedMemoryStream created from a SafeBuffer.
[1] mscorlib.dll!System.IO.UnmanagedMemoryStream.PositionPointer.get
[2] FSharp.Compiler.Service.dll!FSharp.Compiler.IO.MemoryMappedFileExtensions.MemoryMappedFile-TryFromMemory-Static@392.Invoke
with the current statement at:
src\Compiler\Utilities\FileSystem.fs
392: trymmf length (fun stream ->
393: let span = Span<byte>(stream.PositionPointer |> NativePtr.toVoidPtr, int length)
394: bytes.Span.CopyTo(span)
395: stream.Position <- stream.Position + length)
Root cause
MemoryMappedFile.CreateViewStream(...) creates a stream backed by a SafeBuffer (the underlying mapped view). On .NET, accessing PositionPointer on that stream type is not supported and throws NotSupportedException.
The compiler optimization is assuming that the stream is a generic UnmanagedMemoryStream that supports PositionPointer, but this is not true for MemoryMappedFileViewStream.
Why this matters
This is a compiler bug in the memory-mapped-file optimization path, not a user code bug. It can fail while serializing compiler metadata/resources and prevents the compiler from completing the in-memory resource generation path.
Expected behavior
The code should copy the byte payload via the stream API (stream.Write) or another supported safe mechanism, without touching PositionPointer on a SafeBuffer-backed mapped view.
Additional context
Observed in the current debugging session inside the local repo:
C:\Users\Andrii\DevArchive\fsharp
- branch:
fix-project-options-async-debounce
- repo:
dotnet/fsharp
This appears to be in the compiler utility path used for metadata/resource pickling and memory-backed streaming.
Problem
While debugging the F# compiler in VS, the compiler crashes with a
System.NotSupportedExceptionwhen it tries to use the memory-mapped-file fast path forReadOnlyMemory<byte>data.The exception is:
Location
The failing code is in:
src/Compiler/Utilities/FileSystem.fsThe relevant code path is:
This is reached from:
ByteStorage.FromMemoryAndCopy(..., useBackingMemoryMappedFile = true)CompilerImports.PickleToResourceCompilerImports.WriteSignatureDataCompilerImports.EncodeSignatureDataStack trace
The debugger shows:
with the current statement at:
Root cause
MemoryMappedFile.CreateViewStream(...)creates a stream backed by aSafeBuffer(the underlying mapped view). On .NET, accessingPositionPointeron that stream type is not supported and throwsNotSupportedException.The compiler optimization is assuming that the stream is a generic
UnmanagedMemoryStreamthat supportsPositionPointer, but this is not true forMemoryMappedFileViewStream.Why this matters
This is a compiler bug in the memory-mapped-file optimization path, not a user code bug. It can fail while serializing compiler metadata/resources and prevents the compiler from completing the in-memory resource generation path.
Expected behavior
The code should copy the byte payload via the stream API (
stream.Write) or another supported safe mechanism, without touchingPositionPointeron a SafeBuffer-backed mapped view.Additional context
Observed in the current debugging session inside the local repo:
C:\Users\Andrii\DevArchive\fsharpfix-project-options-async-debouncedotnet/fsharpThis appears to be in the compiler utility path used for metadata/resource pickling and memory-backed streaming.