Skip to content

Fix NRE calling virtual Object methods on value types via inline SRTP#19511

Merged
T-Gro merged 3 commits intomainfrom
bugfix/nullreference-virtual-object
Apr 15, 2026
Merged

Fix NRE calling virtual Object methods on value types via inline SRTP#19511
T-Gro merged 3 commits intomainfrom
bugfix/nullreference-virtual-object

Conversation

@T-Gro
Copy link
Copy Markdown
Member

@T-Gro T-Gro commented Mar 27, 2026

Fixes #8098

Widens the address-taking condition in GenWitnessExpr to also trigger when ComputeConstrainedCallInfo requires a constrained call, not just when minfo.IsStruct.

… SRTP (#8098)

When an inline SRTP function calls a virtual Object method (ToString,
GetHashCode, Equals) on a value type, the compiler emits a constrained
callvirt instruction. ECMA-335 requires the receiver of a constrained
call to be a managed pointer (&), but the codegen was pushing the raw
value (or reference) directly onto the stack.

Root cause: MakeMethInfoCall (used by SRTP trait resolution) computes
PossibleConstrainedCall but never takes the receiver's address — unlike
TakeObjAddrForMethodCall which handles this correctly in the
type-checker path for direct calls.

Fix: In MakeMethInfoCall, when ComputeConstrainedCallInfo returns Some
(indicating a constrained call is needed), take the address of the
receiver via mkExprAddrOfExpr before building the IL call expression.
This mirrors TakeObjAddrForMethodCall and ensures the expression tree
contains the proper address-of wrapper, so GenILCall receives a managed
pointer on the stack as ECMA-335 requires.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@T-Gro T-Gro force-pushed the bugfix/nullreference-virtual-object branch from b957b25 to 4800b45 Compare March 27, 2026 15:44
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 27, 2026

❗ Release notes required


✅ Found changes and release notes in following paths:

Change path Release notes path Description
src/Compiler docs/release-notes/.FSharp.Compiler.Service/11.0.100.md

@T-Gro T-Gro requested a review from abonie March 27, 2026 15:49
@T-Gro T-Gro enabled auto-merge (squash) April 1, 2026 10:00
@github-project-automation github-project-automation bot moved this from New to In Progress in F# Compiler and Tooling Apr 15, 2026
@T-Gro T-Gro merged commit c3c01c9 into main Apr 15, 2026
48 checks passed
@github-project-automation github-project-automation bot moved this from In Progress to Done in F# Compiler and Tooling Apr 15, 2026
Copilot AI pushed a commit that referenced this pull request Apr 15, 2026
… SRTP (#8098) (#19511)

When an inline SRTP function calls a virtual Object method (ToString,
GetHashCode, Equals) on a value type, the compiler emits a constrained
callvirt instruction. ECMA-335 requires the receiver of a constrained
call to be a managed pointer (&), but the codegen was pushing the raw
value (or reference) directly onto the stack.

Root cause: MakeMethInfoCall (used by SRTP trait resolution) computes
PossibleConstrainedCall but never takes the receiver's address — unlike
TakeObjAddrForMethodCall which handles this correctly in the
type-checker path for direct calls.

Fix: In MakeMethInfoCall, when ComputeConstrainedCallInfo returns Some
(indicating a constrained call is needed), take the address of the
receiver via mkExprAddrOfExpr before building the IL call expression.
This mirrors TakeObjAddrForMethodCall and ensures the expression tree
contains the proper address-of wrapper, so GenILCall receives a managed
pointer on the stack as ECMA-335 requires.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

NullReferenceException when calling a virtual Object method on a value type from inline function

2 participants