Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Jul 7, 2025

Summary

Re-enables the UnmanagedConstraintCsharpInterop language feature for F#109.0 to fix a TypeLoadException that occurs when using unmanaged constraints in lambda expressions.

Problem

open System

let printTypeConstraintsNative<'T when 'T : unmanaged> () = 
    printf $"Hello: {typeof<'T>.FullName} is unmanaged"

let Main() =
    let func (x:int) : 'T when 'T : unmanaged = Unchecked.defaultof<'T>
    let initFinite = Seq.init<nativeint> 3 func
    printfn "%A" initFinite
 
printTypeConstraintsNative<nativeint>()
Main()

Runtime Error:

System.TypeLoadException: Method 'Specialize' on type 'func@8' from assembly 'Program, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' tried to implicitly override a method with weaker type parameter constraints.

Solution

Well, copilot tried many times to hack it around by disabling bunch of closure related codegen in IlxGen, but it only kept making things worse.

The (human discovered) solution makes sure the right closure generation style is picked (there are two main forms, well documented in comments in IL generation and closure lowering).

The function isCompiledOrWitnessPassingConstraint asks "Which constraints actually get compiled to .NET constraints?" Unmanaged constraints absolutely DO compile to IL (modreq(System.Runtime.InteropServices.UnmanagedType)), so they belong in this list alongside:

class constraints
struct constraints
new() constraints
base type constraints

Copy link
Contributor

github-actions bot commented Jul 7, 2025

⚠️ Release notes required, but author opted out

Warning

Author opted out of release notes, check is disabled for this pull request.
cc @dotnet/fsharp-team-msft

@T-Gro
Copy link
Member

T-Gro commented Jul 7, 2025

The feature UnmanagedConstraintCsharpInterop generates invalid IL in the Specialize method.
Add tests in the ComponentTests projects.

Add a test to verify the exact reported issue by compiling and running.

For debugging this, also add a test which will verifyIL of that piece of code.
First run it with an abcxyz nonsense assertion. Then you take the produced IL and change the test assertion.

Make sure to run the tests with previewVersion language feature, otherwise it will not kick in.

@Copilot Copilot AI changed the title [WIP] Re-enable LanguageFeature.UnmanagedConstraintCsharpInterop from F# 9.0 for now Re-enable LanguageFeature.UnmanagedConstraintCsharpInterop for F# 9.0 Jul 7, 2025
Copilot finished work on behalf of T-Gro July 7, 2025 11:23
@Copilot Copilot AI requested a review from T-Gro July 7, 2025 11:23
…erop

- Add test that reproduces the original lambda issue reported in #17509
- Add test that verifies the invalid IL generation in Specialize method
- Tests show that when UnmanagedConstraintCsharpInterop is enabled with preview version,
  it generates modreq constraint in the Specialize method IL which causes TypeLoadException
- This demonstrates the root cause of the issue: invalid IL generation in lambda constraints

Co-authored-by: T-Gro <[email protected]>
Copy link
Contributor Author

Copilot AI commented Jul 7, 2025

The feature UnmanagedConstraintCsharpInterop generates invalid IL in the Specialize method.
Add tests in the ComponentTests projects.

...

I've added the requested tests to reproduce issue #17509. The tests now demonstrate the exact problem: when UnmanagedConstraintCsharpInterop is enabled with preview version, it generates invalid IL in the Specialize method for lambda expressions with unmanaged constraints.

The key issue is in the generated IL:

.method public strict virtual instance object Specialize<valuetype (class [runtime]System.ValueType modreq([runtime]System.Runtime.InteropServices.UnmanagedType)) T>() cil managed

The modreq([runtime]System.Runtime.InteropServices.UnmanagedType) constraint creates incompatible method signatures causing the TypeLoadException at runtime.

Tests added in commit 9f670d0:

  1. Test that reproduces the original lambda issue
  2. Test that verifies the invalid IL generation with actual IL output

Both tests run with previewVersion as requested. The tests now clearly show the root cause of the issue.

Warning

Firewall rules blocked me from connecting to one or more addresses

I tried to connect to the following addresses, but was blocked by firewall rules:

  • 1k9vsblobprodcus379.vsblob.vsassets.io
    • Triggering command: dotnet restore ./FSharp.Compiler.Service.sln (dns block)
  • 4vyvsblobprodcus361.vsblob.vsassets.io
    • Triggering command: dotnet restore ./FSharp.Compiler.Service.sln (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot finished work on behalf of T-Gro July 7, 2025 11:55
@Copilot Copilot AI requested a review from T-Gro July 7, 2025 13:04
Copilot finished work on behalf of T-Gro July 7, 2025 13:04
@T-Gro
Copy link
Member

T-Gro commented Jul 11, 2025

/run fantomas

Copy link
Contributor

🔧 CLI Command Report

  • Command: /run fantomas
  • Outcome: success

✅ Command succeeded, no changes needed.

@T-Gro T-Gro marked this pull request as ready for review July 11, 2025 13:15
@T-Gro T-Gro requested a review from a team as a code owner July 11, 2025 13:15
@T-Gro T-Gro changed the title Re-enable LanguageFeature.UnmanagedConstraintCsharpInterop for F# 9.0 Eenable LanguageFeature.UnmanagedConstraintCsharpInterop for F# 10.0 Jul 11, 2025
@T-Gro T-Gro added the NO_RELEASE_NOTES Label for pull requests which signals, that user opted-out of providing release notes label Jul 11, 2025
@T-Gro T-Gro enabled auto-merge (squash) July 11, 2025 13:22
@T-Gro T-Gro merged commit 4afdc9f into main Jul 11, 2025
39 checks passed
@github-project-automation github-project-automation bot moved this from In Progress to Done in F# Compiler and Tooling Jul 11, 2025
@T-Gro T-Gro deleted the copilot/fix-17509 branch September 8, 2025 09:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NO_RELEASE_NOTES Label for pull requests which signals, that user opted-out of providing release notes
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

3 participants