fsprojects / FSharp.TypeProviders.SDK

The SDK for creating F# type providers
https://fsprojects.github.io/FSharp.TypeProviders.SDK/
MIT License
298 stars 94 forks source link

Problems with lambdas of the form (_ -> unit) #279

Closed kevmal closed 4 years ago

kevmal commented 5 years ago

Description

Generated code involving lambdas of the form _ -> unit causes issues.

Repro steps

Add (using the type provider template)

        let meth = ProvidedMethod("StaticMethod", [], typeof<int []>, isStatic=true, invokeCode = (fun args -> <@@  let a = [|0 .. 10|] in a |> Array.iteri (fun i x -> a.[i] <- x + 1); a @@> ))
        myType.AddMember(meth)

to BasicGenerativeProvider.

Execute in fsi

type Bleh = LemonadeProvider.GenerativeProvider<3>
Bleh.StaticMethod()

Expected behavior

Return the array [|1 .. 11|].

Actual behavior

Exception:

> System.TypeLoadException: The signature is incorrect.
   at LemonadeProvider.Bleh.StaticMethod()
   at <StartupCode$FSI_0006>.$FSI_0006.main@() in E:\Script6.fsx:line 6
Stopped due to error

Known workarounds

Avoid 'a -> unit

Related information

Comparing the generated assembly with valid code it seems the issue is the generated lambda class inherits from FSharpFunc<_,void> as oppose to the valid code inheriting from FSharpFunc<_,unit>. For example

using Microsoft.FSharp.Core;
using System.Runtime.InteropServices;

internal class Lambdadd375771\u002D88ae\u002D46e9\u002D92b2\u002D100258dec3aa : FSharpFunc<int, void>
{
  public Lambdadd375771\u002D88ae\u002D46e9\u002D92b2\u002D100258dec3aa()
  {
    base.\u002Ector();
  }

  public override sealed void Invoke([In] int obj0)
  {
    Operators.Ignore<int>((int) (obj0 + 21));
  }
}