[cdac] Convert TypeHandle to the ITypeHandle interface#129800
Conversation
|
Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag |
There was a problem hiding this comment.
Pull request overview
This PR refactors cDAC’s type identity from a concrete TypeHandle struct to an ITypeHandle abstraction, enabling “synthetic” (reader-fabricated) handles for unloaded constructed types (Ptr/Byref/SZArray/Array) and updating the contracts/legacy layers/tests accordingly.
Changes:
- Introduces
ITypeHandle(+ null/synthetic/target-backed implementations) and updates contracts to traffic inITypeHandle. - Updates
RuntimeTypeSystem_1.GetConstructedTypeto synthesize constructed types on miss for Ptr/Byref/SZArray/Array. - Updates legacy SOS/DacDbi code and cDAC unit/dump tests to consume the new handle abstraction.
Reviewed changes
Copilot reviewed 52 out of 52 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/native/managed/cdac/tests/UnitTests/TypeDescTests.cs | Updates unit tests to use ITypeHandle and array-returning APIs. |
| src/native/managed/cdac/tests/UnitTests/SOSDacInterface5Tests.cs | Switches test setup to TargetTypeHandle. |
| src/native/managed/cdac/tests/UnitTests/RuntimeMutableTypeSystemTests.cs | Updates Moq setups and APIs to ITypeHandle. |
| src/native/managed/cdac/tests/UnitTests/ObjectTests.cs | Updates object contract tests to use TargetTypeHandle. |
| src/native/managed/cdac/tests/UnitTests/MethodTableTests.cs | Replaces TypeHandle usage with ITypeHandle across MT tests. |
| src/native/managed/cdac/tests/UnitTests/MethodDescTests.cs | Updates generic-instantiation test assertions to use ITypeHandle[]. |
| src/native/managed/cdac/tests/UnitTests/ExceptionTests.cs | Updates exception contract tests to use TargetTypeHandle. |
| src/native/managed/cdac/tests/UnitTests/DacDbiImplTests.cs | Updates DacDbi tests to use TargetTypeHandle and new APIs. |
| src/native/managed/cdac/tests/UnitTests/CodeVersionsTests.cs | Updates code versions test helpers to use ITypeHandle. |
| src/native/managed/cdac/tests/DumpTests/RuntimeTypeSystemDumpTests.cs | Updates dump tests to the ITypeHandle API surface. |
| src/native/managed/cdac/tests/DumpTests/ObjectiveCMarshalDumpTests.cs | Updates dump test to ITypeHandle. |
| src/native/managed/cdac/tests/DumpTests/IXCLRDataValueDumpTests.cs | Updates commentary/type references for ITypeHandle. |
| src/native/managed/cdac/tests/DumpTests/IXCLRDataMethodDefinitionDumpTests.cs | Updates dump test to ITypeHandle. |
| src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiObjectDumpTests.cs | Updates DacDbi dump tests and helpers to ITypeHandle. |
| src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiLoaderDumpTests.cs | Updates DacDbi loader dump test to ITypeHandle. |
| src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiExactTypeHandleDumpTests.cs | Updates exact-typehandle roundtrip dump test to ITypeHandle. |
| src/native/managed/cdac/tests/DumpTests/CCWDumpTests.cs | Updates CCW dump test wording and ITypeHandle usage. |
| src/native/managed/cdac/tests/DumpTests/AsyncContinuationDumpTests.cs | Updates continuation dump tests to ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs | Updates type/method name formatting to consume ITypeHandle and array-returning instantiation APIs. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs | Updates IXCLRDataProcess implementation to ITypeHandle and array-returning APIs. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs | Updates SOS DAC implementation to ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs | Updates signature formatting helpers to use ITypeHandle and array-returning APIs. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/IDacDbiInterface.cs | Updates interop struct comments to refer to ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/Helpers/HeapWalk.cs | Updates heap-walk helper to use ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs | Updates DacDbi implementation to use ITypeHandle and constructed-type synthesis. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodInstance.cs | Updates method instance implementation to use ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodDefinition.cs | Updates generic-instantiation checks to ITypeHandle[]. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataFrame.cs | Updates frame/type resolution paths to use ITypeHandle and array-returning instantiations. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/RuntimeTypeSystemHelpers/ExtensionMethods.cs | Adapts type-handle helper extensions to operate on ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcSignatureTypeProvider.cs | Updates GC signature decoding context and lookups to ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/FrameHelpers.cs | Updates frame helper logic to use ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/SignatureTypeProvider.cs | Updates signature type provider to produce/consume ITypeHandle and constructed types. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/Signature_1.cs | Updates signature contract implementation to decode to ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/IRuntimeSignatureTypeProvider.cs | Updates documentation for “internal type” handling to ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs | Adds TargetTypeHandle and SyntheticTypeHandle implementations of ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs | Core RuntimeTypeSystem changes: ITypeHandle plumbing + synthetic constructed-type behavior. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeMutableTypeSystem_1.cs | Updates mutable type system APIs to accept ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Object_1.cs | Updates object sizing/array logic to use ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ManagedTypeSource_1.cs | Updates managed type resolution/caching to ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ExecutionManager/ExecutionManagerCore.cs | Updates exception-clause reading path to use ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Exception_1.cs | Updates exception contract implementation to use ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ConditionalWeakTable_1.cs | Updates CWT contract implementation to use ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ComWrappers_1.cs | Updates RCW detection to use the renamed generated type-handle accessor. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CodeVersions_1.cs | Updates code-versions contract to use ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/ISignature.cs | Changes signature decoding contract to return ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs | Introduces ITypeHandle/NullTypeHandle and updates the RuntimeTypeSystem contract signatures. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeMutableTypeSystem.cs | Updates mutable-type-system contract signature to use ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IManagedTypeSource.cs | Updates managed type source contract to use ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/CdacAttributes.cs | Updates generator-related docs to refer to ITypeHandle. |
| src/native/managed/cdac/gen/TypeNameResolverSource.cs | Updates generated helper to return ITypeHandle. |
| src/native/managed/cdac/gen/Emitter.cs | Updates generated output to reference ITypeHandle. |
| src/native/managed/cdac/gen/CdacGenerator.cs | Updates generator docs to refer to ITypeHandle. |
1c85305 to
2050b89
Compare
Am I missing something, or where are you removing said side channels with this abstraction? If this is a helper for a PR that you have in progress, what does it look like before and after? |
I needed extra data for implementing the ArgIterator: https://github.com/dotnet/runtime/pull/129769/changes#r3468318817 I believe adding synthetic typehandles aligns with our long-term goal to not have to load things in the runtime just for diagnostics. |
Could we accomplish this by adding (optional) fields and properties to the TypeHandle struct? |
The |
2050b89 to
6522cf8
Compare
6522cf8 to
791163a
Compare
Ok, sounds good |
791163a to
ee5fa4e
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 60 out of 60 changed files in this pull request and generated 5 comments.
Comments suppressed due to low confidence (1)
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/CallingConvention_1.cs:245
- Using Address==TargetPointer.Null to detect “null handle” is no longer equivalent now that synthetic handles have Address==0 but IsNull==false. This should use IsNull (and preferably avoid Address comparisons for ITypeHandle entirely) to prevent misclassifying synthetic handles as missing/uncached handles.
ITypeHandle probe = methodSig.ParameterTypes[argIndex];
if (probe.Address == TargetPointer.Null)
probe = paramInfo[argIndex].OpenGenericType;
if (probe.Address != TargetPointer.Null)
{
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
c6446df to
5c47052
Compare
- Describe ELEMENT_TYPE_INTERNAL payloads as native runtime TypeHandles, which are resolved to cDAC ITypeHandles by the reader. - Restore native VMPTR_TypeHandle names in the DacDbi wire-layout comments. - Use explicit ImmutableArray<ITypeHandle> locals instead of var. - Remove redundant Contracts. qualifiers where the Contracts namespace is already imported. - Fix remaining "a ITypeHandle" grammar. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c
Keep the RuntimeTypeSystem collection API shape unchanged by using ReadOnlySpan<ITypeHandle> over cached ITypeHandle arrays. This removes the unnecessary ImmutableArray API churn and builder allocations from the TypeHandle-to-ITypeHandle conversion. Clear ManagedTypeSource's cached ITypeHandle values on every flush because RuntimeTypeSystem invalidates its canonical handle instances. Continue to retain immutable CoreLib type layouts and field descriptors across forward execution. Add dump-test coverage for canonical handle resolution after a forward flush. Also correct the remaining ITypeHandle documentation and native TypeHandle terminology. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c
- Default ArgumentLocation handle properties to ITypeHandle.Null so omitted object-initializer members preserve the old zero-handle semantics. - Compare TargetTypeHandle addresses with TargetPointer.Null. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c
Use the explicit TargetPointer null sentinel for type-handle address checks and the TypeDescAddress failure result. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c
Remove the stale System.Collections.Immutable using left after restoring ReadOnlySpan<ITypeHandle> in TypeDescTests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c
Use nullable backing fields with null-coalescing getters for TypeHandle and OpenGenericType. This preserves the old zero-valued TypeHandle behavior for new and default(ArgumentLocation), including zero-initialized arrays, without requiring an explicit parameterless struct constructor. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c
Keep ArgumentLocation as a plain readonly struct; its control-flow-specific consumers do not read omitted handle properties. Replace the remaining PR-added var declarations with explicit ITypeHandle/span types. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c
Use an explicit struct constructor with ITypeHandle.Null property initializers so object initializers that omit TypeHandle or OpenGenericType preserve the old zero-valued TypeHandle semantics. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c
Document that ELEMENT_TYPE_INTERNAL and ELEMENT_TYPE_CMOD_INTERNAL contain raw runtime TypeHandle pointers that the provider resolves to cDAC types. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c
There was a problem hiding this comment.
Holistic Review
Motivation: Unchanged from the initial review. The PR replaces the cDAC TypeHandle value struct with an ITypeHandle interface backed by TargetTypeHandle (an address-backed handle) and a NullTypeHandle singleton exposed via ITypeHandle.Null, laying groundwork for modeling handles not backed by a target address. The single new commit only refines a doc comment and does not alter the motivation.
Approach: Unchanged. IRuntimeTypeSystem and consumers switch every TypeHandle to ITypeHandle; RuntimeTypeSystem_1 interns TargetTypeHandle per address and moves TypeKey to reference identity; ManagedTypeSource_1 clears its handle cache on every flush; struct holders (ArgumentLocation, CdacTypeHandle) now hold reference fields. The new commit (#17, 2e2d66c) edits only two XML doc comments in IRuntimeSignatureTypeProvider.cs, clarifying that ELEMENT_TYPE_INTERNAL/ELEMENT_TYPE_CMOD_INTERNAL carry raw runtime TypeHandle pointers that the provider resolves to cDAC types. This is a documentation-only clarification with no behavioral or API effect.
Summary: TypeKey interning invariant and the latent NRE risk for a default-constructed CdacTypeHandle — remain the reasons this PR warrants a maintainer's confirmation. Those live in code unchanged by the new commit, so per re-review scope they are not re-raised as new actionable findings here; see the initial review for their details.
Assessment History
- review 4730716240 reviewed commit
07d5884with verdict Needs Human Review. Current verdict: Needs Human Review. Unchanged — the only new commit (2e2d66c) is a documentation-only clarification of two doc comments inIRuntimeSignatureTypeProvider.cs, leaving motivation, approach, and risk identical.
Detailed Findings
- No new actionable findings. The incremental diff (
07d5884..2e2d66c) touches only XML documentation comments and the wording is accurate: these element types do embed raw runtimeTypeHandlepointers that the type provider resolves. No correctness, performance, or API concerns arise from the change.
Note
This review was generated by this repository's Holistic Review agentic workflow to complement the built-in Copilot review.
Generated by Holistic Review · 52.4 AIC · ⌖ 10.7 AIC · ⊞ 10K
Document that unsupported type parameters return ITypeHandle.Null rather than a null reference. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 63 out of 63 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/CallingConvention_1.cs:464
ParamMetadataProviderproducesTrackedTypevalues whereOpenGenericis left unset for most element types (Wrap / byref / ptr / array). SinceOpenGenericis anITypeHandlereference, that means it can be a null reference at runtime.DecodeParamTypeInfothen copies this intoParamTypeInfo.OpenGenericType, andGetArgumentLayoutassigns it intoArgumentLocation.OpenGenericType, overwriting the= ITypeHandle.Nulldefault onArgumentLocation. This reintroduces the risk ofNullReferenceExceptionif any later code readsarg.OpenGenericType.Addresson an entry where the closed handle is null/uncached.
To preserve the old default(TypeHandle) semantics and the intended non-nullable contract, ensure TrackedType.OpenGeneric is always at least ITypeHandle.Null and propagate it through wrappers.
private static TrackedType Wrap(ITypeHandle th)
=> new() { Underlying = th };
public TrackedType GetByReferenceType(TrackedType elementType)
=> new() { Underlying = elementType.Underlying, IsByRef = true,
OutermostKind = CdacCorElementType.Byref };
There was a problem hiding this comment.
Holistic Review
Motivation: Unchanged from prior reviews. The PR replaces the cDAC TypeHandle value struct with an ITypeHandle interface backed by TargetTypeHandle (an address-backed handle) and a NullTypeHandle singleton exposed via ITypeHandle.Null, laying groundwork for modeling handles not backed by a target address. The single new commit only refines a code comment and does not alter the motivation.
Approach: Unchanged. IRuntimeTypeSystem and consumers switch every TypeHandle to ITypeHandle; RuntimeTypeSystem_1 interns TargetTypeHandle per address and moves TypeKey to reference identity; ManagedTypeSource_1 clears its handle cache on every flush; struct holders (ArgumentLocation, CdacTypeHandle) now hold reference fields. The new commit (#18, b67eb50) edits a single trailing comment on the ITypeHandle inspection region in IRuntimeTypeSystem.cs, changing "Returns null if the ITypeHandle is not a class/struct/generic variable" to "Returns ITypeHandle.Null if the handle is not a class, struct, or generic variable." This is a documentation-only clarification with no behavioral or API effect.
Summary: GetTypeParam) now return ITypeHandle.Null rather than a null reference, so the comment now correctly names the sentinel. The two previously identified semantic subtleties from the value→reference conversion — the reference-identity TypeKey interning invariant and the latent NRE risk for a default-constructed CdacTypeHandle — remain the reasons this PR warrants a maintainer's confirmation. Those live in code unchanged by the new commit, so per re-review scope they are not re-raised as new actionable findings here; see the initial review for their details.
Assessment History
- review 4730716240 reviewed commit
07d5884with verdict Needs Human Review. Current verdict: Needs Human Review. Unchanged — the new commit is a documentation-only comment clarification, leaving motivation, approach, and risk identical. - review 4737835307 reviewed commit
2e2d66cwith verdict Needs Human Review. Current verdict: Needs Human Review. Unchanged — the only new commit (b67eb50) edits one comment inIRuntimeTypeSystem.csto name theITypeHandle.Nullsentinel, with no behavioral, API, or risk change.
Detailed Findings
- No new actionable findings. The incremental diff (
2e2d66c..b67eb50) touches only a single source comment on theITypeHandleinspection region, and the revised wording accurately reflects the refactor's null-sentinel semantics. No correctness, performance, or API concerns arise from the change.
Note
This review was generated by this repository's Holistic Review agentic workflow to complement the built-in Copilot review.
Generated by Holistic Review · 60.7 AIC · ⌖ 16 AIC · ⊞ 10K
noahfalk
left a comment
There was a problem hiding this comment.
I think its fine to check this in and unblock yourself, but I think its worth considering if using reference null to implement a null type would be better than a non-null sentinel object.
Co-authored-by: Noah Falk <noahfalk@users.noreply.github.com>
Co-authored-by: Noah Falk <noahfalk@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 63 out of 63 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/CallingConvention_1.cs:463
TrackedType.OpenGeneric/ParamTypeInfo.OpenGenericTypeare non-nullable, but mostTrackedTypefactories (e.g.,Wrap,GetByReferenceType,GetPointerType, array helpers) never setOpenGeneric. BecauseITypeHandleis a reference type, that meansOpenGenericcan be a null reference at runtime (unlike the oldTypeHandlestruct default), which then flows intoParamTypeInfo.OpenGenericTypeandArgumentLocation.OpenGenericTypeand can causeNullReferenceExceptionif any code reads.Address/.IsNullon it. InitializeOpenGenerictoITypeHandle.Nullby default and propagate it through wrapper constructors.
private static TrackedType Wrap(ITypeHandle th)
=> new() { Underlying = th };
public TrackedType GetByReferenceType(TrackedType elementType)
=> new() { Underlying = elementType.Underlying, IsByRef = true,
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 63 out of 63 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/CallingConvention_1.cs:464
TrackedType.OpenGenericis a non-nullableITypeHandle, but mostTrackedTypevalues are created viaWrap(...)/ wrapper helpers without setting it. That leavesOpenGenericas a null reference, which then flows intoParamTypeInfo.OpenGenericTypeand overridesArgumentLocation.OpenGenericType(which is intentionally defaulted toITypeHandle.Null). Later code reads.Addresson these values (e.g.probe = arg.OpenGenericType; if (probe.Address == ...)), so a null here can surface as aNullReferenceException.
Fix by ensuring Wrap initializes OpenGeneric to ITypeHandle.Null and that wrapper helpers propagate elementType.OpenGeneric so the value is never null (and generic-instantiation metadata isn’t lost through wrappers).
private static TrackedType Wrap(ITypeHandle th)
=> new() { Underlying = th };
public TrackedType GetByReferenceType(TrackedType elementType)
=> new() { Underlying = elementType.Underlying, IsByRef = true,
OutermostKind = CdacCorElementType.Byref };
docs/design/datacontracts/Signature.md:57
- Grammar: use “an” before “ITypeHandle”.
Decoding a signature follows the ECMA-335 §II.23.2 grammar. For all standard element types, decoding behaves identically to `System.Reflection.Metadata.SignatureDecoder<TType, TGenericContext>`. When the decoder encounters one of the runtime-internal tags above, it reads the target-sized pointer to a runtime `TypeHandle` (and optional `required` byte for `ELEMENT_TYPE_CMOD_INTERNAL`) from the signature blob and resolves it to a `ITypeHandle`.
Represent the absence of a type with C# null rather than a non-null sentinel. This removes ITypeHandle.Null, NullTypeHandle, and ITypeHandle.IsNull, and uses nullable annotations to document the APIs and fields where type resolution may fail. - Make constructed/approximate/signature resolution results nullable. - Annotate ManagedTypeSource TryGetTypeHandle with NotNullWhen(true). - Propagate nullable signature types through providers and calling-convention metadata while keeping loaded runtime instantiations non-null. - Update DacDbi/Legacy consumers and dump tests to use is null/is not null. - Update authoritative contract documentation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c
Document that canonical reference identity is scoped to a target cache epoch, fix nullable ITypeHandle grammar, and replace an implicit null-forgiving invariant with an actionable runtime guard. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c
Update the authoritative pseudocode to use nullable ITypeHandle and MetadataReader outputs with NotNullWhen(true), matching the contract and implementation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 63 out of 63 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs:2466
IRuntimeTypeSystem.GetTypeHandlenow throws for a 0/invalid handle, soEnumerateClassFieldswill start returningE_INVALIDARGinstead of the nativeCORDBG_E_CLASS_NOT_LOADEDwhenthExact == 0(previously handled viaTypeHandle.IsNull). Consider explicitly mapping the null-handle sentinel before calling into the contract to preserve the legacy HRESULT semantics.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs:2520EnumerateInstantiationFieldspreviously treated a null/zerovmThApproxasCORDBG_E_CLASS_NOT_LOADED(TypeHandle.IsNullcheck). WithITypeHandle,GetTypeHandle(0)throws and the catch will surface itsHResult(likelyE_INVALIDARG) instead. Add an explicitvmThApprox == 0guard to preserve the intended HRESULT behavior for unloaded/unknown types.
|
/ba-g build analysis stuck |
Summary
Converts the cDAC
TypeHandlevalue type into anITypeHandleinterface with a canonical, target-backed implementation (TargetTypeHandle). This is a foundational refactor; synthetic (reader-fabricated) type handles for unloaded constructed types are deferred to a follow-up PR.Absent or unresolved types use standard C# nullable-reference semantics (
ITypeHandle?/null). Non-null handles are canonical identities produced and interned byRuntimeTypeSystemwithin a target cache epoch.Motivation
This change is primarily enabling groundwork. Turning
TypeHandleinto an interface lets the Runtime Type System (RTS) contract grow in two directions that the current value-type shape cannot accommodate:ITypeHandleimplementations without changing every consumer when the representation evolves.Ptr/Byref/SzArray/Array, and later generic instantiations) that are not loaded in the target. A polymorphicITypeHandlelets RTS fabricate a queryable handle instead of relying on ad-hoc side channels.Behavior note
The old struct compared by address value. The new handles use canonical reference identity: repeated
GetTypeHandlecalls for the same address return the same object untilTarget.Flushinvalidates the cache. Resolving the same address after a flush may return a different object reference. This identity change is intentional and prevents future handle implementations from having to coordinate cross-implementation value equality.Changes
TypeHandle->ITypeHandleacross cDAC type references (members namedTypeHandleremain unchanged).ITypeHandleinterface in Abstractions (Address).TargetTypeHandleimplementation for real target-backed handles.GetTypeHandlecalls return the same canonical instance within a cache epoch.ReadOnlySpancollection API shapes.Why split it this way
The original draft also added synthetic handles and reworked calling-convention side channels in one change. Splitting out the interface conversion keeps this PR focused; synthetic-handle behavior and its downstream simplifications can build on the stable
ITypeHandleabstraction in a follow-up.Testing
Note
This PR description and the changes were produced with the assistance of GitHub Copilot.