-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[mono] Use underlying type in RuntimeHelpers.GetSpanDataFrom (#87019)
* [mono] Use underlying type in RuntimeHelpers.GetSpanDataFrom Make it work correctly for spans of enums Fixes #86865 Note that in net8 RuntimeHelpers.CreateSpan<T> is an intrinsic, so GetSpanDataFrom is never called directly. But in net7 CreateSpan is not intrinsified on Mono, so the underlying method really does get called. * test: Print all hidden field names if we can't find the right one
- Loading branch information
1 parent
9d55017
commit 75a1806
Showing
3 changed files
with
80 additions
and
1 deletion.
There are no files selected for viewing
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
using System; | ||
using System.Reflection; | ||
|
||
namespace test86865; | ||
|
||
public class test86865 | ||
{ | ||
public static int Main() | ||
{ | ||
|
||
// Regression test for https://github.com/dotnet/runtime/issues/86865 | ||
// Verify that the RuntimeHelpers.GetSpanDataFrom method underlying RuntimeHelpers.CreateSpan<T> | ||
// works correctly with enums. | ||
|
||
ReadOnlySpan<MyEnum> myEnums = new[] | ||
{ | ||
MyEnum.A, | ||
MyEnum.B, | ||
MyEnum.C, | ||
MyEnum.B, | ||
MyEnum.C, | ||
}; | ||
|
||
if (string.Join(", ", myEnums.ToArray()) != "A, B, C, B, C") | ||
return 1; | ||
|
||
var types = new Type[] { | ||
typeof(RuntimeFieldHandle), | ||
typeof(RuntimeTypeHandle), | ||
typeof(int).MakeByRefType(), | ||
}; | ||
var mi = typeof(System.Runtime.CompilerServices.RuntimeHelpers).GetMethod("GetSpanDataFrom", BindingFlags.Static | BindingFlags.NonPublic, types); | ||
if (mi == null) | ||
return 2; | ||
|
||
var pid = typeof(MyEnum).Assembly.GetType("<PrivateImplementationDetails>"); | ||
if (pid == null) | ||
return 3; | ||
|
||
var fi = pid.GetField("0B77DC554B4A81403D62BE25FB5404020AD451151D4203D544BF60E3FEDBD8AE4", BindingFlags.Static | BindingFlags.NonPublic); | ||
if (fi == null) | ||
{ | ||
Console.WriteLine("Could not find the expected array data in <PrivateImplementationDetails>. The available static non-public fields are:"); | ||
foreach (var f in pid.GetFields(BindingFlags.Static | BindingFlags.NonPublic)) { | ||
Console.WriteLine($" - '{f}'"); | ||
} | ||
return 4; | ||
} | ||
|
||
var parms = new object[] { | ||
fi.FieldHandle, | ||
typeof(MyEnum).TypeHandle, | ||
new int() | ||
}; | ||
var result = mi.Invoke(null, parms); | ||
if (result == null) | ||
return 6; | ||
if ((int)parms[2] != myEnums.Length) | ||
return 7; | ||
|
||
return 100; | ||
} | ||
} | ||
|
||
enum MyEnum | ||
{ | ||
A, | ||
B, | ||
C | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<Compile Include="test86865.cs" /> | ||
</ItemGroup> | ||
</Project> |