Fix TypeLoadException in .NET 11 Preview 7 with DotNext threading - #134460
Conversation
|
Azure Pipelines: Successfully started running 3 pipeline(s). 13 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
Co-authored-by: VSadov <8218165+VSadov@users.noreply.github.com>
|
Tagging subscribers to this area: @agocke |
|
@copilot - does NativeAOT needs a separate fix for the same issue/test? |
|
@copilot - the original repro mentions can we have an additional repro scenario with a shape similar to that? |
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
Interface/default-interface-method coverage or justification remains unresolved.
Review effort: Lite
Findings: None
What changed in this PR
Fixes a CoreCLR TypeLoadException involving abstract covariant Task overrides.
Changes:
- Masks
mdAbstracton return-dropping thunks. - Adds method and property regression tests.
| File | Summary |
|---|---|
src/tests/async/covariant-return/covariant-returns.cs |
Adds abstract covariant override coverage. |
src/coreclr/vm/method.cpp |
Corrects synthesized thunk attributes. |
Co-authored-by: VSadov <8218165+VSadov@users.noreply.github.com>
No separate NativeAOT fix is needed. NativeAOT resolves the async slot to the concrete override first and then wraps that resolved implementation in
Added |
Co-authored-by: VSadov <8218165+VSadov@users.noreply.github.com>
|
@jakobbotsch - could you take a look at this PR |
|
/backport to release/11.0 |
|
Started backporting to |

Fixes a
TypeLoadException("does not have an implementation") thrown when loading a concrete type whose base hierarchy contains an abstract covariantTask→Task<T>override (the DotNext.Threading failure reported in the issue).Root cause
For a covariant
Task→Task<T>virtual override,MethodTableBuilder::EnumerateClassMethodssynthesizes a third MethodDesc — a return-dropping thunk — whose void-returning signature MethodImpl-overrides the base's void-returning async variant. All three MethodDescs share the same metadata token, andMethodDesc::GetAttrs()reads attributes straight from metadata. When the covariant override is declaredabstract, the synthesized thunk therefore also reportsmdAbstract, even thoughEmitReturnDroppingThunkalways emits a body (CALLVIRT to theT-returning async variant + POP + RET).A concrete derived type's own
Task<T>override matches the abstract declaration exactly, so no MethodImpl and no additional variant is created for it — nothing ever implements the inherited "abstract" thunk slot, andVerifyVirtualMethodsImplementedfails the type load.Fix
MethodDesc::GetAttrs()now masks offmdAbstractfor return-dropping thunks. Patching the single choke point keeps the VM, JIT (CORINFO_FLG_ABSTRACT),MayHaveNativeCode()/MayHavePrecode()and default-interface-method resolution consistent. Async variants are filtered out of reflection, so the adjusted attributes are not observable from managed code../build.sh clr+libs -lc release -rc checked) + Core_Root layoutMethodDesc::GetAttrs()src/tests/async/covariant-return/covariant-returns.cs(abstract covariant method override + abstract covariant property override, theget_Taskshape from the issue)TypeLoadException)Not verified: only linux-x64 Checked was built/tested; no test trees outside
src/tests/asyncwere run;parallel_validationproduced no signal (code-review binary missing in the environment, CodeQL skipped bothcppandcsharpfor database size). The NativeAOT/crossgen2 path models this differently (CompilerTypeSystemContext.Async.cswraps the resolved implementation in aReturnDroppingAsyncThunk) and appears unaffected, but was reasoned about rather than tested; interface/DIM variants of this shape are likewise untested.Resolves #132971
Note
This pull request description was generated by GitHub Copilot.
TypeLoadException#132971