Skip to content

Fix asserts for TypeSpecs not in lookup table#233

Merged
josesimoes merged 1 commit into
developfrom
fix-asserts-typespecs
Apr 24, 2026
Merged

Fix asserts for TypeSpecs not in lookup table#233
josesimoes merged 1 commit into
developfrom
fix-asserts-typespecs

Conversation

@josesimoes
Copy link
Copy Markdown
Member

Description

  • Fix FillTypeSpecsFromMemberReferences to use AddIfNew instead of adding directly to _idByTypeSpecifications, so RID!=0 TypeSpecs from member references are now reachable via TryGetTypeReferenceId.
  • Remove asserts in Minimize() and replace with explanatory comment in case someone debugging this code hits the else.

Motivation and Context

How Has This Been Tested?

Screenshots

Types of changes

  • Improvement (non-breaking change that improves a feature, code or algorithm)
  • Bug fix (non-breaking change which fixes an issue with code or algorithm)
  • New feature (non-breaking change which adds functionality to code)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Config and build (change in the configuration and build system, has no impact on code or features)
  • Dependencies (update dependencies and changes associated, has no impact on code or features)
  • Unit Tests (add new Unit Test(s) or improved existing one(s), has no impact on code or features)
  • Documentation (changes or updates in the documentation, has no impact on code or features)

Checklist:

  • My code follows the code style of this project (only if there are changes in source code).
  • My changes require an update to the documentation (there are changes that require the docs website to be updated).
  • I have updated the documentation accordingly (the changes require an update on the docs in this repo).
  • I have read the CONTRIBUTING document.
  • I have tested everything locally and all new and existing tests passed (only if there are changes in source code).
  • I have added new tests to cover my changes.

@nfbot nfbot added the Type: enhancement New feature or request label Apr 24, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 24, 2026

📝 Walkthrough

Walkthrough

Two files in the metadata processor are modified to improve synchronization of type specification lookups. Changes ensure both internal dictionaries are updated consistently when seeding from member references, and document why certain lookup failures are benign.

Changes

Cohort / File(s) Summary
Type Specification Dictionary Synchronization
MetadataProcessor.Shared/Tables/nanoTypeSpecificationsTable.cs
Modified member-reference seeding to use AddIfNew for synchronized updates to both _idByTypeSpecifications and _indexByTypeReference, ensuring TryGetTypeReferenceId can reliably locate newly added entries.
Dependency Building Debug Assertion Removal
MetadataProcessor.Shared/nanoAssemblyBuilder.cs
Replaced Debug.Fail calls in dependency logic with explanatory comments documenting two benign scenarios where TypeSpecificationsTable.TryGetTypeReferenceId may fail (open generics with RID==0 or entries only in one internal dictionary), preserving original control flow.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description details both key changes (fixing FillTypeSpecsFromMemberReferences to use AddIfNew and removing Debug.Fail asserts) and provides motivation and testing information related to the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title accurately and concisely describes the main change: removing invalid Debug.Fail asserts for TypeSpecs not found in the lookup table.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@josesimoes
Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 24, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
MetadataProcessor.Shared/Tables/nanoTypeSpecificationsTable.cs (2)

329-341: 🛠️ Refactor suggestion | 🟠 Major

FillTypeSpecsFromTypes has the same direct-Add gap.

Line 337 (_idByTypeSpecifications.Add(genericInstanceType, sigId);) adds only to the primary dictionary and skips _indexByTypeReference, mirroring the issue the PR fixes elsewhere. Route this through AddIfNew as well to keep the two maps coherent and make the downstream TryGetTypeReferenceId lookups deterministic.

♻️ Proposed fix
                             if (genericInstanceType != null
                                 && !_idByTypeSpecifications.ContainsKey(genericInstanceType)
                                 && !genericInstanceType.IsToExclude())
                             {
                                 ushort sigId = _context.SignaturesTable.GetOrCreateSignatureId(genericInstanceType);
-                                _idByTypeSpecifications.Add(genericInstanceType, sigId);
+                                AddIfNew(genericInstanceType, sigId);
 
                                 // also pull in its element‐type and args
                                 ExpandNestedTypeSpecs(genericInstanceType);
                             }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@MetadataProcessor.Shared/Tables/nanoTypeSpecificationsTable.cs` around lines
329 - 341, In FillTypeSpecsFromTypes there's a direct call to
_idByTypeSpecifications.Add(genericInstanceType, sigId) that skips updating the
parallel map _indexByTypeReference; replace this direct Add with the existing
helper (call AddIfNew(genericInstanceType, sigId)) so both
_idByTypeSpecifications and _indexByTypeReference are updated atomically and
keep TryGetTypeReferenceId deterministic; ensure you still call
ExpandNestedTypeSpecs(genericInstanceType) afterward and handle
genericInstanceMethod / genericInstanceType as before.

266-304: 🛠️ Refactor suggestion | 🟠 Major

Same divergence still exists in the follow-up loops within FillTypeSpecsFromMemberReferences.

The two subsequent loops (GenericInstanceType seeding from TypeReferencesTable at lines 272/280, and the allGenericInstances union at line 301) still call _idByTypeSpecifications.Add(...) directly and never update _indexByTypeReference. That reproduces exactly the failure mode documented in the new comments in nanoAssemblyBuilder.cs (scenario 2: "Added only to _idByTypeSpecificationsTryGetTypeReferenceId cannot find it"), so any caller relying on TryGetTypeReferenceId for these entries will still miss them until ResetTypeSpecificationsTable() runs.

Consider routing these through AddIfNew for consistency and to fully eliminate the benign-lookup-miss case the PR is papering over.

♻️ Proposed refactor
             foreach (GenericInstanceType genericInstanceType in _context.TypeReferencesTable.Items.OfType<GenericInstanceType>())
             {
                 if (!_idByTypeSpecifications.ContainsKey(genericInstanceType) && !genericInstanceType.IsToExclude())
                 {
                     // create or get the signature ID for this instanced type
                     ushort sigId = _context.SignaturesTable.GetOrCreateSignatureId(genericInstanceType);
-                    _idByTypeSpecifications.Add(genericInstanceType, sigId);
+                    AddIfNew(genericInstanceType, sigId);
 
                     // (and don’t forget to pull in any nested generic-parameter args)
                     foreach (GenericParameter arg in genericInstanceType.GenericArguments.OfType<GenericParameter>())
                     {
                         if (!_idByTypeSpecifications.ContainsKey(arg) && !arg.IsToExclude())
                         {
                             ushort argSig = _context.SignaturesTable.GetOrCreateSignatureId(arg);
-                            _idByTypeSpecifications.Add(arg, argSig);
+                            AddIfNew(arg, argSig);
                         }
                     }
                 }
             }
@@
             foreach (TypeReference typeRefItem in allGenericInstances)
             {
                 if (!_idByTypeSpecifications.ContainsKey(typeRefItem) && !typeRefItem.IsToExclude())
                 {
                     ushort sigId = _context.SignaturesTable.GetOrCreateSignatureId(typeRefItem);
-                    _idByTypeSpecifications.Add(typeRefItem, sigId);
+                    AddIfNew(typeRefItem, sigId);
                     ExpandNestedTypeSpecs(typeRefItem);
                 }
             }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@MetadataProcessor.Shared/Tables/nanoTypeSpecificationsTable.cs` around lines
266 - 304, In FillTypeSpecsFromMemberReferences the loops that seed
GenericInstanceType and GenericParameter currently call
_idByTypeSpecifications.Add(...) directly (in the first foreach and in the
allGenericInstances loop), which omits updating _indexByTypeReference and causes
TryGetTypeReferenceId misses; replace those direct adds with the existing helper
AddIfNew(...) so entries go through the canonical insertion path (use
AddIfNew(genericInstanceType, sigId) and AddIfNew(arg, argSig) and
AddIfNew(typeRefItem, sigId) respectively) and keep the
ExpandNestedTypeSpecs(typeRefItem) call as-is.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@MetadataProcessor.Shared/nanoAssemblyBuilder.cs`:
- Around line 372-378: The Debug.Fail removal is fine, but to make scenario 2
truly benign you must stop masking the lookup-table inconsistency by routing all
direct writes to the type-spec ID map through the canonical add helper: replace
the direct uses of _idByTypeSpecifications.Add (the calls currently in
nanoTypeSpecificationsTable: the adds at the sites that correspond to the
earlier lines 272, 280, 301, 337) with the existing AddIfNew helper so that
AddIfNew enforces uniqueness and consistent state; ensure AddIfNew is invoked
from FillTypeSpecsFromMemberReferences and any other code paths that previously
called _idByTypeSpecifications.Add so TryGetTypeReferenceId no longer relies on
a separate implicit window opened by ResetTypeSpecificationsTable.

---

Outside diff comments:
In `@MetadataProcessor.Shared/Tables/nanoTypeSpecificationsTable.cs`:
- Around line 329-341: In FillTypeSpecsFromTypes there's a direct call to
_idByTypeSpecifications.Add(genericInstanceType, sigId) that skips updating the
parallel map _indexByTypeReference; replace this direct Add with the existing
helper (call AddIfNew(genericInstanceType, sigId)) so both
_idByTypeSpecifications and _indexByTypeReference are updated atomically and
keep TryGetTypeReferenceId deterministic; ensure you still call
ExpandNestedTypeSpecs(genericInstanceType) afterward and handle
genericInstanceMethod / genericInstanceType as before.
- Around line 266-304: In FillTypeSpecsFromMemberReferences the loops that seed
GenericInstanceType and GenericParameter currently call
_idByTypeSpecifications.Add(...) directly (in the first foreach and in the
allGenericInstances loop), which omits updating _indexByTypeReference and causes
TryGetTypeReferenceId misses; replace those direct adds with the existing helper
AddIfNew(...) so entries go through the canonical insertion path (use
AddIfNew(genericInstanceType, sigId) and AddIfNew(arg, argSig) and
AddIfNew(typeRefItem, sigId) respectively) and keep the
ExpandNestedTypeSpecs(typeRefItem) call as-is.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: nanoframework/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: ab5fa57e-6007-404c-a125-320b143ee10e

📥 Commits

Reviewing files that changed from the base of the PR and between 41f76e7 and b4dddb9.

📒 Files selected for processing (2)
  • MetadataProcessor.Shared/Tables/nanoTypeSpecificationsTable.cs
  • MetadataProcessor.Shared/nanoAssemblyBuilder.cs

Comment thread MetadataProcessor.Shared/nanoAssemblyBuilder.cs
- Fix FillTypeSpecsFromMemberReferences to use AddIfNew instead of
adding directly to _idByTypeSpecifications, so RID!=0 TypeSpecs from
member references are now reachable via TryGetTypeReferenceId.
- Remove asserts in Minimize() and replace with explanatory comment in case someone debugging this code hits the else.
@josesimoes josesimoes force-pushed the fix-asserts-typespecs branch from b4dddb9 to b184c68 Compare April 24, 2026 13:14
@josesimoes josesimoes enabled auto-merge (squash) April 24, 2026 13:17
@josesimoes josesimoes changed the title Fix invalid Debug.Fail asserts for TypeSpecs not in lookup table Fix asserts for TypeSpecs not in lookup table Apr 24, 2026
@josesimoes josesimoes merged commit ad96dcb into develop Apr 24, 2026
5 checks passed
@josesimoes josesimoes deleted the fix-asserts-typespecs branch April 24, 2026 13:29
josesimoes added a commit that referenced this pull request Apr 27, 2026
- Missed #233.

***NO_CI***
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Type: enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants