Skip to content

Fix support generic struct arrays with generic TypeSpecs#3340

Merged
josesimoes merged 4 commits into
nanoframework:developfrom
josesimoes:fix-generic-array
Apr 24, 2026
Merged

Fix support generic struct arrays with generic TypeSpecs#3340
josesimoes merged 4 commits into
nanoframework:developfrom
josesimoes:fix-generic-array

Conversation

@josesimoes
Copy link
Copy Markdown
Member

@josesimoes josesimoes commented Apr 24, 2026

Description

  • ResolveToken for a TypeDef instance now resolves generic TypeSpec tokens to their open generic TypeDef, enabling newarr, ldelem.any and stelem.any to succeed on generic struct element types.
  • InitializeReference now properly handles a VAR field without generic instance context, falling back to Object instead of faiing, mirroring the existing MVAR behaviour.
  • Narrow VAR fallback to array pre-allocation path only.
    • Add allowUnresolvedVarFallback parameter to InitializeReference.
    • Now using this when resolving VAR.
    • Update callers, noticably NewObject as this is the only path reached from ClearElements → NewObjectFromIndex during open-generic array pre-allocation.

Motivation and Context

  • newarr Pair<TKey,TValue> inside a generic method emits a generic TypeSpec token. The runtime had no handling for this token class in ResolveToken, causing CLR_E_WRONG_TYPE for newarr, ldelem.any and stelem.any on generic struct arrays.
    Even after resolving the element type, pre-allocating struct slots in the new array calls InitializeReference on each field. For open generic structs the field types are unresolved VAR parameters; without a closed generic context at array-creation time the call unconditionally returned CLR_E_FAIL. Fields are written correctly by subsequent stfld instructions, so initialising them as objects (which are null) is safe.
  • Edge case surfaced when adding new test code in MDP Fix minimize failing for generic interface TypeSpecs with no member refs metadata-processor#232.
  • Related with Support for generics <T> Home#782.

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)
  • Dev Containers (changes related with Dev Containers, has no impact on code or features)
  • Dependencies/declarations (update dependencies or assembly declarations and changes associated, 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).

- ResolveToken for a TypeDef instance now resolves generic TypeSpec tokens to their open generic TypeDef, enabling newarr, ldelem.any and stelem.any to succeed on generic struct element types.
- InitializeReference now properly handles a VAR field without generic instance context, falling back to Object instead of faiing, mirroring the existing MVAR behaviour.
@josesimoes josesimoes added the Area: Common libs Everything related with common libraries label Apr 24, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 24, 2026

📝 Walkthrough

Walkthrough

The changes update generic type instantiation handling in the CLR. They modify reflection element type selection for array creation, add lenient handling for unresolved generic parameters during field initialization, and simplify type token resolution logic for generic instantiations.

Changes

Cohort / File(s) Summary
Generic Type Instantiation Handling
src/CLR/Core/CLR_RT_HeapBlock_Array.cpp, src/CLR/Core/Execution.cpp, src/CLR/Core/TypeSystem.cpp
Updates reflection element type selection to prefer genericTypeDef for generic instantiations with fallback to cachedElementType; allows InitializeReference to coerce unresolved generic parameters to DATATYPE_OBJECT instead of failing; simplifies ResolveToken logic to directly capture and validate the open generic type definition token for DATATYPE_GENERICINST cases.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title concisely describes the main change (fixing support for generic struct arrays with generic TypeSpecs), is directly related to the core changeset, and follows the requirements.
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.
Description check ✅ Passed The pull request description clearly relates to the changeset, detailing fixes for generic struct array support and VAR field handling with specific context about motivation and testing.

✏️ 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.

nfbot and others added 2 commits April 24, 2026 14:31
Automated fixes for code style.
…687af-89e1-4a08-b12c-d539e7b510c9

Code style fixes for nanoframework/nf-interpreter PR#3340
@josesimoes
Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

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
Contributor

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/CLR/Core/Execution.cpp`:
- Around line 2118-2131: The current fallback that sets VAR to DATATYPE_OBJECT
when genericInstance is null is too broad and incorrectly affects callers like
InitializeReference used during static field initialization; narrow the fallback
so only the open-generic pre-allocation path uses DATATYPE_OBJECT. Specifically,
in the block that checks genericInstance and NANOCLR_INDEX_IS_VALID, detect the
pre-allocation scenario (the same condition used when preparing array element
structs for open generics) and only in that case set dt = DATATYPE_OBJECT;
otherwise return/propagate the unresolved/generic error (i.e., preserve failure)
so callers such as InitializeReference (static field init) continue to handle
value-type generic parameters correctly; keep the call to
ResolveGenericTypeParameter and the goto process_datatype for the
normal/closed-generic path.
🪄 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 YAML (base), Central YAML (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3619426b-7257-4cdd-9003-be399d7a40b1

📥 Commits

Reviewing files that changed from the base of the PR and between 2df0ad2 and ea07066.

📒 Files selected for processing (3)
  • src/CLR/Core/CLR_RT_HeapBlock_Array.cpp
  • src/CLR/Core/Execution.cpp
  • src/CLR/Core/TypeSystem.cpp

Comment thread src/CLR/Core/Execution.cpp
- Add allowUnresolvedVarFallback parameter to InitializeReference.
- Now using this when resolving VAR.
- Update callers, noticably NewObject as this is the only path reached from ClearElements → NewObjectFromIndex during open-generic array pre-allocation.
@josesimoes josesimoes merged commit 8987ffa into nanoframework:develop Apr 24, 2026
23 checks passed
@josesimoes josesimoes deleted the fix-generic-array branch April 24, 2026 15:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: Common libs Everything related with common libraries Type: bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants