I am using a SequenceReader<T>
to copy contents from a ReadOnlySequence<T>
into different Span<T>
. However, I get a compiler error when I try to encapsulate the copy logic into a separate function and want to call it with a Span<T>
allocated on the stack.
var sequence = new ReadOnlySequence<byte>(new byte[20]); // Source data to copy
Span<byte> heap = new byte[10]; // Target location 1
Span<byte> stack = stackalloc byte[10]; // Target location 2
var reader = new SequenceReader<byte>(sequence);
TryReadInto(ref reader, heap); // This is fine
TryReadInto(ref reader, stack); // Gives compile time error CS8350
Since the instance method TryCopyTo
on SequenceReader<T>
does not advance the reader, I have created a higher level function that takes care of that:
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static bool TryReadInto(ref SequenceReader<byte> reader, Span<byte> destination)
{
if (reader.TryCopyTo(destination)) {
reader.Advance(destination.Length);
return true;
}
return false;
}
As long as the destination is heap allocated everything works fine. But when the destination is allocated using stackalloc
the compiler complains with a CS8350: This combination of arguments to is disallowed because it may expose variables referenced by parameter outside of their declaration scope.
When I do not pass the reader as reference that compiler error goes away, but it is required for the reader to be passed as reference since SequenceReader<T>
is a mutable struct and the position is advanced within the function.
I get the compiler error. Parameter reader
could be allocated in an earlier stack frame and as a ref-like struct would be able to have a Span<T>
as a field. The method body could make the second (stack-allocated) parameter destination
escape it's own stack frame, thus a function call with both a ref
-parameter and a stack-allocated Span<T>
is illegal in C#.
However, how am I able to encapsulate my logic then? SequenceReader<T>
is a closed type so I can't just add an instance method. When I just inline the function call manually I do not get compiler errors. I guess the compiler sees that the reader is allocated in the same stack frame as the stack-allocated Span<byte>
. Passing the reader by value is not an options since SequenceReader<T>
is a mutable struct.