Skip to content

Retire legacy type forwarder resolver - #3898

Merged
richlander merged 15 commits into
mainfrom
cleanup/retire-forwarder-migration
Aug 9, 2026
Merged

Retire legacy type forwarder resolver#3898
richlander merged 15 commits into
mainfrom
cleanup/retire-forwarder-migration

Conversation

@richlander

@richlander richlander commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Summary

The structured type-forwarding architecture is complete: this removes the last parallel path/string-based resolver and migrates its sole consumer, ReturnToSender external-interface planning, to TypeResolutionContext.

  • preserves the harness's Any-then-Platform binding behavior while carrying an exact resolved assembly descriptor and durable TypeDef address
  • keeps planning consistent with Roslyn's sibling-first compilation closure when structured resolution tightens a signed forwarder hop to Platform
  • moves AssemblyResolutionScope to its own contract file and removes TypeLocation, the resolver implementation, and its duplicate tests
  • adds end-to-end gates for nested forwarded declarations, a load-bearing forwarded external base interface, and a signed-platform/confusable-sibling candidate mismatch
  • updates the authoritative design and decompiler docs to mark all six architecture slices delivered and name their enforcing gates

Product decompiler behavior is unchanged; it already used the structured engine. The removed public types belong to an internal library with no external API-stability contract.

Evidence

  • dotnet build dotnet-inspect.slnx -c Release --no-restore
  • Metadata: 1,282 passed
  • inspection workspace/query suite: 20 passed
  • Analysis: 567 passed
  • affected Decompiler suites: 225 passed (ReturnToSenderPrototypeTests, CrossAssemblyMethodFactsTests, TypeRefDecoderCanonicalReferencedTests)
  • changed Markdown passes markdownlint
  • mutation proofs:
    • inserting Environment.FailFast at ResolveExternalTypeDefinition terminates the forwarded-base fixture
    • deleting the candidate-consistency check makes ResolveExternalTypeDefinition_DeclinesWhenPlatformSelectionDiffersFromCompilationClosure fail by returning the TPA System.Text.Json definition instead of declining

The nested engine gate resolves #3458 and #3480. Removing the alias/path compatibility layer retires #3479, #3598, and #3605.

Two downstream boundaries remain intentionally open and are not claimed by this retirement: #3513 still tracks forwarded non-core-library parameter types in direct Callers, while graph correspondence already resolves every named signature type; #3578 still tracks general physical-file identity, an explicit design non-goal.

Closes #3458
Closes #3480
Closes #3479
Closes #3598
Closes #3605

Remove the parallel path-based resolver after migrating the final compile-back harness consumer to TypeResolutionContext. Add nested and harness forwarder gates, and mark the structured architecture delivered.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: e19e4751-6306-4d3c-b6a9-6ac74523f178
Keep the completed design status consistent by describing retired consumers in the past tense and separating TypeRef's local normalization from resolution identity.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: e19e4751-6306-4d3c-b6a9-6ac74523f178
Integrate c4db43c before fixed-head review; the NuGet configuration cleanup has no overlap with this change.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: e19e4751-6306-4d3c-b6a9-6ac74523f178
@richlander

Copy link
Copy Markdown
Owner Author

Integrated current origin/main before fixed-head review in merge commit 190a6889e3a8f56dc198e8791762e8e4745acdd3. The intervening NuGet-configuration cleanup (c4db43c69) had no changed-file overlap or behavioral interaction with the forwarder retirement. The Release build, Metadata (1,281), Analysis (567), affected Decompiler suites (224), and Markdown lint all remain clean at the merged head.

Route the fixture through a forwarded external base interface so the test executes ReturnToSender's migrated TypeResolutionContext path instead of resolving the leaf definition through closure discovery.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: e19e4751-6306-4d3c-b6a9-6ac74523f178
Keep #3513 open: direct Callers correspondence resolves the declaring type, while forwarded non-core-library parameter types remain downstream work. Graph correspondence already resolves every named signature type.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: e19e4751-6306-4d3c-b6a9-6ac74523f178
Integrate 6a73ea6 because its workspace image-lifetime changes touch the acquisition substrate used by TypeResolutionContext.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: e19e4751-6306-4d3c-b6a9-6ac74523f178
@richlander

Copy link
Copy Markdown
Owner Author

Review round 1 at 190a6889e3a8f56dc198e8791762e8e4745acdd3 found one shared blocking issue and two scope corrections:

Before re-review, origin/main moved to 6a73ea686 with acquisition/image-lifetime changes that interact with TypeResolutionContext's substrate. Merge head 447d562dc6300e97f64a4a962d3fcd52cd7b9cfd integrates that work. Release build, Metadata (1,282), workspace lifetime (17), Analysis (567), affected Decompiler suites (224), and Markdown lint are clean locally. Fixed-head re-review will wait for current-head CI.

Integrate 0ff89be because its group-scoped query extends the workspace and assembly-session substrate adjacent to TypeResolutionContext.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: e19e4751-6306-4d3c-b6a9-6ac74523f178
@richlander

Copy link
Copy Markdown
Owner Author

Integrated current origin/main again before fixed-head re-review in merge commit 1739292c3ddf1e869c1e53ec6d8f1f98e9b5e6e0. The intervening group-scoped integrations query (0ff89befc) had no changed-file overlap, but it extends the workspace and assembly-session substrate adjacent to TypeResolutionContext. Release build, Metadata (1,282), workspace/query suite (20), Analysis (567), affected Decompiler suites (224), and Markdown lint remain clean. Re-review will wait for current-head CI.

Decline external-interface engagement when structured platform tightening selects a different defining assembly than Roslyn's sibling-first compilation closure. Add a signed-platform confusable-sibling gate that fails without the consistency check.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: e19e4751-6306-4d3c-b6a9-6ac74523f178
@richlander

Copy link
Copy Markdown
Owner Author

Re-review at 1739292c3ddf1e869c1e53ec6d8f1f98e9b5e6e0 produced one new finding:

  • Claude Opus found no significant issues and independently proved the corrected forwarded-base fixture is load-bearing.
  • GPT-5.6 Sol found that structured resolution can tighten a signed forwarder hop to Platform and inspect the trusted platform definition while Roslyn still compiles against a same-named sibling from its filename-deduplicated closure. That can turn a safe decline into CS0535.

Commit ab50e2b5d fixes the mismatch by requiring the resolved definition descriptor to be the same descriptor selected by the resolver's Any/compilation closure before ReturnToSender engages. The new System.Text.Json signed-platform/confusable-sibling gate is mutation-proven: deleting the check returns the TPA definition and fails the test; with the check, all affected Decompiler suites pass 225/225. Release build and Markdown lint are clean. A clean fixed-head re-review will wait for current-head CI.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: e19e4751-6306-4d3c-b6a9-6ac74523f178
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: e19e4751-6306-4d3c-b6a9-6ac74523f178
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: e19e4751-6306-4d3c-b6a9-6ac74523f178
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: e19e4751-6306-4d3c-b6a9-6ac74523f178
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: e19e4751-6306-4d3c-b6a9-6ac74523f178
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: e19e4751-6306-4d3c-b6a9-6ac74523f178
@richlander

Copy link
Copy Markdown
Owner Author

Round 7 adversarial review is clean at exact head 67b5355e4862d1c8595bf4e4637bdb2f7d01e649 against origin/main 1d47eb9443d6bf00d8546a5da90277001441467a.

The first read exposed one substantive gap: direct platform-signed interface references entered the frozen Roslyn closure through a name scan, bypassing the structured platform-vs-sibling convergence check used for forwarded hops. It also exposed that the review base had advanced, so that read did not count as a fixed-head round. Commit 67b5355e4 integrates current main and fixes the gap by snapshot-acquiring the target assembly into the same closure, resolving its initial signed AssemblyRef through TypeResolutionContext, replaying that complete binding/forwarding walk under Roslyn's sibling-first policy, and requiring matching identity, durable TypeDef address, and defining-image SHA-256. The closure scan must then identify that same definition and image. New end-to-end gates accept a byte-identical signed sibling and decline a fabricated same-identity interface; the unsigned hand-authored compatibility seam remains explicit.

GPT-5.6 Sol and Claude Opus independently re-reviewed the full current diff in isolated worktrees and reported CLEAN. They verified the initial reference origin/scope, non-vacuous independent replay, exact scan correspondence, inherited-interface origin, immutable shared snapshot lifetime and budget, retry/cluster/all/authored closure reuse, unsigned compatibility boundary, and positive/negative gate non-vacuity.

Current-head ci-required passes, the PR is mergeable, and the exact reviewed head is pushed.

Ready to merge

@richlander
richlander merged commit 945e750 into main Aug 9, 2026
10 checks passed
@richlander
richlander deleted the cleanup/retire-forwarder-migration branch August 9, 2026 12:17
richlander added a commit that referenced this pull request Aug 9, 2026
Resolve the dynamic compilation inventory additively for the independent #3784 and #3898 sites.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: d6c5d668-eb01-4f5b-bc22-09e6eade8835
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment