You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue tracks the runtime core team part of work on static interface methods. The broader implementation of this feature spanning other parts of the stack (JIT, Roslyn, libraries) are tracked separately. (Reference needed)
Update the ECMA addendum to cover static interface methods, their behavior and resolution;
Define positive and negative testing scenarios for the feature to run as CoreCLR IL-based tests (Roslyn support doesn't yet exist);
Coordinate with the JIT team regarding the new behavior of .constrained call / .constrained ldftn instruction;
Implement runtime changes to the typesystem and JIT interface to support compilation and runtime resolution of static interface methods;
Basic Functionality
Adjust JIT processing for the ldftn and call instructions to permit them to work with a constrained. prefix and pass the constrained type to the getCallInfo function.
Write a function to perform a static resolution given an implementing type, and an interface static method. Place this method into the MethodTable codebase. Call it MethodTable::ResolveStaticVirtualMethod(MethodDesc interfaceMethod)
This function shall process MethodImpls walking the type hierarchy. Be sure to properly handle covariant returns.
Adjust getCallInfo to have special handling for constrained ldftn and constrained call instructions.
If the constrained type is sufficiently well known to resolve to exactly one target method using MethodTable::ResolveStaticVirtualMethod, resolve to that target, and return the appropriate details to call that method directly.
If the constrained type is a shared generic which is insufficiently precise to specify only 1 possible target method, follow the path that returns CORINFO_CALL_CODE_POINTER (R2R implementation may be slightly different)
Adjust the type loader to allow abstract static methods to exist on interface types. Set a flag (HasStaticVirtualMethods) on the interface type to indicate that these methods exist.
Adjust normal MethodImpl processing to ignore MethodImpls which refer to static methods
Negative checking
In the same place as covariant return processing return type validation, if the type is non-abstract loop through all the interfaces that have the HasStaticVirtualMethods flag set. For each static abstract method on those interfaces, make sure it is implemented. If the interface was implemented on a base type which is also concrete, then this logic may be skipped.
In the constraint checker, if the type is abstract verify that interface constraints which have the HasStaticVirtualMethods flag set are fully implemented.
Basic optimization
Add a hashtable of interface method and constraint type which is filled in as ResolveStaticVirtualMethod is run. Future executions with the same parameters should be able to simply use the value in the hash.
Add a hashtable of concrete type, interface type to improve the performance of the constraint checker extra logic.
Reflection support
The implementation of GetInterfaceMap() will need to handle these new static interface methods.
Fix issues around TypeBuild.CreateType so that these new overrides can be implemented
Implement changes to the Crossgen2 JIT interface to support CG2 compilation of static interface methods;
Crossgen2 constraint checker update
R2R format update to handle new case (I'm not sure if its necessary, but we may need a new R2R fixup)
Crossgen2 jit interface updates
Implement the proposed set of tests and use them to validate the expected compilation / runtime behavior.
Test calls between generic contexts (Implement as autogenerator)
Generic over reference type
Generic over value type
Generic over constrained type which is instantiated as a reference type
Generic over constrained type which is instantiated as a valuetype
Curiously recurring pattern various incarnations thereof
Shared generic where the exact constrained type and interface type of the call are both reference types.
Test override with various different type hierarchies (Implement as autogenerator)
Test MethodBody of MethodImpl on MethodImpl defining type
Test MethodBody of MethodImpl on non-generic base type of MethodImpl defining type
Test MethodBody of MethodImpl on generic base type of MethodImpl defining type where base type is exactly defined
Test MethodBody of MethodImpl on generic base type of MethodImpl defining type where base type is a generic type defined by the generic parameters of MethodImpl defining type
Test covariant override (share autogenerator with normal type hierarchy testing)
Test covariant override where override is implemented on MethodImpl defining type (non-generic)
Test covariant override where override is implemented on MethodImpl defining type (generic over reference type)
Test covariant override where override is implemented on MethodImpl defining type (generic over value type)
Test covariant override where override is implemented on MethodImpl base type (non-generic)
Test covariant override where override is implemented on MethodImpl base type (generic case)
Positive Type equivalence test case
Positive test case, variant use of interface static method
Positive test case, verify that name/sig match static method on derived type has no effect on method dispatch of interface MethodImpl defined on base type
ReadyToRun Version resilience test
Verify that change in override produces correct result
Verify that adding a new override on the most derived class (where there was none before and the MethodImpl was only present on the Base class) works
Negative test case MethodBody defined on unrelated type
Negative test case, multiple MethodImpl records with same MethodDecl
Negative test case, non-abstract static virtual method on interface type
Negative test case, abstract virtual method on class type
Negative test case, non-abstract virtual method on class type
Negative test case, abstract static interface method which violates variance safety rule
Negative test case, non-implemented static abstract interface method on non-abstract class
Negative test case, non-implemented static abstract interface method on abstract class used concrete instantiation
Reflection testing
Test behavior of Type.GetInterfaceMap()
Test MethodInfo.Invoke on abstract static method -> Should throw
Test MethodBase.IsVirtual and MethodBase.IsAbstract -> Should show presence of static interface methods
Test PropertyInfo.GetValue/SetValue -> Should throw in presence of static interface methods
Reflection.Emit testing
Test behavior of TypeBuilder.DefineMethod to allow definition of abstract virtual static method
Test behavior of TypeBuilder.DefineMethodOverride to ensure that it works for defining override for method defined on type
Test behavior of TypeBuilder.DefineMethodOverride to ensure that it works for defining override for method defined on base type
This issue tracks the runtime core team part of work on static interface methods. The broader implementation of this feature spanning other parts of the stack (JIT, Roslyn, libraries) are tracked separately. (Reference needed)