[mono][jit] Resolve constrained static virtual calls in gshared methods.
Mostly fixes https://github.com/dotnet/runtime/issues/75801.
Some restrictions still remain, mostly methods with generic arguments like INegator`1<T>:NegateIfNeeded<Vector128<T>>.
/azp run runtime-wasm
Azure Pipelines successfully started running 1 pipeline(s).
/azp run runtime-wasm
Azure Pipelines successfully started running 1 pipeline(s).
This approach is not going to work, for example:
public class Tests
{
private interface INegator<T> where T : struct
{
static abstract bool NegateIfNeeded(bool equals);
}
private readonly struct DontNegate<T> : INegator<T> where T : struct
{
public static bool NegateIfNeeded(bool equals) {
Console.WriteLine (typeof (T));
Console.WriteLine (typeof (T));
Console.WriteLine (typeof (T));
Console.WriteLine (typeof (T));
return equals;
}
}
private readonly struct Negate<T> : INegator<T> where T : struct
{
public static bool NegateIfNeeded(bool equals) => !equals;
}
private static int IndexOfValueType<TValue, TNegator>()
where TValue : struct, INumber<TValue>
where TNegator : struct, INegator<TValue>
{
for (int j = 0; j < 1000; ++j) {
for (int i = 0; i < 100000; ++i)
TNegator.NegateIfNeeded (true);
}
return 0;
}
The AOT compiler will compile IndexOfValueType(TValue_BYTE, TNegator_INST). The IL sequence for the call is:
constrained. !!TNegator
call bool class Tests/INegator`1<!!TValue>::NegateIfNeeded(bool)
This PR will resolve the called method to:
Tests/DontNegate`1<T_BYTE>:NegateIfNeeded (bool)
where T_BYTE is the inner type variable of TNegator_INST.
The problem is that this type variable is not part of the calling method so at runtime, when we try to inflate Tests/DontNegate`1<T_BYTE>:NegateIfNeeded (bool) with the real type arguments (byte, Negate<byte>), it won't be inflated so we end up calling an open method.
Closing in favor of: https://github.com/dotnet/runtime/pull/76033