Skip to content

Fix invalid IL for generative methods declared with System.Void return type#523

Open
Thorium wants to merge 1 commit into
fsprojects:masterfrom
Thorium:fix-void-return-ldnull
Open

Fix invalid IL for generative methods declared with System.Void return type#523
Thorium wants to merge 1 commit into
fsprojects:masterfrom
Thorium:fix-void-return-ldnull

Conversation

@Thorium

@Thorium Thorium commented Jul 9, 2026

Copy link
Copy Markdown
Member

Problem

The unit-return fix from #518 emits I_ldnull before I_ret whenever the method's return type is unit-like:

let retUnit = retType = ILType.Void || retType.QualifiedName = (transType (convTypeToTgt typeof<unit>)).QualifiedName
...
if retUnit then ilg.Emit(I_ldnull)

The check also matches ILType.Void, so a ProvidedMethod declared with returnType = typeof<System.Void> (which transType maps to ILType.Void) gets a stray null pushed onto the stack of a void-returning method. That is invalid IL — the stack must be empty at ret in a void method — and the JIT throws InvalidProgramException the first time the method is invoked:

System.InvalidProgramException : Common Language Runtime detected an invalid program.
   at VoidReturn.Provided.Container.Widget.DoNothing()

(The equivalent lambda path in CodeGenerator.emitLambda already gets this right: it emits I_ldnull only for the FSharp.Core Unit return type, not for void.)

Fix

Split the check: retVoid keeps the empty-stack behavior with no ldnull; only a genuine FSharp.Core Unit return pushes the boxed unit value null.

Testing

  • New generative regression test declaring a System.Void-returning method and invoking it from the loaded assembly — fails with InvalidProgramException before the fix, passes after.
  • Full suite green: 161/161 (including the try-finally unit-return test added in Fix for issue #517 #518).

🤖 Generated with Claude Code

…n type

The unit-return fix from fsprojects#518 emits I_ldnull before I_ret whenever the
return type is unit-like, but its retUnit check also matched ILType.Void.
A ProvidedMethod declared with returnType = typeof<System.Void> then got
a stray null pushed onto the stack of a void-returning method, which is
invalid IL: the JIT throws InvalidProgramException on first invocation.

Split the check: void keeps the empty-stack behavior with no ldnull,
while only a genuine FSharp.Core Unit return pushes the boxed unit null.

Adds a generative regression test that declares a System.Void-returning
method and invokes it from the loaded assembly (fails with
InvalidProgramException before this fix).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Thorium

Thorium commented Jul 10, 2026

Copy link
Copy Markdown
Member Author

This is a low-priority issue compared to 520 and 522, which are solving real production issues.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant