[naot] [Runtime async] Support for covariant override of Task -> Task<T>#126768
[naot] [Runtime async] Support for covariant override of Task -> Task<T>#126768eduardo-vp merged 18 commits intodotnet:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Mirrors the CoreCLR runtime-async fix for covariant overrides (Task base overridden by Task<T> derived) into the NativeAOT type system by introducing a return-dropping async thunk and wiring it into virtual/interface resolution, and re-enables the previously NativeAOT-disabled test.
Changes:
- Add
ReturnDroppingAsyncThunkand a corresponding IL stub emitter that calls theT-returning async variant and discards the result. - Update NativeAOT async-aware virtual/interface method resolution to select the return-dropping thunk when the async slot is
void-returning but the resolved override isT-returning. - Re-enable the covariant-return async test project for NativeAOT.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/tests/async/covariant-return/covariant-returns.csproj | Re-enables building the test under NativeAOT. |
| src/coreclr/vm/asyncthunks.cpp | Adds a comment noting parity with the managed type system emitter. |
| src/coreclr/tools/Common/TypeSystem/IL/Stubs/AsyncThunks.cs | Adds IL emission for the return-dropping async thunk. |
| src/coreclr/tools/Common/TypeSystem/IL/NativeAotILProvider.cs | Routes ReturnDroppingAsyncThunk to the new IL emitter. |
| src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.Async.cs | Wraps resolved async variants with a return-dropping thunk for Task -> Task<T> async-slot mismatches; adds caching. |
| src/coreclr/tools/Common/Compiler/AsyncMethodVariant.Mangling.cs | Adds prefix mangling support for ReturnDroppingAsyncThunk. |
| src/coreclr/tools/Common/Compiler/AsyncMethodVariant.cs | Introduces ReturnDroppingAsyncThunk type and updates async-thunk classification helpers. |
|
Tagging subscribers to this area: @agocke, @dotnet/ilc-contrib |
CI is not failing because the test is still disabled (I assume there was a merge conflict with the R2R disablement) |
Ah yes, I locally updated the project and tested the native aot compiled test. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 25 out of 25 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs:127
GenericMethodsHashtableNode.GetMethodForMetadatacurrently asserts that the typical method definition is not aReturnDroppingAsyncThunkand always returnsisReturnDroppingAsyncThunk = false. This makes the newGenericMethodsHashtableConstants.IsReturnDroppingAsyncThunkflag effectively unreachable for generic-method dictionary lookups and will either trip the debug assert or prevent the runtime from finding dictionary entries for return-dropping async thunks (e.g., in generic covariant-return/GVM scenarios). Update this helper to unwrapReturnDroppingAsyncThunkthe same way asNativeLayoutVertexNode/ExactMethodInstantiationsNode(set the flag and return the underlying target method for metadata).
private static MethodDesc GetMethodForMetadata(MethodDesc method, out bool isAsyncVariant, out bool isReturnDroppingAsyncThunk)
{
MethodDesc result = method.GetTypicalMethodDefinition();
Debug.Assert(!(result is ReturnDroppingAsyncThunk));
isReturnDroppingAsyncThunk = false;
if (result is AsyncMethodVariant asyncVariant)
{
isAsyncVariant = true;
return asyncVariant.Target;
}
isAsyncVariant = false;
return result;
|
Given the latest commits, it looks like generic virtual methods are failing on CoreCLR. If the changes for Native AOT look fine, should we file an issue and disable the test? |
// If this assert fires, we may just need to add a lookup that matches AsyncMethodFlags::ReturnDroppingThunk
// It does not look like there is a scenario for directly calling ReturnDroppingThunk right now.
_ASSERTE(!pPrimaryMD->IsReturnDroppingThunk());It looks like we found a scenario involving GVM where we need to lookup for a return dropping thunk. Yes, log an issue and disable the test on CorCLR. |
|
This will break the following program (that worked before the PR): class Program
{
interface IFoo
{
Task<int> AsyncInterfaceMethod<T>();
}
class Foo : IFoo
{
async Task<int> IFoo.AsyncInterfaceMethod<T>()
{
await Task.Yield();
return typeof(T).FullName.Length;
}
}
static async Task Main()
{
IFoo f = new Foo();
int x = await f.AsyncInterfaceMethod<object>();
Console.WriteLine(x);
}
}We should add this test and fix the bug (the bug is that the logic that chooses return-dropping thunk in System.Private.TypeLoader doesn't match the logic in the compiler in WrapAsAsyncVariant). |
|
/azp run runtime-nativeaot-outerloop |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Co-authored-by: Michal Strehovský <MichalStrehovsky@users.noreply.github.com>
Mirrors work in #125900 for Native AOT.
Fixes #126685.