using System.Runtime.CompilerServices;
namespace XFESystem.Kernel;
/// <summary>Guest regression for real generic interface casting and dispatch; no runtime pointer substitutions.</summary>
internal static class RuntimeVarianceRegression
{
public static bool Run()
{
// The factories intentionally hide concrete types from the caller. The interface cast,
// enumeration and constructor must resolve at runtime in the actual bare-metal image.
object strings = CreateStringSet();
if (strings is not IEnumerable<object> covariant) return false;
int seen = 0;
foreach (object item in covariant)
{
if (!"XFE".Equals(item)) return false;
seen++;
}
if (seen != 1) return false;
var copied = new HashSet<object>(covariant);
if (copied.Count != 1 || !copied.Contains("XFE")) return false;
// Arrays permit this read-only interface use through the runtime's array-covariance rules.
object array = CreateStringArray();
if (array is not IList<object> arrayView || arrayView.Count != 1 || !"Array".Equals(arrayView[0])) return false;
// Contravariance goes in the opposite direction; exercise the method after the cast too.
object comparer = CreateObjectComparer();
if (comparer is not IComparer<string> stringComparer || stringComparer.Compare("XFE", "System") != -7) return false;
// These conversions must remain rejected. Broadly accepting the same generic definition
// or boxing value-type arguments would make the positive cases unsafe.
if (CreateIntSet() is IEnumerable<object>) return false;
if (CreateStringList() is IList<object>) return false;
if (CreateObjectSet() is IEnumerable<string>) return false;
if (CreateStringComparer() is IComparer<object>) return false;
return true;
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static object CreateStringSet() => new HashSet<string> { "XFE" };
[MethodImpl(MethodImplOptions.NoInlining)]
private static object CreateStringArray() => new[] { "Array" };
[MethodImpl(MethodImplOptions.NoInlining)]
private static object CreateObjectComparer() => new ObjectComparer();
[MethodImpl(MethodImplOptions.NoInlining)]
private static object CreateIntSet() => new HashSet<int> { 42 };
[MethodImpl(MethodImplOptions.NoInlining)]
private static object CreateStringList() => new List<string> { "Invariant" };
[MethodImpl(MethodImplOptions.NoInlining)]
private static object CreateObjectSet() => new HashSet<object> { new object() };
[MethodImpl(MethodImplOptions.NoInlining)]
private static object CreateStringComparer() => new StringComparer();
private sealed class ObjectComparer : IComparer<object>
{
public int Compare(object? first, object? second) => -7;
}
private sealed class StringComparer : IComparer<string>
{
public int Compare(string? first, string? second) => 29;
}
}
using System.Runtime.CompilerServices;
namespace XFESystem.Kernel;
/// <summary>Guest regression for real generic interface casting and dispatch; no runtime pointer substitutions.</summary>
internal static class RuntimeVarianceRegression
{
public static bool Run()
{
// The factories intentionally hide concrete types from the caller. The interface cast,
// enumeration and constructor must resolve at runtime in the actual bare-metal image.
object strings = CreateStringSet();
if (strings is not IEnumerable<object> covariant) return false;
int seen = 0;
foreach (object item in covariant)
{
if (!"XFE".Equals(item)) return false;
seen++;
}
if (seen != 1) return false;
var copied = new HashSet<object>(covariant);
if (copied.Count != 1 || !copied.Contains("XFE")) return false;
// Arrays permit this read-only interface use through the runtime's array-covariance rules.
object array = CreateStringArray();
if (array is not IList<object> arrayView || arrayView.Count != 1 || !"Array".Equals(arrayView[0])) return false;
// Contravariance goes in the opposite direction; exercise the method after the cast too.
object comparer = CreateObjectComparer();
if (comparer is not IComparer<string> stringComparer || stringComparer.Compare("XFE", "System") != -7) return false;
// These conversions must remain rejected. Broadly accepting the same generic definition
// or boxing value-type arguments would make the positive cases unsafe.
if (CreateIntSet() is IEnumerable<object>) return false;
if (CreateStringList() is IList<object>) return false;
if (CreateObjectSet() is IEnumerable<string>) return false;
if (CreateStringComparer() is IComparer<object>) return false;
return true;
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static object CreateStringSet() => new HashSet<string> { "XFE" };
[MethodImpl(MethodImplOptions.NoInlining)]
private static object CreateStringArray() => new[] { "Array" };
[MethodImpl(MethodImplOptions.NoInlining)]
private static object CreateObjectComparer() => new ObjectComparer();
[MethodImpl(MethodImplOptions.NoInlining)]
private static object CreateIntSet() => new HashSet<int> { 42 };
[MethodImpl(MethodImplOptions.NoInlining)]
private static object CreateStringList() => new List<string> { "Invariant" };
[MethodImpl(MethodImplOptions.NoInlining)]
private static object CreateObjectSet() => new HashSet<object> { new object() };
[MethodImpl(MethodImplOptions.NoInlining)]
private static object CreateStringComparer() => new StringComparer();
private sealed class ObjectComparer : IComparer<object>
{
public int Compare(object? first, object? second) => -7;
}
private sealed class StringComparer : IComparer<string>
{
public int Compare(string? first, string? second) => 29;
}
}