Repository navigation
Make the CopyTo and WriteTo destination parameters scoped - #9
Merged
Merged
Conversation
IReadBuffer.CopyTo and ArrayPoolListWriteBuffer.WriteTo only copy into their destination, but without `scoped` the compiler must assume a ref struct receiver could keep it. Passing stack memory then failed with CS8350 whenever the buffer outlived the call: a buffer built over heap memory, one reached by ref, or any buffer through the generic `allows ref struct` path, which goes by the interface member's signature. The interface member, all four implementations, their private CopyToSlow helpers and both WriteTo overloads now take `scoped Span<byte>`. Parameters that constructors store (scratch, the span inputs) stay unscoped. A ref struct that implements IReadBuffer must now declare the parameter `scoped` too, or the compiler reports CS8987. Plain struct implementations and compiled binaries are unaffected, since `scoped` is only an attribute on the parameter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reported from the MessagePack for C# v4 work against 1.3.1: on net9+, passing stack memory to
IReadBuffer.CopyToorArrayPoolListWriteBuffer.WriteTofails to compile, so MessagePack had to work around it in two places.Problem
Both methods only copy into
destination. Withoutscoped, though, the compiler must assume that a ref struct receiver could store the span in itself. So passing a stackalloc'd span fails with CS8350 whenever the buffer can outlive the call. This was reproduced for:ref TReadBuffer(allows ref struct) path, which checks against the interface member's signatureReadOnlySpanReadBuffer/ReadOnlySequenceReadBufferlocal built over heap memoryArrayPoolListWriteBuffer.WriteToon a local with heap scratch, or on arefparameterChange
The following now take
scoped Span<byte> destination:IReadBuffer.CopyToCopyToSlowhelpers (ascopedspan cannot be passed on to an unscoped parameter of the same ref struct)ArrayPoolListWriteBuffer.WriteToandCompatibleArrayPoolListWriteBuffer.WriteToThe doc comments and the README (interface listing and the custom-implementation contract table) note the new rule.
Audit of the rest of the public surface
ReadOnlySpanReadBuffer(ReadOnlySpan),SpanWriteBuffer(Span),ReadOnlySequenceReadBuffer(ReadOnlySpan), thescratchparameters,BufferSegmentsctorReadOnlySequenceReadBuffer(scoped in ReadOnlySequence<byte>, ...)TryGetSpan/TryGetNextoutparametersoutis implicitly scopedCompatibleReadOnlySequenceReadBuffer(in ReadOnlySequence<byte>)scopedwould change nothingGetReferenceextensionCompatibility (please review)
ref structthat implementsIReadBufferwithoutscopedonCopyTonow fails with CS8987. The fix is to addscoped. Plain struct implementations are not affected (verified). Since custom implementations are a documented extension point, this probably warrants a minor version bump rather than 1.3.2.scopedis encoded asScopedRefAttributeon the parameter, and the IL signature is the same.Tests
ScopedDestinationTestpasses stackalloc'd spans toCopyToon all four read buffers (generic and concrete, including the segment-straddlingCopyToSlowpath), and toWriteToon a local and arefparameter (scratch plus pooled segments).scopedremoved, the file fails to compile with CS8350 at all five call shapes (verified locally).🤖 Generated with Claude Code