Skip to content

Fix closed-generic .cctor ordering causing NullReferenceException - #3493

Merged
josesimoes merged 2 commits into
nanoframework:developfrom
josesimoes:fix-cctor-generics
Jul 23, 2026
Merged

Fix closed-generic .cctor ordering causing NullReferenceException#3493
josesimoes merged 2 commits into
nanoframework:developfrom
josesimoes:fix-cctor-generics

Conversation

@josesimoes

Copy link
Copy Markdown
Member

Description

  • Add EnsureGenericCctorCompleted() to force a closed generic type .cctor to run before its first use.
  • Gate CEE_NEWOBJ, static CEE_CALL, CEE_LDSFLD, CEE_LDSFLDA, and CEE_STSFLD on the new check, removed the old post-access reschedule-on-null fallback.
  • Extend the gate to open declaring TypeSpecs (e.g. SZGenericArrayEnumerator<!!0>) that resolve to a closed instantiation via the caller's method generic context.
  • Update docs with the generic .cctor lifecycle and call contract.

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)
  • 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).

- Add EnsureGenericCctorCompleted() to force a closed generic type .cctor to run before its first use.
- Gate CEE_NEWOBJ, static CEE_CALL, CEE_LDSFLD, CEE_LDSFLDA, and CEE_STSFLD on the new check, removed the old post-access reschedule-on-null fallback.
- Extend the gate to open declaring TypeSpecs (e.g. SZGenericArrayEnumerator<!!0>) that resolve to a closed instantiation via the caller's method generic context.
- Update docs with the generic .cctor lifecycle and call contract.

Assisted by Claude Opus 4.8
@josesimoes josesimoes added the Area: Interpreter Everything related with the interpreter, execution engine and such label Jul 23, 2026
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 0748bfcc-a574-412b-9cd6-d72ae9e6476b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The interpreter centralizes generic static constructor completion in EnsureGenericCctorCompleted, invokes it for generic calls, construction, and static field access, and documents the resulting lifecycle, scheduling states, and control-flow contract.

Changes

Generic static constructor enforcement

Layer / File(s) Summary
Demand gate and lifecycle contract
src/CLR/Core/Interpreter.cpp, src/CLR/Core/CLAUDE.md
Adds EnsureGenericCctorCompleted to track generic .cctor state, schedule or push constructor frames, and document interpreter and crawler behavior.
Call and construction integration
src/CLR/Core/Interpreter.cpp
Enforces generic .cctor completion before static calls and generic object construction, handling restart and reschedule results.
Static field access integration
src/CLR/Core/Interpreter.cpp
Enforces completion before generic static field operations, removes null-resolution rescheduling, and narrows generic tracing output.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ILInterpreter
  participant EnsureGenericCctorCompleted
  participant GenericCctorExecution
  participant StaticFieldResolver
  ILInterpreter->>EnsureGenericCctorCompleted: process generic call, newobj, or static field access
  EnsureGenericCctorCompleted->>GenericCctorExecution: inspect or update .cctor state
  GenericCctorExecution-->>ILInterpreter: return completion, restart, or reschedule status
  ILInterpreter->>StaticFieldResolver: resolve static field after completion
Loading
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the PR’s main fix for closed-generic .cctor ordering and NullReferenceException.
Description check ✅ Passed The description is directly related to the code and doc changes in this PR.
Linked Issues check ✅ Passed The changes address issue #1821 by ensuring generic .cctor completion before relevant list and static operations.
Out of Scope Changes check ✅ Passed The code and documentation changes all support the same generic .cctor bug fix and contain no obvious unrelated scope.

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.

@josesimoes

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/CLR/Core/Interpreter.cpp`:
- Around line 3066-3077: In the NEWOBJ .cctor type-selection block, reverse the
priority so valid stack->m_call.genericType is selected before
calleeInst.genericType. Preserve the existing validity checks and fallback
behavior, aligning this gate with the caller-first context selection used by the
object-creation path.
- Around line 1099-1118: Roll back the generic constructor record flags when
initialization or frame scheduling fails. In the flow that sets c_Scheduled and
c_Executed before CLR_RT_MethodDef_Instance::InitializeFromIndex and
CLR_RT_StackFrame::Push, clear both flags before returning either failure
HRESULT so a later trigger can retry the .cctor.
🪄 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 Plus

Run ID: dbf60a7e-eda4-411e-903a-6b09bb305ab2

📥 Commits

Reviewing files that changed from the base of the PR and between 699e1b3 and 378e623.

📒 Files selected for processing (2)
  • src/CLR/Core/CLAUDE.md
  • src/CLR/Core/Interpreter.cpp

Comment thread src/CLR/Core/Interpreter.cpp
Comment thread src/CLR/Core/Interpreter.cpp
@josesimoes
josesimoes merged commit 9ce1bb5 into nanoframework:develop Jul 23, 2026
29 checks passed
@josesimoes
josesimoes deleted the fix-cctor-generics branch July 23, 2026 10:40
@coderabbitai coderabbitai Bot mentioned this pull request Jul 24, 2026
13 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: Interpreter Everything related with the interpreter, execution engine and such Type: bug Type: documentation Type: enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants