Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for F# anonymous records #2530

Open
psfinaki opened this issue Feb 26, 2024 · 3 comments
Open

Support for F# anonymous records #2530

psfinaki opened this issue Feb 26, 2024 · 3 comments

Comments

@psfinaki
Copy link
Member

Repro

namespace Perf

open BenchmarkDotNet.Running
open BenchmarkDotNet.Attributes

module Main =

    type Test() =

        [<Benchmark>]
        member _.AnonymousRecord() =
            let array = Array.init 5 id
            array |> Array.countBy (fun n -> {| Field = n |})

    [<EntryPoint>]
    let main args = 
        printfn "Running benchmarks..."
        BenchmarkSwitcher.FromAssembly(typeof<Test>.Assembly).Run(args) |> ignore
        0

What happens

// Build Error: Standard output:

 Standard error:
 MSBuild version 17.10.0-preview-23619-02+5cf78584f for .NET
C:\Program Files\dotnet\sdk\9.0.100-alpha.1.23620.14\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.RuntimeIdentifierInference.targets(311,5): message NETSDK1057: You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(186,37): error CS1001: Identifier expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(186,37): error CS1003: Syntax error, '(' expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(186,80): error CS1001: Identifier expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(186,94): error CS1001: Identifier expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(186,94): error CS1003: Syntax error, ',' expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(186,95): error CS1003: Syntax error, ',' expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(186,96): error CS1001: Identifier expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(186,114): error CS1001: Identifier expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(186,114): error CS1003: Syntax error, ',' expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(186,115): error CS8124: Tuple must contain at least two elements. [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(186,116): error CS1001: Identifier expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(186,116): error CS1026: ) expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(188,38): error CS1001: Identifier expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(188,38): error CS1003: Syntax error, '(' expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(188,81): error CS1001: Identifier expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(188,95): error CS1001: Identifier expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(188,95): error CS1003: Syntax error, ',' expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(188,96): error CS1003: Syntax error, ',' expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(188,97): error CS1001: Identifier expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(188,115): error CS1001: Identifier expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(188,115): error CS1003: Syntax error, ',' expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(188,116): error CS8124: Tuple must contain at least two elements. [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(188,117): error CS1001: Identifier expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(188,117): error CS1026: ) expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(239,29): error CS1519: Invalid token '<<' in class, record, struct, or interface member declaration [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(239,72): error CS1519: Invalid token ',' in class, record, struct, or interface member declaration [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(239,86): error CS1519: Invalid token '>' in class, record, struct, or interface member declaration [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(239,88): error CS1001: Identifier expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(318,28): error CS1519: Invalid token '<<' in class, record, struct, or interface member declaration [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(318,71): error CS1519: Invalid token ',' in class, record, struct, or interface member declaration [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(318,85): error CS1519: Invalid token '>' in class, record, struct, or interface member declaration [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(318,87): error CS1001: Identifier expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(326,40): error CS1026: ) expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(326,42): error CS1525: Invalid expression term '>' [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(326,83): error CS1002: ; expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(326,83): error CS1513: } expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(326,100): error CS1002: ; expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]
FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\1a71ca95-94eb-441e-9549-46a619937196.notcs(326,100): error CS1513: } expected [FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196\BenchmarkDotNet.Autogenerated.csproj]

Build FAILED

    38 Error(s)
Time Elapsed 00:00:01.94

// BenchmarkDotNet has failed to build the auto-generated boilerplate code.
// It can be found in FSharpConsoleApp\bin\Release\net8.0\1a71ca95-94eb-441e-9549-46a619937196
// Please follow the troubleshooting guide: https://benchmarkdotnet.org/articles/guides/troubleshooting.html

What should happen

Well something more clear. It should either work or give a clear message. This might be related to the fact that anon records in F# are very generic under the hood and AFAIK BDN has problems with those.

Env

BenchmarkDotNet v0.13.12, Windows 11 (10.0.22621.3155/22H2/2022Update/SunValley2)
11th Gen Intel Core i7-1185G7 3.00GHz, 1 CPU, 8 logical and 4 physical cores
.NET SDK 9.0.100-alpha.1.23620.14
  [Host] : .NET 8.0.2 (8.0.224.6711), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI DEBUG

@adamsitnik
Copy link
Member

Please follow the troubleshooting guide: https://benchmarkdotnet.org/articles/guides/troubleshooting.html

BDN generates a C# project that references the F# project and generates a class that derives from the type that defined the benchmarks (to generate the boilerplate code and run every benchmark in a standalone process to avoid any side-effects affecting other benchmarks). Please use the link provided above and troubleshoot the issue (I suspect that BDN fails to reference the F# method with such name) and send a PR with a fix.

Here is the logic that generates the C# code: https://github.com/dotnet/BenchmarkDotNet/blob/master/src/BenchmarkDotNet/Code/CodeGenerator.cs

Here is the template it's filling:
https://github.com/dotnet/BenchmarkDotNet/blob/master/src/BenchmarkDotNet/Templates/BenchmarkType.txt

@timcassell
Copy link
Collaborator

timcassell commented Feb 27, 2024

I'm guessing F# anonymous records are implemented similar to C# anonymous types where their underlying type name in IL cannot be expressed in C#. If that's the case, there is nothing we can do about it. You will have to wrap it in another type that C# can consume (or up-cast to object), or use an InProcess toolchain.

@psfinaki
Copy link
Member Author

I'm guessing F# anonymous records are implemented similar to C# anonymous types where their underlying type name in IL cannot be expressed in C#. If that's the case, there is nothing we can do about it. You will have to wrap it in another type that C# can consume (or up-cast to object), or use an InProcess toolchain.

Very well might be - in that case yeah, at least a proper error message would be helpful.

I haven't worked with debugging BDN yet but this looks like an interesting opportunity. Will post heads up here if I start working on this.

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

No branches or pull requests

3 participants