dotnet / dotnet/fsharp

Tooling :: Interop story for .NET libraries using C# source generators for high performance

Open
#14,300 12 comments 23 reactions 0 assignees View on GitHub
Area-Compiler-ImportAndInterop Area-ProjectsAndBuild Feature Request
Dominant language
F#
Stars
4.3k
Forks
876
Avg merge
4d 22h
Merged PRs (30d)
144

Description

I want to open the discussion on **consumption** of .NET libraries built using C# source gen support https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview .

With every .NET version, more APIs use it and is part of the reason of the unprecedented performance boosts of .NET platform for various computing tasks. A few examples include:
- JSON serialization https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-source-generator/
- gRPC support ( dotnetconf2022 talk by J.N.King )
- Regex compilation https://learn.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-source-generators
- upcoming ideas for aspnetcore apis itself https://github.com/davidfowl/SourceGeneratorPlayground

And I think it is only about time before database libraries or structured loggers (incl. telemetry) will have it as well.

I do **not** believe that F# needs it's own clone of source generators, there are concepts like type providers or Myriad which allow accomplishing similar goals. Therefore I did not continue this as a comment on https://github.com/fsharp/fslang-suggestions/issues/864 , which I believe has different aspirations.

I do want to reopen the discussion from the **.NET library consumption** perspective, especially around libraries/frameworks that are massively backed and invested in (like aspnetcore), and are expensive to replicate and part of the big performance wins.
F# is " | Succinct, robust and performant language for .NET" and the ability to consume the fastest of .NET's libraries IMO comes with this motto.

The latest resolution I could find on the topic is "use C# project" https://github.com/fsharp/fslang-suggestions/issues/864#issuecomment-903267638 , which makes sense in the short term (< 3 years) perspective.

However, the broader the usage of C# code gen in well established libraries, the more slices would have to be done in a project to separate the F# pieces (where F# programmers wants to write) and C# parts (simply due to libraries needing that). Important to note that it might spread multiple layers of the application, and therefore isn't just "1 F# and 1C# project", but rather an interleaved sandwich depending on the level of the stack a library is targeting. The cognitive complexity of seeing a project (which turned into a solution by now) like this is objectively bigger and the typical display by Solution Explorer does not make the dependency order visible at a first glance.

Which brings me to the tooling topic - what can we do better in order to support a smooth workflow using such libraries in a project that would want to be F#-only otherwise.

There is an older suggestion about mixed projects https://github.com/fsharp/fslang-suggestions/issues/117 , which was correctly resolved as being a tooling issue and not a change to F# language itself.

My current view is that the **user-facing side of this feature could look like embedding a single standalone C# file into middle of a F# project**.
That C# file would have access to all project/package dependencies (this is where the source gen stuff is), F# files before it, NOT the files after it ;; and would be only accessible by F# files coming after it.
If this eliminates any worries, I think this would be handy even if always restricted to 1-C#-file scenarios only.

From the IDE side, I could imagine this being a "lightweight project within project", as well as a .cs file being within .fsproj and the F# compiler knowing to split the project into multiple compilation units, invoke Roslyn underneath and putting the results together in the right order.

I will wait for someone more knowledgeable to assess if merging the produced C# & F# ILs together is even a theoretical thought, or it if this would have to be independent .dlls on the output.

This is an XXL item

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.