I was under the impression that static abstract method calls should compile to a simple call because the compiler can tell exactly what function is being called, and I don't understand why it is more complex than that.
You should note one thing - for reference types the generics are compiled only once(compared to the value types, where for every one passed as generic parameter the separate implementation will be compiled) to prevent code bloat (see this or this) and the same compiled code is used for all reference types used as generic type parameter, so compiler does not actually know exactly which function being called.
If you update your second snippet with several value and reference types (note that implementations are a bit different so the difference becomes more clear):
[JitGeneric(typeof(MyTestable))]
[JitGeneric(typeof(MyTestable11))]
[JitGeneric(typeof(MyTestable1))]
[JitGeneric(typeof(MyTestable2))]
public class MyTester<T> where T : ITestable {
public void RunTest() {
T.Test();
}
}
public class MyTestable: ITestable {
public static void Test() =>Console.WriteLine("Hello!");
}
public class MyTestable11: ITestable {
public static void Test() =>Console.Write("Hello!");
}
public struct MyTestable1: ITestable {
public static void Test() =>Console.WriteLine("Hello!");
}
public struct MyTestable2: ITestable {
public static void Test() =>Console.Write("Hello!");
}
You will see that for all reference types the same MyTester`1[[System.__Canon, System.Private.CoreLib]].RunTest()
is emmited while for value types you will have separate ones:
MyTester`1[[MyTestable1, _]].RunTest()
L0000: mov ecx, [0x8d2daa0]
L0006: call dword ptr [0x10a29ac8]
L000c: ret
MyTester`1[[MyTestable2, _]].RunTest()
L0000: mov ecx, [0x8d2daa0]
L0006: call dword ptr [0x10a29cc0]
L000c: ret
Code @sharplab.io
As for the question in title - my guess is that docs were not updated to support the introduction of the static abstract methods in the interfaces (note - the docs are not always correct, even I have bumped into several such cases - for example github PR 1, github PR 2, github PR 3, or even for the IL OpCodes
- github issue for OpCodes.Ldind_I8)
Created a new issue for docs @github.
UPD
As written in the answer by @Charlieface there is another piece of documentation which explains the usage of the constrained
in this case.