-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Description
Description
When creating an inline array via a constructor that assigns the elements of the array, accessing said inline array via a spread element throws a System.AccessViolationException.
Reproduction Steps
For an inline array defined as:
[InlineArray(8)]
public struct InlineIntArray8
{
private int element0;
public InlineIntArray8()
{
for (int i = 0; i < 8; ++i)
{
this[i] = i;
}
}
}Then accessing the inline array such as:
InlineIntArray8 inlineArray = new();
ReadOnlySpan<int> readOnlySpan = [ 5, ..inlineArray ]; // AccessViolationExceptionNote that the AccessViolationException occurs only when using the spread element on the inline array which has at least one element assigned (this[i] = ...) in the constructor. This does not occur if the array elements are unassigned, nor when performing an implicit/explicit cast from the inline array to ReadOnlySpan<T>/Span<T>.
Expected behavior
The spread element should not throw an exception in this use-case.
Actual behavior
An exception of System.AccessViolationException is thrown when the inline array is accessed via the spread element (in a collection expression). Other uses of the inline array do not throw this exception.
Regression?
Unknown.
Known Workarounds
The inline array can be implicitly/explicitly cast to a span first, and then used by the spread element normally.
ReadOnlySpan<int> intermediateSpan = inlineArray;
ReadOnlySpan<int> targetSpan = [ 5, ..intermediateSpan ];
ReadOnlySpan<int> targetSpan2 = [ 5, ..((ReadOnlySpan<int>)inlineArray) ];targetSpan and targetSpan2 do not throw an exception.
Configuration
.NET 8
Visual Studio Community 2022 (64-bit) Version 17.8.1
Windows 11
VS version and OS do not seem to affect this issue.
Other information
Via StackOverflow, user Ivan Petrov reports that the spread element is compiled into the following:
Span<int>.Enumerator enumerator = ((Span<int>*)(&inlineArray))->GetEnumerator();That is, rather than constructing a new span from the inline array, an unsafe cast is performed, incorrectly mapping the inline array onto the memory layout of a Span<T>:
internal readonly ref T _reference;
private readonly int _length;Because the inline array does not match this layout in memory, the AccessViolationException is thrown.