Make IL block comparison hierarchy- and order-aware - #269
Draft
Widthdom wants to merge 5 commits into
Draft
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
marshal({ ... })declarations attached to their methods.interfaceandimporttypes.dotnet-ildasmandilspycmdlayouts.Changed areas:
FolderDiffIL4DotNet.Core/IL/ILBlockParser.csFolderDiffIL4DotNet.Core/FolderDiffIL4DotNet.Core.csprojServices/ILOutput/ILBlockParser.cs,Services/ILOutputService.BlockComparison.cs,Services/ILOutputService.Comparison.csFolderDiffIL4DotNet.Tests/Services/ILBlockParserTests.cs,FolderDiffIL4DotNet.Tests/Services/ILOutputServiceTests.cs,FolderDiffIL4DotNet.Tests/Services/ILOutputServiceTests.BlockComparison.csCHANGELOG.md,USER_GUIDE.md,doc/DEVELOPER_GUIDE.md,doc/TESTING_GUIDE.mdWhy
Compiler and disassembler output may reorder members inside an ordinary class without changing program behavior. The previous block-aware fallback treated an entire class as one hashed block, so this harmless reordering produced a false mismatch.
The comparison must still report meaningful differences: method-body edits, bodies swapped between signatures, moves between classes, ABI-sensitive interface/import member reordering, and marshal metadata changes.
Root cause
The previous fallback used a flat multiset of top-level
(signature, content hash)blocks. It had no class/member hierarchy representation, so member order contributed to the hash of the entire class.The parser also treated braces inside declaration-header parentheses such as
marshal({ ... })as structural body braces. A hierarchy identity based only on the first.classline could not distinguish multiline declarations whose type names occur on continuation lines, while unconditional order-independent matching was unsafe for interface/import members whose order can define interop ABI layout.Impact
interfaceandimporttypes remain order-sensitive, including COM vtable-relevant ordering.Six OSS review fixes
Class-internal member reordering
Ordinary classes are decomposed into a class shell and separately matched direct-member blocks under the same parent hierarchy.
Non-recursive hierarchy parsing
A single forward scan with an explicit stack avoids recursive stack growth and repeated subtree rescans or copies.
Bounded hierarchy identities
Comparison uses incrementally derived fixed-size SHA-256 hierarchy keys instead of materializing every complete ancestor path in the production comparison flow.
Marshal-header block boundaries
Braces nested inside header parentheses, including multiline
marshal({ ... })blobs, no longer terminate method blocks early.Complete multiline class identities
Comparison keys include every class-header line, preventing classes whose names appear on continuation lines from sharing a member bucket while preserving the existing first-line
ContainerPathdisplay.ABI-sensitive member ordering
Direct members of
interfaceandimporttypes stay in their ordered class shell; ordinary-class and ordinary nested-class members remain reorderable.Checks
dotnet test FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj --configuration Release --nologogit diff --check origin/main...HEADcdidx status --checkThe skipped test is
RealDisassemblerE2ETests.FilesAreEqualAsync_WhenDotNetIldasmComparesNonDeterministicRebuilds_ReturnsIlMatch. Coverage collection was not run.Visual assets
No screenshots or GIFs are needed because this change does not alter UI or report layout.