Fix variant interface GVM resolution in managed type system#130218
Conversation
|
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
There was a problem hiding this comment.
Pull request overview
This PR adjusts the CoreCLR managed TypeSystem’s interface virtual method resolution so that interface slot selection for instantiated interface GVMs is performed on the generic method definition (and then the method instantiation is reapplied), avoiding incorrect target selection when multiple variant-compatible interface instantiations exist.
Changes:
- Update
MetadataVirtualMethodAlgorithmto resolve interface GVMs using the method definition and then re-instantiate the resolved target. - Add a new variance-focused regression test (plus optimized variant) under
src/tests/JIT/Generics/Variance.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/coreclr/tools/Common/TypeSystem/Common/MetadataVirtualMethodAlgorithm.cs | Resolves instantiated interface GVMs via the definition for slot selection, then reapplies method instantiation. |
| src/tests/JIT/Generics/Variance/variance_generic_virtual.cs | Adds a regression test covering multiple variant-compatible interface instantiations with generic interface methods. |
| src/tests/JIT/Generics/Variance/variance_generic_virtual.csproj | Adds the new JIT test project. |
| src/tests/JIT/Generics/Variance/variance_generic_virtual_o.csproj | Adds an optimized build variant of the same test. |
|
Test failure is #129871. @MichalStrehovsky Please take a look. |
|
/azp run runtime-nativeaot-outerloop, runtime-coreclr crossgen2 outerloop, runtime-coreclr outerloop |
|
Azure Pipelines successfully started running 3 pipeline(s). |
|
/ba-g filed #130286 on the crash in GC. it's unlikely to be related. |
|
I didn't merge copilot's spelling nit because then I can no longer approve or merge and that's not a good tradeoff. |
I didn't merge it either as that would require yet another long outerloop run and that's not a good tradeoff as well. |
|
Any eta on when this will be pushed into the a release? Currently dealing with this issue. What i found was when a class implements the same generic interface with different type arguments (e.g., Workaround that worked: The issue can be avoided by extracting the cast and method call into a separate generic helper method, which forces the JIT to resolve the correct interface method at runtime: private IHaveLevelSettings ResolveParent<TParent>()
where TParent : class, ICanBeIdentified, ICanBeEnumerated_Base<TParent>, IHaveLevelSettings
{
if (this is I_IsParent<TParent, LE_LevelSettings> typed)
{
return typed.ParentGaurantee();
}
throw new ServerException($"No I_IsParent<{typeof(TParent).Name}, LE_LevelSettings> implemented");
}Code that triggered the bug: Direct casting and calling in a switch statement: // This incorrectly called the wrong interface method
AP_Instance application = ((I_IsParent<AP_Instance, LE_LevelSettings>)this).ParentGaurantee();thankyou |
The issue you described doesn't seem to be the same issue here. Here it's an AOT-specific issue after enabling GVM devirt in .NET 11 preview7 (not released yet). In .NET 10 we don't devirtualize any GVM at all. Can you share a standalone repro in a new issue so that we can take a look? |
When resolving an instantiated interface GVM, we passed down the method generic instantiation. However, interface slot selection needs to be done on the GVM definition, otherwise it could resolve to whatever the first compatible interface slot we saw. This can produce the incorrect devirtualized target when a type implements an interface GVM with multiple variant-compatible instantiations.
Fixed it by stripping the method instantiation before resolving the interface slot.
The CoreCLR native type system already handles such cases well so we don't have any issue there.
Found this issue while I was working on GVM devirt for NAOT in #130202. See added tests for repro: previously it failed for the
CallOnBasecases. Tests are added to both the managed type system and the normal JIT tests to prevent future regressions in either side.cc: @MichalStrehovsky